[ Index ]
 

Code source de CMS made simple 1.0.5

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/lib/adodb_lite/ -> adodb-xmlschema.inc.php (source)

   1  <?php
   2  // Copyright (c) 2004 ars Cognita Inc., all rights reserved
   3  /* ******************************************************************************
   4      Released under both BSD license and Lesser GPL library license. 
   5       Whenever there is any discrepancy between the two licenses, 
   6       the BSD license will take precedence. 
   7  *******************************************************************************/
   8  /**
   9   * xmlschema is a class that allows the user to quickly and easily
  10   * build a database on any ADOdb-supported platform using a simple
  11   * XML schema.
  12   *
  13   * Last Editor: $Author: Mark Dickenson $
  14   * @author Richard Tango-Lowy & Dan Cech
  15   * @version $Revision: 1.13 $
  16   *
  17   * @package axmls
  18   * @tutorial getting_started.pkg
  19   */
  20  
  21  /**
  22  * Debug on or off
  23  */
  24  if( !defined( 'XMLS_DEBUG' ) ) {
  25      define( 'XMLS_DEBUG', FALSE );
  26  }
  27  
  28  /**
  29  * Default prefix key
  30  */
  31  if( !defined( 'XMLS_PREFIX' ) ) {
  32      define( 'XMLS_PREFIX', '%%P' );
  33  }
  34  
  35  /**
  36  * Maximum length allowed for object prefix
  37  */
  38  if( !defined( 'XMLS_PREFIX_MAXLEN' ) ) {
  39      define( 'XMLS_PREFIX_MAXLEN', 10 );
  40  }
  41  
  42  /**
  43  * Execute SQL inline as it is generated
  44  */
  45  if( !defined( 'XMLS_EXECUTE_INLINE' ) ) {
  46      define( 'XMLS_EXECUTE_INLINE', FALSE );
  47  }
  48  
  49  /**
  50  * Continue SQL Execution if an error occurs?
  51  */
  52  if( !defined( 'XMLS_CONTINUE_ON_ERROR' ) ) {
  53      define( 'XMLS_CONTINUE_ON_ERROR', FALSE );
  54  }
  55  
  56  /**
  57  * Current Schema Version
  58  */
  59  if( !defined( 'XMLS_SCHEMA_VERSION' ) ) {
  60      define( 'XMLS_SCHEMA_VERSION', '0.2' );
  61  }
  62  
  63  /**
  64  * Default Schema Version.  Used for Schemas without an explicit version set.
  65  */
  66  if( !defined( 'XMLS_DEFAULT_SCHEMA_VERSION' ) ) {
  67      define( 'XMLS_DEFAULT_SCHEMA_VERSION', '0.1' );
  68  }
  69  
  70  /**
  71  * Default Schema Version.  Used for Schemas without an explicit version set.
  72  */
  73  if( !defined( 'XMLS_DEFAULT_UPGRADE_METHOD' ) ) {
  74      define( 'XMLS_DEFAULT_UPGRADE_METHOD', 'ALTER' );
  75  }
  76  
  77  /**
  78  * Include the main ADODB library
  79  */
  80  if( !defined( '_ADODB_LAYER' ) ) {
  81      include_once ( 'adodb.inc.php' );
  82      include_once ( 'adodb-datadict.inc.php' );
  83  }
  84  
  85  /**
  86  * Abstract DB Object. This class provides basic methods for database objects, such
  87  * as tables and indexes.
  88  *
  89  * @package axmls
  90  * @access private
  91  */
  92  class dbObject {
  93      
  94      /**
  95      * var object Parent
  96      */
  97      var $parent;
  98      
  99      /**
 100      * var string current element
 101      */
 102      var $currentElement;
 103      
 104      /**
 105      * NOP
 106      */
 107  	function dbObject( &$parent, $attributes = NULL ) {
 108          $this->parent =& $parent;
 109      }
 110      
 111      /**
 112      * XML Callback to process start elements
 113      *
 114      * @access private
 115      */
 116  	function _tag_open( &$parser, $tag, $attributes ) {
 117          
 118      }
 119      
 120      /**
 121      * XML Callback to process CDATA elements
 122      *
 123      * @access private
 124      */
 125  	function _tag_cdata( &$parser, $cdata ) {
 126          
 127      }
 128      
 129      /**
 130      * XML Callback to process end elements
 131      *
 132      * @access private
 133      */
 134  	function _tag_close( &$parser, $tag ) {
 135          
 136      }
 137      
 138  	function create() {
 139          return array();
 140      }
 141      
 142      /**
 143      * Destroys the object
 144      */
 145  	function destroy() {
 146          unset( $this );
 147      }
 148      
 149      /**
 150      * Checks whether the specified RDBMS is supported by the current
 151      * database object or its ranking ancestor.
 152      *
 153      * @param string $platform RDBMS platform name (from ADODB platform list).
 154      * @return boolean TRUE if RDBMS is supported; otherwise returns FALSE.
 155      */
 156  	function supportedPlatform( $platform = NULL ) {
 157          return is_object( $this->parent ) ? $this->parent->supportedPlatform( $platform ) : TRUE;
 158      }
 159      
 160      /**
 161      * Returns the prefix set by the ranking ancestor of the database object.
 162      *
 163      * @param string $name Prefix string.
 164      * @return string Prefix.
 165      */
 166  	function prefix( $name = '' ) {
 167          return is_object( $this->parent ) ? $this->parent->prefix( $name ) : $name;
 168      }
 169      
 170      /**
 171      * Extracts a field ID from the specified field.
 172      *
 173      * @param string $field Field.
 174      * @return string Field ID.
 175      */
 176  	function FieldID( $field ) {
 177          return strtoupper( preg_replace( '/^`(.+)`$/', '$1', $field ) );
 178      }
 179  }
 180  
 181  /**
 182  * Creates a table object in ADOdb's datadict format
 183  *
 184  * This class stores information about a database table. As charactaristics
 185  * of the table are loaded from the external source, methods and properties
 186  * of this class are used to build up the table description in ADOdb's
 187  * datadict format.
 188  *
 189  * @package axmls
 190  * @access private
 191  */
 192  class dbTable extends dbObject {
 193      
 194      /**
 195      * @var string Table name
 196      */
 197      var $name;
 198      
 199      /**
 200      * @var array Field specifier: Meta-information about each field
 201      */
 202      var $fields = array();
 203      
 204      /**
 205      * @var array List of table indexes.
 206      */
 207      var $indexes = array();
 208      
 209      /**
 210      * @var array Table options: Table-level options
 211      */
 212      var $opts = array();
 213      
 214      /**
 215      * @var string Field index: Keeps track of which field is currently being processed
 216      */
 217      var $current_field;
 218      
 219      /**
 220      * @var boolean Mark table for destruction
 221      * @access private
 222      */
 223      var $drop_table;
 224      
 225      /**
 226      * @var boolean Mark field for destruction (not yet implemented)
 227      * @access private
 228      */
 229      var $drop_field = array();
 230      
 231      /**
 232      * Iniitializes a new table object.
 233      *
 234      * @param string $prefix DB Object prefix
 235      * @param array $attributes Array of table attributes.
 236      */
 237  	function dbTable( &$parent, $attributes = NULL ) {
 238          $this->parent =& $parent;
 239          $this->name = $this->prefix($attributes['NAME']);
 240      }
 241      
 242      /**
 243      * XML Callback to process start elements. Elements currently 
 244      * processed are: INDEX, DROP, FIELD, KEY, NOTNULL, AUTOINCREMENT & DEFAULT. 
 245      *
 246      * @access private
 247      */
 248  	function _tag_open( &$parser, $tag, $attributes ) {
 249          $this->currentElement = strtoupper( $tag );
 250          
 251          switch( $this->currentElement ) {
 252              case 'INDEX':
 253                  if( !isset( $attributes['PLATFORM'] ) OR $this->supportedPlatform( $attributes['PLATFORM'] ) ) {
 254                      xml_set_object( $parser, $this->addIndex( $attributes ) );
 255                  }
 256                  break;
 257              case 'DATA':
 258                  if( !isset( $attributes['PLATFORM'] ) OR $this->supportedPlatform( $attributes['PLATFORM'] ) ) {
 259                      xml_set_object( $parser, $this->addData( $attributes ) );
 260                  }
 261                  break;
 262              case 'DROP':
 263                  $this->drop();
 264                  break;
 265              case 'FIELD':
 266                  // Add a field
 267                  $fieldName = $attributes['NAME'];
 268                  $fieldType = $attributes['TYPE'];
 269                  $fieldSize = isset( $attributes['SIZE'] ) ? $attributes['SIZE'] : NULL;
 270                  $fieldOpts = isset( $attributes['OPTS'] ) ? $attributes['OPTS'] : NULL;
 271                  
 272                  $this->addField( $fieldName, $fieldType, $fieldSize, $fieldOpts );
 273                  break;
 274              case 'KEY':
 275              case 'NOTNULL':
 276              case 'AUTOINCREMENT':
 277                  // Add a field option
 278                  $this->addFieldOpt( $this->current_field, $this->currentElement );
 279                  break;
 280              case 'DEFAULT':
 281                  // Add a field option to the table object
 282                  
 283                  // Work around ADOdb datadict issue that misinterprets empty strings.
 284                  if( $attributes['VALUE'] == '' ) {
 285                      $attributes['VALUE'] = " '' ";
 286                  }
 287                  
 288                  $this->addFieldOpt( $this->current_field, $this->currentElement, $attributes['VALUE'] );
 289                  break;
 290              case 'DEFDATE':
 291              case 'DEFTIMESTAMP':
 292                  // Add a field option to the table object
 293                  $this->addFieldOpt( $this->current_field, $this->currentElement );
 294                  break;
 295              default:
 296                  // print_r( array( $tag, $attributes ) );
 297          }
 298      }
 299      
 300      /**
 301      * XML Callback to process CDATA elements
 302      *
 303      * @access private
 304      */
 305  	function _tag_cdata( &$parser, $cdata ) {
 306          switch( $this->currentElement ) {
 307              // Table constraint
 308              case 'CONSTRAINT':
 309                  if( isset( $this->current_field ) ) {
 310                      $this->addFieldOpt( $this->current_field, $this->currentElement, $cdata );
 311                  } else {
 312                      $this->addTableOpt( $cdata );
 313                  }
 314                  break;
 315              // Table option
 316              case 'OPT':
 317                  $this->addTableOpt( $cdata );
 318                  break;
 319              default:
 320                  
 321          }
 322      }
 323      
 324      /**
 325      * XML Callback to process end elements
 326      *
 327      * @access private
 328      */
 329  	function _tag_close( &$parser, $tag ) {
 330          $this->currentElement = '';
 331          
 332          switch( strtoupper( $tag ) ) {
 333              case 'TABLE':
 334                  $this->parent->addSQL( $this->create( $this->parent ) );
 335                  xml_set_object( $parser, $this->parent );
 336                  $this->destroy();
 337                  break;
 338              case 'FIELD':
 339                  unset($this->current_field);
 340                  break;
 341  
 342          }
 343      }
 344      
 345      /**
 346      * Adds an index to a table object
 347      *
 348      * @param array $attributes Index attributes
 349      * @return object dbIndex object
 350      */
 351      function &addIndex( $attributes ) {
 352          $name = strtoupper( $attributes['NAME'] );
 353          $this->indexes[$name] =& new dbIndex( $this, $attributes );
 354          return $this->indexes[$name];
 355      }
 356      
 357      /**
 358      * Adds data to a table object
 359      *
 360      * @param array $attributes Data attributes
 361      * @return object dbData object
 362      */
 363      function &addData( $attributes ) {
 364          if( !isset( $this->data ) ) {
 365              $this->data =& new dbData( $this, $attributes );
 366          }
 367          return $this->data;
 368      }
 369      
 370      /**
 371      * Adds a field to a table object
 372      *
 373      * $name is the name of the table to which the field should be added. 
 374      * $type is an ADODB datadict field type. The following field types
 375      * are supported as of ADODB 3.40:
 376      *     - C:  varchar
 377      *    - X:  CLOB (character large object) or largest varchar size
 378      *       if CLOB is not supported
 379      *    - C2: Multibyte varchar
 380      *    - X2: Multibyte CLOB
 381      *    - B:  BLOB (binary large object)
 382      *    - D:  Date (some databases do not support this, and we return a datetime type)
 383      *    - T:  Datetime or Timestamp
 384      *    - L:  Integer field suitable for storing booleans (0 or 1)
 385      *    - I:  Integer (mapped to I4)
 386      *    - I1: 1-byte integer
 387      *    - I2: 2-byte integer
 388      *    - I4: 4-byte integer
 389      *    - I8: 8-byte integer
 390      *    - F:  Floating point number
 391      *    - N:  Numeric or decimal number
 392      *
 393      * @param string $name Name of the table to which the field will be added.
 394      * @param string $type    ADODB datadict field type.
 395      * @param string $size    Field size
 396      * @param array $opts    Field options array
 397      * @return array Field specifier array
 398      */
 399  	function addField( $name, $type, $size = NULL, $opts = NULL ) {
 400          $field_id = $this->FieldID( $name );
 401          
 402          // Set the field index so we know where we are
 403          $this->current_field = $field_id;
 404          
 405          // Set the field name (required)
 406          $this->fields[$field_id]['NAME'] = $name;
 407          
 408          // Set the field type (required)
 409          $this->fields[$field_id]['TYPE'] = $type;
 410          
 411          // Set the field size (optional)
 412          if( isset( $size ) ) {
 413              $this->fields[$field_id]['SIZE'] = $size;
 414          }
 415          
 416          // Set the field options
 417          if( isset( $opts ) ) {
 418              $this->fields[$field_id]['OPTS'][] = $opts;
 419          }
 420      }
 421      
 422      /**
 423      * Adds a field option to the current field specifier
 424      *
 425      * This method adds a field option allowed by the ADOdb datadict 
 426      * and appends it to the given field.
 427      *
 428      * @param string $field    Field name
 429      * @param string $opt ADOdb field option
 430      * @param mixed $value Field option value
 431      * @return array Field specifier array
 432      */
 433  	function addFieldOpt( $field, $opt, $value = NULL ) {
 434          if( !isset( $value ) ) {
 435              $this->fields[$this->FieldID( $field )]['OPTS'][] = $opt;
 436          // Add the option and value
 437          } else {
 438              $this->fields[$this->FieldID( $field )]['OPTS'][] = array( $opt => $value );
 439          }
 440      }
 441      
 442      /**
 443      * Adds an option to the table
 444      *
 445      * This method takes a comma-separated list of table-level options
 446      * and appends them to the table object.
 447      *
 448      * @param string $opt Table option
 449      * @return array Options
 450      */
 451  	function addTableOpt( $opt ) {
 452          $this->opts[] = $opt;
 453          
 454          return $this->opts;
 455      }
 456      
 457      /**
 458      * Generates the SQL that will create the table in the database
 459      *
 460      * @param object $xmls adoSchema object
 461      * @return array Array containing table creation SQL
 462      */
 463  	function create( &$xmls ) {
 464          $sql = array();
 465          
 466          // drop any existing indexes
 467          if( is_array( $legacy_indexes = $xmls->dict->MetaIndexes( $this->name ) ) ) {
 468              foreach( $legacy_indexes as $index => $index_details ) {
 469                  $sql[] = $xmls->dict->DropIndexSQL( $index, $this->name );
 470              }
 471          }
 472          
 473          // remove fields to be dropped from table object
 474          foreach( $this->drop_field as $field ) {
 475              unset( $this->fields[$field] );
 476          }
 477          
 478          // if table exists
 479          if( is_array( $legacy_fields = $xmls->dict->MetaColumns( $this->name ) ) ) {
 480              // drop table
 481              if( $this->drop_table ) {
 482                  $sql[] = $xmls->dict->DropTableSQL( $this->name );
 483                  
 484                  return $sql;
 485              }
 486              
 487              // drop any existing fields not in schema
 488              foreach( $legacy_fields as $field_id => $field ) {
 489                  if( !isset( $this->fields[$field_id] ) ) {
 490                      $sql[] = $xmls->dict->DropColumnSQL( $this->name, '`'.$field->name.'`' );
 491                  }
 492              }
 493          // if table doesn't exist
 494          } else {
 495              if( $this->drop_table ) {
 496                  return $sql;
 497              }
 498              
 499              $legacy_fields = array();
 500          }
 501          
 502          // Loop through the field specifier array, building the associative array for the field options
 503          $fldarray = array();
 504          
 505          foreach( $this->fields as $field_id => $finfo ) {
 506              // Set an empty size if it isn't supplied
 507              if( !isset( $finfo['SIZE'] ) ) {
 508                  $finfo['SIZE'] = '';
 509              }
 510              
 511              // Initialize the field array with the type and size
 512              $fldarray[$field_id] = array(
 513                  'NAME' => $finfo['NAME'],
 514                  'TYPE' => $finfo['TYPE'],
 515                  'SIZE' => $finfo['SIZE']
 516              );
 517              
 518              // Loop through the options array and add the field options. 
 519              if( isset( $finfo['OPTS'] ) ) {
 520                  foreach( $finfo['OPTS'] as $opt ) {
 521                      // Option has an argument.
 522                      if( is_array( $opt ) ) {
 523                          $key = key( $opt );
 524                          $value = $opt[key( $opt )];
 525                          @$fldarray[$field_id][$key] .= $value;
 526                      // Option doesn't have arguments
 527                      } else {
 528                          $fldarray[$field_id][$opt] = $opt;
 529                      }
 530                  }
 531              }
 532          }
 533          
 534          if( empty( $legacy_fields ) ) {
 535              // Create the new table
 536              $sql[] = $xmls->dict->CreateTableSQL( $this->name, $fldarray, $this->opts );
 537              logMsg( end( $sql ), 'Generated CreateTableSQL' );
 538          } else {
 539              // Upgrade an existing table
 540              logMsg( "Upgrading {$this->name} using '{$xmls->upgrade}'" );
 541              switch( $xmls->upgrade ) {
 542                  // Use ChangeTableSQL
 543                  case 'ALTER':
 544                      logMsg( 'Generated ChangeTableSQL (ALTERing table)' );
 545                      $sql[] = $xmls->dict->ChangeTableSQL( $this->name, $fldarray, $this->opts );
 546                      break;
 547                  case 'REPLACE':
 548                      logMsg( 'Doing upgrade REPLACE (testing)' );
 549                      $sql[] = $xmls->dict->DropTableSQL( $this->name );
 550                      $sql[] = $xmls->dict->CreateTableSQL( $this->name, $fldarray, $this->opts );
 551                      break;
 552                  // ignore table
 553                  default:
 554                      return array();
 555              }
 556          }
 557          
 558          foreach( $this->indexes as $index ) {
 559              $sql[] = $index->create( $xmls );
 560          }
 561          
 562          if( isset( $this->data ) ) {
 563              $sql[] = $this->data->create( $xmls );
 564          }
 565          
 566          return $sql;
 567      }
 568      
 569      /**
 570      * Marks a field or table for destruction
 571      */
 572  	function drop() {
 573          if( isset( $this->current_field ) ) {
 574              // Drop the current field
 575              logMsg( "Dropping field '{$this->current_field}' from table '{$this->name}'" );
 576              // $this->drop_field[$this->current_field] = $xmls->dict->DropColumnSQL( $this->name, $this->current_field );
 577              $this->drop_field[$this->current_field] = $this->current_field;
 578          } else {
 579              // Drop the current table
 580              logMsg( "Dropping table '{$this->name}'" );
 581              // $this->drop_table = $xmls->dict->DropTableSQL( $this->name );
 582              $this->drop_table = TRUE;
 583          }
 584      }
 585  }
 586  
 587  /**
 588  * Creates an index object in ADOdb's datadict format
 589  *
 590  * This class stores information about a database index. As charactaristics
 591  * of the index are loaded from the external source, methods and properties
 592  * of this class are used to build up the index description in ADOdb's
 593  * datadict format.
 594  *
 595  * @package axmls
 596  * @access private
 597  */
 598  class dbIndex extends dbObject {
 599      
 600      /**
 601      * @var string    Index name
 602      */
 603      var $name;
 604      
 605      /**
 606      * @var array    Index options: Index-level options
 607      */
 608      var $opts = array();
 609      
 610      /**
 611      * @var array    Indexed fields: Table columns included in this index
 612      */
 613      var $columns = array();
 614      
 615      /**
 616      * @var boolean Mark index for destruction
 617      * @access private
 618      */
 619      var $drop = FALSE;
 620      
 621      /**
 622      * Initializes the new dbIndex object.
 623      *
 624      * @param object $parent Parent object
 625      * @param array $attributes Attributes
 626      *
 627      * @internal
 628      */
 629  	function dbIndex( &$parent, $attributes = NULL ) {
 630          $this->parent =& $parent;
 631          
 632          $this->name = $this->prefix ($attributes['NAME']);
 633      }
 634      
 635      /**
 636      * XML Callback to process start elements
 637      *
 638      * Processes XML opening tags. 
 639      * Elements currently processed are: DROP, CLUSTERED, BITMAP, UNIQUE, FULLTEXT & HASH. 
 640      *
 641      * @access private
 642      */
 643  	function _tag_open( &$parser, $tag, $attributes ) {
 644          $this->currentElement = strtoupper( $tag );
 645          
 646          switch( $this->currentElement ) {
 647              case 'DROP':
 648                  $this->drop();
 649                  break;
 650              case 'CLUSTERED':
 651              case 'BITMAP':
 652              case 'UNIQUE':
 653              case 'FULLTEXT':
 654              case 'HASH':
 655                  // Add index Option
 656                  $this->addIndexOpt( $this->currentElement );
 657                  break;
 658              default:
 659                  // print_r( array( $tag, $attributes ) );
 660          }
 661      }
 662      
 663      /**
 664      * XML Callback to process CDATA elements
 665      *
 666      * Processes XML cdata.
 667      *
 668      * @access private
 669      */
 670  	function _tag_cdata( &$parser, $cdata ) {
 671          switch( $this->currentElement ) {
 672              // Index field name
 673              case 'COL':
 674                  $this->addField( $cdata );
 675                  break;
 676              default:
 677                  
 678          }
 679      }
 680      
 681      /**
 682      * XML Callback to process end elements
 683      *
 684      * @access private
 685      */
 686  	function _tag_close( &$parser, $tag ) {
 687          $this->currentElement = '';
 688          
 689          switch( strtoupper( $tag ) ) {
 690              case 'INDEX':
 691                  xml_set_object( $parser, $this->parent );
 692                  break;
 693          }
 694      }
 695      
 696      /**
 697      * Adds a field to the index
 698      *
 699      * @param string $name Field name
 700      * @return string Field list
 701      */
 702  	function addField( $name ) {
 703          $this->columns[$this->FieldID( $name )] = $name;
 704          
 705          // Return the field list
 706          return $this->columns;
 707      }
 708      
 709      /**
 710      * Adds options to the index
 711      *
 712      * @param string $opt Comma-separated list of index options.
 713      * @return string Option list
 714      */
 715  	function addIndexOpt( $opt ) {
 716          $this->opts[] = $opt;
 717          
 718          // Return the options list
 719          return $this->opts;
 720      }
 721      
 722      /**
 723      * Generates the SQL that will create the index in the database
 724      *
 725      * @param object $xmls adoSchema object
 726      * @return array Array containing index creation SQL
 727      */
 728  	function create( &$xmls ) {
 729          if( $this->drop ) {
 730              return NULL;
 731          }
 732          
 733          // eliminate any columns that aren't in the table
 734          foreach( $this->columns as $id => $col ) {
 735              if( !isset( $this->parent->fields[$id] ) ) {
 736                  unset( $this->columns[$id] );
 737              }
 738          }
 739          
 740          return $xmls->dict->CreateIndexSQL( $this->name, $this->parent->name, $this->columns, $this->opts );
 741      }
 742      
 743      /**
 744      * Marks an index for destruction
 745      */
 746  	function drop() {
 747          $this->drop = TRUE;
 748      }
 749  }
 750  
 751  /**
 752  * Creates a data object in ADOdb's datadict format
 753  *
 754  * This class stores information about table data.
 755  *
 756  * @package axmls
 757  * @access private
 758  */
 759  class dbData extends dbObject {
 760      
 761      var $data = array();
 762      
 763      var $row;
 764      
 765      /**
 766      * Initializes the new dbIndex object.
 767      *
 768      * @param object $parent Parent object
 769      * @param array $attributes Attributes
 770      *
 771      * @internal
 772      */
 773  	function dbData( &$parent, $attributes = NULL ) {
 774          $this->parent =& $parent;
 775      }
 776      
 777      /**
 778      * XML Callback to process start elements
 779      *
 780      * Processes XML opening tags. 
 781      * Elements currently processed are: DROP, CLUSTERED, BITMAP, UNIQUE, FULLTEXT & HASH. 
 782      *
 783      * @access private
 784      */
 785  	function _tag_open( &$parser, $tag, $attributes ) {
 786          $this->currentElement = strtoupper( $tag );
 787          
 788          switch( $this->currentElement ) {
 789              case 'ROW':
 790                  $this->row = count( $this->data );
 791                  $this->data[$this->row] = array();
 792                  break;
 793              case 'F':
 794                  $this->addField($attributes);
 795              default:
 796                  // print_r( array( $tag, $attributes ) );
 797          }
 798      }
 799      
 800      /**
 801      * XML Callback to process CDATA elements
 802      *
 803      * Processes XML cdata.
 804      *
 805      * @access private
 806      */
 807  	function _tag_cdata( &$parser, $cdata ) {
 808          switch( $this->currentElement ) {
 809              // Index field name
 810              case 'F':
 811                  $this->addData( $cdata );
 812                  break;
 813              default:
 814                  
 815          }
 816      }
 817      
 818      /**
 819      * XML Callback to process end elements
 820      *
 821      * @access private
 822      */
 823  	function _tag_close( &$parser, $tag ) {
 824          $this->currentElement = '';
 825          
 826          switch( strtoupper( $tag ) ) {
 827              case 'DATA':
 828                  xml_set_object( $parser, $this->parent );
 829                  break;
 830          }
 831      }
 832      
 833      /**
 834      * Adds a field to the index
 835      *
 836      * @param string $name Field name
 837      * @return string Field list
 838      */
 839  	function addField( $attributes ) {
 840          if( isset( $attributes['NAME'] ) ) {
 841              $name = $attributes['NAME'];
 842          } else {
 843              $name = count($this->data[$this->row]);
 844          }
 845          
 846          // Set the field index so we know where we are
 847          $this->current_field = $this->FieldID( $name );
 848      }
 849      
 850      /**
 851      * Adds options to the index
 852      *
 853      * @param string $opt Comma-separated list of index options.
 854      * @return string Option list
 855      */
 856  	function addData( $cdata ) {
 857          if( !isset( $this->data[$this->row] ) ) {
 858              $this->data[$this->row] = array();
 859          }
 860          
 861          if( !isset( $this->data[$this->row][$this->current_field] ) ) {
 862              $this->data[$this->row][$this->current_field] = '';
 863          }
 864          
 865          $this->data[$this->row][$this->current_field] .= $cdata;
 866      }
 867      
 868      /**
 869      * Generates the SQL that will create the index in the database
 870      *
 871      * @param object $xmls adoSchema object
 872      * @return array Array containing index creation SQL
 873      */
 874  	function create( &$xmls ) {
 875          $table = $xmls->dict->TableName($this->parent->name);
 876          $table_field_count = count($this->parent->fields);
 877          $sql = array();
 878          
 879          // eliminate any columns that aren't in the table
 880          foreach( $this->data as $row ) {
 881              $table_fields = $this->parent->fields;
 882              $fields = array();
 883              
 884              foreach( $row as $field_id => $field_data ) {
 885                  if( !array_key_exists( $field_id, $table_fields ) ) {
 886                      if( is_numeric( $field_id ) ) {
 887                          $field_id = reset( array_keys( $table_fields ) );
 888                      } else {
 889                          continue;
 890                      }
 891                  }
 892                  
 893                  $name = $table_fields[$field_id]['NAME'];
 894                  
 895                  switch( $table_fields[$field_id]['TYPE'] ) {
 896                      case 'C':
 897                      case 'C2':
 898                      case 'X':
 899                      case 'X2':
 900                          $fields[$name] = $xmls->db->qstr( $field_data );
 901                          break;
 902                      case 'I':
 903                      case 'I1':
 904                      case 'I2':
 905                      case 'I4':
 906                      case 'I8':
 907                          $fields[$name] = intval($field_data);
 908                          break;
 909                      default:
 910                          $fields[$name] = $field_data;
 911                  }
 912                  
 913                  unset($table_fields[$field_id]);
 914              }
 915              
 916              // check that at least 1 column is specified
 917              if( empty( $fields ) ) {
 918                  continue;
 919              }
 920              
 921              // check that no required columns are missing
 922              if( count( $fields ) < $table_field_count ) {
 923                  foreach( $table_fields as $field ) {
 924                      if (isset( $field['OPTS'] ))
 925                          if( ( in_array( 'NOTNULL', $field['OPTS'] ) || in_array( 'KEY', $field['OPTS'] ) ) && !in_array( 'AUTOINCREMENT', $field['OPTS'] ) ) {
 926                              continue(2);
 927                          }
 928                  }
 929              }
 930              
 931              $sql[] = 'INSERT INTO '. $table .' ('. implode( ',', array_keys( $fields ) ) .') VALUES ('. implode( ',', $fields ) .')';
 932          }
 933          
 934          return $sql;
 935      }
 936  }
 937  
 938  /**
 939  * Creates the SQL to execute a list of provided SQL queries
 940  *
 941  * @package axmls
 942  * @access private
 943  */
 944  class dbQuerySet extends dbObject {
 945      
 946      /**
 947      * @var array    List of SQL queries
 948      */
 949      var $queries = array();
 950      
 951      /**
 952      * @var string    String used to build of a query line by line
 953      */
 954      var $query;
 955      
 956      /**
 957      * @var string    Query prefix key
 958      */
 959      var $prefixKey = '';
 960      
 961      /**
 962      * @var boolean    Auto prefix enable (TRUE)
 963      */
 964      var $prefixMethod = 'AUTO';
 965      
 966      /**
 967      * Initializes the query set.
 968      *
 969      * @param object $parent Parent object
 970      * @param array $attributes Attributes
 971      */
 972  	function dbQuerySet( &$parent, $attributes = NULL ) {
 973          $this->parent =& $parent;
 974              
 975          // Overrides the manual prefix key
 976          if( isset( $attributes['KEY'] ) ) {
 977              $this->prefixKey = $attributes['KEY'];
 978          }
 979          
 980          $prefixMethod = isset( $attributes['PREFIXMETHOD'] ) ? strtoupper( trim( $attributes['PREFIXMETHOD'] ) ) : '';
 981          
 982          // Enables or disables automatic prefix prepending
 983          switch( $prefixMethod ) {
 984              case 'AUTO':
 985                  $this->prefixMethod = 'AUTO';
 986                  break;
 987              case 'MANUAL':
 988                  $this->prefixMethod = 'MANUAL';
 989                  break;
 990              case 'NONE':
 991                  $this->prefixMethod = 'NONE';
 992                  break;
 993          }
 994      }
 995      
 996      /**
 997      * XML Callback to process start elements. Elements currently 
 998      * processed are: QUERY. 
 999      *
1000      * @access private
1001      */
1002  	function _tag_open( &$parser, $tag, $attributes ) {
1003          $this->currentElement = strtoupper( $tag );
1004          
1005          switch( $this->currentElement ) {
1006              case 'QUERY':
1007                  // Create a new query in a SQL queryset.
1008                  // Ignore this query set if a platform is specified and it's different than the 
1009                  // current connection platform.
1010                  if( !isset( $attributes['PLATFORM'] ) OR $this->supportedPlatform( $attributes['PLATFORM'] ) ) {
1011                      $this->newQuery();
1012                  } else {
1013                      $this->discardQuery();
1014                  }
1015                  break;
1016              default:
1017                  // print_r( array( $tag, $attributes ) );
1018          }
1019      }
1020      
1021      /**
1022      * XML Callback to process CDATA elements
1023      */
1024  	function _tag_cdata( &$parser, $cdata ) {
1025          switch( $this->currentElement ) {
1026              // Line of queryset SQL data
1027              case 'QUERY':
1028                  $this->buildQuery( $cdata );
1029                  break;
1030              default:
1031                  
1032          }
1033      }
1034      
1035      /**
1036      * XML Callback to process end elements
1037      *
1038      * @access private
1039      */
1040  	function _tag_close( &$parser, $tag ) {
1041          $this->currentElement = '';
1042          
1043          switch( strtoupper( $tag ) ) {
1044              case 'QUERY':
1045                  // Add the finished query to the open query set.
1046                  $this->addQuery();
1047                  break;
1048              case 'SQL':
1049                  $this->parent->addSQL( $this->create( $this->parent ) );
1050                  xml_set_object( $parser, $this->parent );
1051                  $this->destroy();
1052                  break;
1053              default:
1054                  
1055          }
1056      }
1057      
1058      /**
1059      * Re-initializes the query.
1060      *
1061      * @return boolean TRUE
1062      */
1063  	function newQuery() {
1064          $this->query = '';
1065          
1066          return TRUE;
1067      }
1068      
1069      /**
1070      * Discards the existing query.
1071      *
1072      * @return boolean TRUE
1073      */
1074  	function discardQuery() {
1075          unset( $this->query );
1076          
1077          return TRUE;
1078      }
1079      
1080      /** 
1081      * Appends a line to a query that is being built line by line
1082      *
1083      * @param string $data Line of SQL data or NULL to initialize a new query
1084      * @return string SQL query string.
1085      */
1086  	function buildQuery( $sql = NULL ) {
1087          if( !isset( $this->query ) OR empty( $sql ) ) {
1088              return FALSE;
1089          }
1090          
1091          $this->query .= $sql;
1092          
1093          return $this->query;
1094      }
1095      
1096      /**
1097      * Adds a completed query to the query list
1098      *
1099      * @return string    SQL of added query
1100      */
1101  	function addQuery() {
1102          if( !isset( $this->query ) ) {
1103              return FALSE;
1104          }
1105          
1106          $this->queries[] = $return = trim($this->query);
1107          
1108          unset( $this->query );
1109          
1110          return $return;
1111      }
1112      
1113      /**
1114      * Creates and returns the current query set
1115      *
1116      * @param object $xmls adoSchema object
1117      * @return array Query set
1118      */
1119  	function create( &$xmls ) {
1120          foreach( $this->queries as $id => $query ) {
1121              switch( $this->prefixMethod ) {
1122                  case 'AUTO':
1123                      // Enable auto prefix replacement
1124                      
1125                      // Process object prefix.
1126                      // Evaluate SQL statements to prepend prefix to objects
1127                      $query = $this->prefixQuery( '/^\s*((?is)INSERT\s+(INTO\s+)?)((\w+\s*,?\s*)+)(\s.*$)/', $query, $xmls->objectPrefix );
1128                      $query = $this->prefixQuery( '/^\s*((?is)UPDATE\s+(FROM\s+)?)((\w+\s*,?\s*)+)(\s.*$)/', $query, $xmls->objectPrefix );
1129                      $query = $this->prefixQuery( '/^\s*((?is)DELETE\s+(FROM\s+)?)((\w+\s*,?\s*)+)(\s.*$)/', $query, $xmls->objectPrefix );
1130                      
1131                      // SELECT statements aren't working yet
1132                      #$data = preg_replace( '/(?ias)(^\s*SELECT\s+.*\s+FROM)\s+(\W\s*,?\s*)+((?i)\s+WHERE.*$)/', "\1 $prefix\2 \3", $data );
1133                      
1134                  case 'MANUAL':
1135                      // If prefixKey is set and has a value then we use it to override the default constant XMLS_PREFIX.
1136                      // If prefixKey is not set, we use the default constant XMLS_PREFIX
1137                      if( isset( $this->prefixKey ) AND( $this->prefixKey !== '' ) ) {
1138                          // Enable prefix override
1139                          $query = str_replace( $this->prefixKey, $xmls->objectPrefix, $query );
1140                      } else {
1141                          // Use default replacement
1142                          $query = str_replace( XMLS_PREFIX , $xmls->objectPrefix, $query );
1143                      }
1144              }
1145              
1146              $this->queries[$id] = trim( $query );
1147          }
1148          
1149          // Return the query set array
1150          return $this->queries;
1151      }
1152      
1153      /**
1154      * Rebuilds the query with the prefix attached to any objects
1155      *
1156      * @param string $regex Regex used to add prefix
1157      * @param string $query SQL query string
1158      * @param string $prefix Prefix to be appended to tables, indices, etc.
1159      * @return string Prefixed SQL query string.
1160      */
1161  	function prefixQuery( $regex, $query, $prefix = NULL ) {
1162          if( !isset( $prefix ) ) {
1163              return $query;
1164          }
1165          
1166          if( preg_match( $regex, $query, $match ) ) {
1167              $preamble = $match[1];
1168              $postamble = $match[5];
1169              $objectList = explode( ',', $match[3] );
1170              // $prefix = $prefix . '_';
1171              
1172              $prefixedList = '';
1173              
1174              foreach( $objectList as $object ) {
1175                  if( $prefixedList !== '' ) {
1176                      $prefixedList .= ', ';
1177                  }
1178                  
1179                  $prefixedList .= $prefix . trim( $object );
1180              }
1181              
1182              $query = $preamble . ' ' . $prefixedList . ' ' . $postamble;
1183          }
1184          
1185          return $query;
1186      }
1187  }
1188  
1189  /**
1190  * Loads and parses an XML file, creating an array of "ready-to-run" SQL statements
1191  * 
1192  * This class is used to load and parse the XML file, to create an array of SQL statements
1193  * that can be used to build a database, and to build the database using the SQL array.
1194  *
1195  * @tutorial getting_started.pkg
1196  *
1197  * @author Richard Tango-Lowy & Dan Cech
1198  * @version $Revision: 1.12 $
1199  *
1200  * @package axmls
1201  */
1202  class adoSchema {
1203      
1204      /**
1205      * @var array    Array containing SQL queries to generate all objects
1206      * @access private
1207      */
1208      var $sqlArray;
1209      
1210      /**
1211      * @var object    ADOdb connection object
1212      * @access private
1213      */
1214      var $db;
1215      
1216      /**
1217      * @var object    ADOdb Data Dictionary
1218      * @access private
1219      */
1220      var $dict;
1221      
1222      /**
1223      * @var string Current XML element
1224      * @access private
1225      */
1226      var $currentElement = '';
1227      
1228      /**
1229      * @var string If set (to 'ALTER' or 'REPLACE'), upgrade an existing database
1230      * @access private
1231      */
1232      var $upgrade = '';
1233      
1234      /**
1235      * @var string Optional object prefix
1236      * @access private
1237      */
1238      var $objectPrefix = '';
1239      
1240      /**
1241      * @var long    Original Magic Quotes Runtime value
1242      * @access private
1243      */
1244      var $mgq;
1245      
1246      /**
1247      * @var long    System debug
1248      * @access private
1249      */
1250      var $debug;
1251      
1252      /**
1253      * @var string Regular expression to find schema version
1254      * @access private
1255      */
1256      var $versionRegex = '/<schema.*?( version="([^"]*)")?.*?>/';
1257      
1258      /**
1259      * @var string Current schema version
1260      * @access private
1261      */
1262      var $schemaVersion;
1263      
1264      /**
1265      * @var int    Success of last Schema execution
1266      */
1267      var $success;
1268      
1269      /**
1270      * @var bool    Execute SQL inline as it is generated
1271      */
1272      var $executeInline;
1273      
1274      /**
1275      * @var bool    Continue SQL execution if errors occur
1276      */
1277      var $continueOnError;
1278      
1279      /**
1280      * Creates an adoSchema object
1281      *
1282      * Creating an adoSchema object is the first step in processing an XML schema.
1283      * The only parameter is an ADOdb database connection object, which must already
1284      * have been created.
1285      *
1286      * @param object $db ADOdb database connection object.
1287      */
1288  	function adoSchema( &$db ) {
1289          // Initialize the environment
1290          $this->mgq = get_magic_quotes_runtime();
1291          set_magic_quotes_runtime(0);
1292          
1293          $this->db =& $db;
1294          $this->debug = $this->db->debug;
1295          $this->dict = NewDataDictionary( $this->db );
1296          $this->sqlArray = array();
1297          $this->schemaVersion = XMLS_SCHEMA_VERSION;
1298          $this->executeInline( XMLS_EXECUTE_INLINE );
1299          $this->continueOnError( XMLS_CONTINUE_ON_ERROR );
1300          $this->setUpgradeMethod();
1301      }
1302      
1303      /**
1304      * Sets the method to be used for upgrading an existing database
1305      *
1306      * Use this method to specify how existing database objects should be upgraded.
1307      * The method option can be set to ALTER, REPLACE, BEST, or NONE. ALTER attempts to
1308      * alter each database object directly, REPLACE attempts to rebuild each object
1309      * from scratch, BEST attempts to determine the best upgrade method for each
1310      * object, and NONE disables upgrading.
1311      *
1312      * This method is not yet used by AXMLS, but exists for backward compatibility.
1313      * The ALTER method is automatically assumed when the adoSchema object is
1314      * instantiated; other upgrade methods are not currently supported.
1315      *
1316      * @param string $method Upgrade method (ALTER|REPLACE|BEST|NONE)
1317      * @returns string Upgrade method used
1318      */
1319  	function SetUpgradeMethod( $method = '' ) {
1320          if( !is_string( $method ) ) {
1321              return FALSE;
1322          }
1323          
1324          $method = strtoupper( $method );
1325          
1326          // Handle the upgrade methods
1327          switch( $method ) {
1328              case 'ALTER':
1329                  $this->upgrade = $method;
1330                  break;
1331              case 'REPLACE':
1332                  $this->upgrade = $method;
1333                  break;
1334              case 'BEST':
1335                  $this->upgrade = 'ALTER';
1336                  break;
1337              case 'NONE':
1338                  $this->upgrade = 'NONE';
1339                  break;
1340              default:
1341                  // Use default if no legitimate method is passed.
1342                  $this->upgrade = XMLS_DEFAULT_UPGRADE_METHOD;
1343          }
1344          
1345          return $this->upgrade;
1346      }
1347      
1348      /**
1349      * Enables/disables inline SQL execution.
1350      *
1351      * Call this method to enable or disable inline execution of the schema. If the mode is set to TRUE (inline execution),
1352      * AXMLS applies the SQL to the database immediately as each schema entity is parsed. If the mode
1353      * is set to FALSE (post execution), AXMLS parses the entire schema and you will need to call adoSchema::ExecuteSchema()
1354      * to apply the schema to the database.
1355      *
1356      * @param bool $mode execute
1357      * @return bool current execution mode
1358      *
1359      * @see ParseSchema(), ExecuteSchema()
1360      */
1361  	function ExecuteInline( $mode = NULL ) {
1362          if( is_bool( $mode ) ) {
1363              $this->executeInline = $mode;
1364          }
1365          
1366          return $this->executeInline;
1367      }
1368      
1369      /**
1370      * Enables/disables SQL continue on error.
1371      *
1372      * Call this method to enable or disable continuation of SQL execution if an error occurs.
1373      * If the mode is set to TRUE (continue), AXMLS will continue to apply SQL to the database, even if an error occurs.
1374      * If the mode is set to FALSE (halt), AXMLS will halt execution of generated sql if an error occurs, though parsing
1375      * of the schema will continue.
1376      *
1377      * @param bool $mode execute
1378      * @return bool current continueOnError mode
1379      *
1380      * @see addSQL(), ExecuteSchema()
1381      */
1382  	function ContinueOnError( $mode = NULL ) {
1383          if( is_bool( $mode ) ) {
1384              $this->continueOnError = $mode;
1385          }
1386          
1387          return $this->continueOnError;
1388      }
1389      
1390      /**
1391      * Loads an XML schema from a file and converts it to SQL.
1392      *
1393      * Call this method to load the specified schema (see the DTD for the proper format) from
1394      * the filesystem and generate the SQL necessary to create the database described. 
1395      * @see ParseSchemaString()
1396      *
1397      * @param string $file Name of XML schema file.
1398      * @param bool $returnSchema Return schema rather than parsing.
1399      * @return array Array of SQL queries, ready to execute
1400      */
1401  	function ParseSchema( $filename, $returnSchema = FALSE ) {
1402          return $this->ParseSchemaString( $this->ConvertSchemaFile( $filename ), $returnSchema );
1403      }
1404      
1405      /**
1406      * Loads an XML schema from a file and converts it to SQL.
1407      *
1408      * Call this method to load the specified schema from a file (see the DTD for the proper format) 
1409      * and generate the SQL necessary to create the database described by the schema.
1410      *
1411      * @param string $file Name of XML schema file.
1412      * @param bool $returnSchema Return schema rather than parsing.
1413      * @return array Array of SQL queries, ready to execute.
1414      *
1415      * @deprecated Replaced by adoSchema::ParseSchema() and adoSchema::ParseSchemaString()
1416      * @see ParseSchema(), ParseSchemaString()
1417      */
1418  	function ParseSchemaFile( $filename, $returnSchema = FALSE ) {
1419          // Open the file
1420          if( !($fp = fopen( $filename, 'r' )) ) {
1421              // die( 'Unable to open file' );
1422              return FALSE;
1423          }
1424          
1425          // do version detection here
1426          if( $this->SchemaFileVersion( $filename ) != $this->schemaVersion ) {
1427              return FALSE;
1428          }
1429          
1430          if ( $returnSchema )
1431          {
1432              return $xmlstring;
1433          }
1434          
1435          $this->success = 2;
1436          
1437          $xmlParser = $this->create_parser();
1438          
1439          // Process the file
1440          while( $data = fread( $fp, 4096 ) ) {
1441              if( !xml_parse( $xmlParser, $data, feof( $fp ) ) ) {
1442                  die( sprintf(
1443                      "XML error: %s at line %d",
1444                      xml_error_string( xml_get_error_code( $xmlParser) ),
1445                      xml_get_current_line_number( $xmlParser)
1446                  ) );
1447              }
1448          }
1449          
1450          xml_parser_free( $xmlParser );
1451          
1452          return $this->sqlArray;
1453      }
1454      
1455      /**
1456      * Converts an XML schema string to SQL.
1457      *
1458      * Call this method to parse a string containing an XML schema (see the DTD for the proper format)
1459      * and generate the SQL necessary to create the database described by the schema. 
1460      * @see ParseSchema()
1461      *
1462      * @param string $xmlstring XML schema string.
1463      * @param bool $returnSchema Return schema rather than parsing.
1464      * @return array Array of SQL queries, ready to execute.
1465      */
1466  	function ParseSchemaString( $xmlstring, $returnSchema = FALSE ) {
1467          if( !is_string( $xmlstring ) OR empty( $xmlstring ) ) {
1468              return FALSE;
1469          }
1470          
1471          // do version detection here
1472          if( $this->SchemaStringVersion( $xmlstring ) != $this->schemaVersion ) {
1473              return FALSE;
1474          }
1475          
1476          if ( $returnSchema )
1477          {
1478              return $xmlstring;
1479          }
1480          
1481          $this->success = 2;
1482          
1483          $xmlParser = $this->create_parser();
1484          
1485          if( !xml_parse( $xmlParser, $xmlstring, TRUE ) ) {
1486              die( sprintf(
1487                  "XML error: %s at line %d",
1488                  xml_error_string( xml_get_error_code( $xmlParser) ),
1489                  xml_get_current_line_number( $xmlParser)
1490              ) );
1491          }
1492          
1493          xml_parser_free( $xmlParser );
1494          
1495          return $this->sqlArray;
1496      }
1497      
1498      /**
1499      * Loads an XML schema from a file and converts it to uninstallation SQL.
1500      *
1501      * Call this method to load the specified schema (see the DTD for the proper format) from
1502      * the filesystem and generate the SQL necessary to remove the database described.
1503      * @see RemoveSchemaString()
1504      *
1505      * @param string $file Name of XML schema file.
1506      * @param bool $returnSchema Return schema rather than parsing.
1507      * @return array Array of SQL queries, ready to execute
1508      */
1509  	function RemoveSchema( $filename, $returnSchema = FALSE ) {
1510          return $this->RemoveSchemaString( $this->ConvertSchemaFile( $filename ), $returnSchema );
1511      }
1512      
1513      /**
1514      * Converts an XML schema string to uninstallation SQL.
1515      *
1516      * Call this method to parse a string containing an XML schema (see the DTD for the proper format)
1517      * and generate the SQL necessary to uninstall the database described by the schema. 
1518      * @see RemoveSchema()
1519      *
1520      * @param string $schema XML schema string.
1521      * @param bool $returnSchema Return schema rather than parsing.
1522      * @return array Array of SQL queries, ready to execute.
1523      */
1524  	function RemoveSchemaString( $schema, $returnSchema = FALSE ) {
1525          
1526          // grab current version
1527          if( !( $version = $this->SchemaStringVersion( $schema ) ) ) {
1528              return FALSE;
1529          }
1530          
1531          return $this->ParseSchemaString( $this->TransformSchema( $schema, 'remove-' . $version), $returnSchema );
1532      }
1533      
1534      /**
1535      * Applies the current XML schema to the database (post execution).
1536      *
1537      * Call this method to apply the current schema (generally created by calling 
1538      * ParseSchema() or ParseSchemaString() ) to the database (creating the tables, indexes, 
1539      * and executing other SQL specified in the schema) after parsing.
1540      * @see ParseSchema(), ParseSchemaString(), ExecuteInline()
1541      *
1542      * @param array $sqlArray Array of SQL statements that will be applied rather than
1543      *        the current schema.
1544      * @param boolean $continueOnErr Continue to apply the schema even if an error occurs.
1545      * @returns integer 0 if failure, 1 if errors, 2 if successful.
1546      */
1547  	function ExecuteSchema( $sqlArray = NULL, $continueOnErr =  NULL ) {
1548          if( !is_bool( $continueOnErr ) ) {
1549              $continueOnErr = $this->ContinueOnError();
1550          }
1551          
1552          if( !isset( $sqlArray ) ) {
1553              $sqlArray = $this->sqlArray;
1554          }
1555          
1556          if( !is_array( $sqlArray ) ) {
1557              $this->success = 0;
1558          } else {
1559              $this->success = $this->dict->ExecuteSQLArray( $sqlArray, $continueOnErr );
1560          }
1561          
1562          return $this->success;
1563      }
1564      
1565      /**
1566      * Returns the current SQL array. 
1567      *
1568      * Call this method to fetch the array of SQL queries resulting from 
1569      * ParseSchema() or ParseSchemaString(). 
1570      *
1571      * @param string $format Format: HTML, TEXT, or NONE (PHP array)
1572      * @return array Array of SQL statements or FALSE if an error occurs
1573      */
1574  	function PrintSQL( $format = 'NONE' ) {
1575          return $this->getSQL( $format, $sqlArray );
1576      }
1577      
1578      /**
1579      * Saves the current SQL array to the local filesystem as a list of SQL queries.
1580      *
1581      * Call this method to save the array of SQL queries (generally resulting from a
1582      * parsed XML schema) to the filesystem.
1583      *
1584      * @param string $filename Path and name where the file should be saved.
1585      * @return boolean TRUE if save is successful, else FALSE. 
1586      */
1587  	function SaveSQL( $filename = './schema.sql' ) {
1588          
1589          if( !isset( $sqlArray ) ) {
1590              $sqlArray = $this->sqlArray;
1591          }
1592          if( !isset( $sqlArray ) ) {
1593              return FALSE;
1594          }
1595          
1596          $fp = fopen( $filename, "w" );
1597          
1598          foreach( $sqlArray as $key => $query ) {
1599              fwrite( $fp, $query . ";\n" );
1600          }
1601          fclose( $fp );
1602      }
1603      
1604      /**
1605      * Create an xml parser
1606      *
1607      * @return object PHP XML parser object
1608      *
1609      * @access private
1610      */
1611      function &create_parser() {
1612          // Create the parser
1613          $xmlParser = xml_parser_create();
1614          xml_set_object( $xmlParser, $this );
1615          
1616          // Initialize the XML callback functions
1617          xml_set_element_handler( $xmlParser, '_tag_open', '_tag_close' );
1618          xml_set_character_data_handler( $xmlParser, '_tag_cdata' );
1619          
1620          return $xmlParser;
1621      }
1622      
1623      /**
1624      * XML Callback to process start elements
1625      *
1626      * @access private
1627      */
1628  	function _tag_open( &$parser, $tag, $attributes ) {
1629          switch( strtoupper( $tag ) ) {
1630              case 'TABLE':
1631                  $this->obj = new dbTable( $this, $attributes );
1632                  xml_set_object( $parser, $this->obj );
1633                  break;
1634              case 'SQL':
1635                  if( !isset( $attributes['PLATFORM'] ) OR $this->supportedPlatform( $attributes['PLATFORM'] ) ) {
1636                      $this->obj = new dbQuerySet( $this, $attributes );
1637                      xml_set_object( $parser, $this->obj );
1638                  }
1639                  break;
1640              default:
1641                  // print_r( array( $tag, $attributes ) );
1642          }
1643          
1644      }
1645      
1646      /**
1647      * XML Callback to process CDATA elements
1648      *
1649      * @access private
1650      */
1651  	function _tag_cdata( &$parser, $cdata ) {
1652      }
1653      
1654      /**
1655      * XML Callback to process end elements
1656      *
1657      * @access private
1658      * @internal
1659      */
1660  	function _tag_close( &$parser, $tag ) {
1661          
1662      }
1663      
1664      /**
1665      * Converts an XML schema string to the specified DTD version.
1666      *
1667      * Call this method to convert a string containing an XML schema to a different AXMLS
1668      * DTD version. For instance, to convert a schema created for an pre-1.0 version for 
1669      * AXMLS (DTD version 0.1) to a newer version of the DTD (e.g. 0.2). If no DTD version 
1670      * parameter is specified, the schema will be converted to the current DTD version. 
1671      * If the newFile parameter is provided, the converted schema will be written to the specified
1672      * file.
1673      * @see ConvertSchemaFile()
1674      *
1675      * @param string $schema String containing XML schema that will be converted.
1676      * @param string $newVersion DTD version to convert to.
1677      * @param string $newFile File name of (converted) output file.
1678      * @return string Converted XML schema or FALSE if an error occurs.
1679      */
1680  	function ConvertSchemaString( $schema, $newVersion = NULL, $newFile = NULL ) {
1681          
1682          // grab current version
1683          if( !( $version = $this->SchemaStringVersion( $schema ) ) ) {
1684              return FALSE;
1685          }
1686          
1687          if( !isset ($newVersion) ) {
1688              $newVersion = $this->schemaVersion;
1689          }
1690          
1691          if( $version == $newVersion ) {
1692              $result = $schema;
1693          } else {
1694              $result = $this->TransformSchema( $schema, 'convert-' . $version . '-' . $newVersion);
1695          }
1696          
1697          if( is_string( $result ) AND is_string( $newFile ) AND ( $fp = fopen( $newFile, 'w' ) ) ) {
1698              fwrite( $fp, $result );
1699              fclose( $fp );
1700          }
1701          
1702          return $result;
1703      }
1704      
1705      /**
1706      * Converts an XML schema file to the specified DTD version.
1707      *
1708      * Call this method to convert the specified XML schema file to a different AXMLS
1709      * DTD version. For instance, to convert a schema created for an pre-1.0 version for 
1710      * AXMLS (DTD version 0.1) to a newer version of the DTD (e.g. 0.2). If no DTD version 
1711      * parameter is specified, the schema will be converted to the current DTD version. 
1712      * If the newFile parameter is provided, the converted schema will be written to the specified
1713      * file.
1714      * @see ConvertSchemaString()
1715      *
1716      * @param string $filename Name of XML schema file that will be converted.
1717      * @param string $newVersion DTD version to convert to.
1718      * @param string $newFile File name of (converted) output file.
1719      * @return string Converted XML schema or FALSE if an error occurs.
1720      */
1721  	function ConvertSchemaFile( $filename, $newVersion = NULL, $newFile = NULL ) {
1722          
1723          // grab current version
1724          if( !( $version = $this->SchemaFileVersion( $filename ) ) ) {
1725              return FALSE;
1726          }
1727          
1728          if( !isset ($newVersion) ) {
1729              $newVersion = $this->schemaVersion;
1730          }
1731          
1732          if( $version == $newVersion ) {
1733              $result = implode('', file( $filename ));
1734              
1735              // remove unicode BOM if present
1736              if( substr( $result, 0, 3 ) == sprintf( '%c%c%c', 239, 187, 191 ) ) {
1737                  $result = substr( $result, 3 );
1738              }
1739          } else {
1740              $result = $this->TransformSchema( $filename, 'convert-' . $version . '-' . $newVersion, 'file' );
1741          }
1742          
1743          if( is_string( $result ) AND is_string( $newFile ) AND ( $fp = fopen( $newFile, 'w' ) ) ) {
1744              fwrite( $fp, $result );
1745              fclose( $fp );
1746          }
1747          
1748          return $result;
1749      }
1750      
1751  	function TransformSchema( $schema, $xsl, $schematype='string' )
1752      {
1753          // Fail if XSLT extension is not available
1754          if( ! function_exists( 'xslt_create' ) ) {
1755              return FALSE;
1756          }
1757          
1758          $xsl_file = dirname( __FILE__ ) . '/xsl/' . $xsl . '.xsl';
1759          
1760          // look for xsl
1761          if( !is_readable( $xsl_file ) ) {
1762              return FALSE;
1763          }
1764          
1765          switch( $schematype )
1766          {
1767              case 'file':
1768                  if( !is_readable( $schema ) ) {
1769                      return FALSE;
1770                  }
1771                  
1772                  $schema = implode('', file( $schema ));
1773                  break;
1774              case 'string':
1775              default:
1776                  if( !is_string( $schema ) ) {
1777                      return FALSE;
1778                  }
1779          }
1780          
1781          $arguments = array (
1782              '/_xml' => $schema,
1783              '/_xsl' => implode('', file(  $xsl_file ))
1784          );
1785          
1786          // create an XSLT processor
1787          $xh = xslt_create ();
1788          
1789          // set error handler
1790          xslt_set_error_handler ($xh, array (&$this, 'xslt_error_handler'));
1791          
1792          // process the schema
1793          $result = xslt_process ($xh, 'arg:/_xml', 'arg:/_xsl', NULL, $arguments); 
1794          
1795          xslt_free ($xh);
1796          
1797          return $result;
1798      }
1799      
1800      /**
1801      * Processes XSLT transformation errors
1802      *
1803      * @param object $parser XML parser object
1804      * @param integer $errno Error number
1805      * @param integer $level Error level
1806      * @param array $fields Error information fields
1807      *
1808      * @access private
1809      */
1810  	function xslt_error_handler( $parser, $errno, $level, $fields ) {
1811          if( is_array( $fields ) ) {
1812              $msg = array(
1813                  'Message Type' => ucfirst( $fields['msgtype'] ),
1814                  'Message Code' => $fields['code'],
1815                  'Message' => $fields['msg'],
1816                  'Error Number' => $errno,
1817                  'Level' => $level
1818              );
1819              
1820              switch( $fields['URI'] ) {
1821                  case 'arg:/_xml':
1822                      $msg['Input'] = 'XML';
1823                      break;
1824                  case 'arg:/_xsl':
1825                      $msg['Input'] = 'XSL';
1826                      break;
1827                  default:
1828                      $msg['Input'] = $fields['URI'];
1829              }
1830              
1831              $msg['Line'] = $fields['line'];
1832          } else {
1833              $msg = array(
1834                  'Message Type' => 'Error',
1835                  'Error Number' => $errno,
1836                  'Level' => $level,
1837                  'Fields' => var_export( $fields, TRUE )
1838              );
1839          }
1840          
1841          $error_details = $msg['Message Type'] . ' in XSLT Transformation' . "\n"
1842                         . '<table>' . "\n";
1843          
1844          foreach( $msg as $label => $details ) {
1845              $error_details .= '<tr><td><b>' . $label . ': </b></td><td>' . htmlentities( $details ) . '</td></tr>' . "\n";
1846          }
1847          
1848          $error_details .= '</table>';
1849          
1850          trigger_error( $error_details, E_USER_ERROR );
1851      }
1852      
1853      /**
1854      * Returns the AXMLS Schema Version of the requested XML schema file.
1855      *
1856      * Call this method to obtain the AXMLS DTD version of the requested XML schema file.
1857      * @see SchemaStringVersion()
1858      *
1859      * @param string $filename AXMLS schema file
1860      * @return string Schema version number or FALSE on error
1861      */
1862  	function SchemaFileVersion( $filename ) {
1863          // Open the file
1864          if( !($fp = fopen( $filename, 'r' )) ) {
1865              // die( 'Unable to open file' );
1866              return FALSE;
1867          }
1868          
1869          // Process the file
1870          while( $data = fread( $fp, 4096 ) ) {
1871              if( preg_match( $this->versionRegex, $data, $matches ) ) {
1872                  return !empty( $matches[2] ) ? $matches[2] : XMLS_DEFAULT_SCHEMA_VERSION;
1873              }
1874          }
1875          
1876          return FALSE;
1877      }
1878      
1879      /**
1880      * Returns the AXMLS Schema Version of the provided XML schema string.
1881      *
1882      * Call this method to obtain the AXMLS DTD version of the provided XML schema string.
1883      * @see SchemaFileVersion()
1884      *
1885      * @param string $xmlstring XML schema string
1886      * @return string Schema version number or FALSE on error
1887      */
1888  	function SchemaStringVersion( $xmlstring ) {
1889          if( !is_string( $xmlstring ) OR empty( $xmlstring ) ) {
1890              return FALSE;
1891          }
1892          
1893          if( preg_match( $this->versionRegex, $xmlstring, $matches ) ) {
1894              return !empty( $matches[2] ) ? $matches[2] : XMLS_DEFAULT_SCHEMA_VERSION;
1895          }
1896          
1897          return FALSE;
1898      }
1899      
1900      /**
1901      * Extracts an XML schema from an existing database.
1902      *
1903      * Call this method to create an XML schema string from an existing database.
1904      * If the data parameter is set to TRUE, AXMLS will include the data from the database
1905      * in the schema. 
1906      *
1907      * @param boolean $data Include data in schema dump
1908      * @return string Generated XML schema
1909      */
1910  	function ExtractSchema( $data = FALSE, $sep_tables = FALSE ) {
1911          $old_mode = $this->db->SetFetchMode( ADODB_FETCH_NUM );
1912          
1913          if($sep_tables)
1914          {
1915              $xml_table_array = array();
1916              $schema_header = '<?xml version="1.0"?>' . "\n"
1917                      . '<schema version="' . $this->schemaVersion . '">' . "\n";
1918              $schema_footer .= '</schema>';
1919          }
1920          
1921          $schema = '<?xml version="1.0"?>' . "\n"
1922                  . '<schema version="' . $this->schemaVersion . '">' . "\n";
1923          
1924          if( is_array( $tables = $this->dict->MetaTables( 'TABLES' ) ) ) {
1925              foreach( $tables as $table ) {
1926                  $schema_temp = '    <table name="' . $table . '">' . "\n";
1927                  
1928                  // grab details from database
1929                  $rs = $this->db->Execute( 'SELECT * FROM ' . $table . ' WHERE 1=1' );
1930                  $fields = $this->dict->MetaColumns( $table );
1931                  $indexes = $this->dict->MetaIndexes( $table );
1932                  
1933                  if( is_array( $fields ) ) {
1934                      foreach( $fields as $details ) {
1935                          $extra = '';
1936                          $content = array();
1937                          
1938                          if( $details->max_length > 0 ) {
1939                              $extra .= ' size="' . $details->max_length . '"';
1940                          }
1941                          
1942                          if( $details->primary_key ) {
1943                              $content[] = '<KEY/>';
1944                          } elseif( $details->not_null ) {
1945                              $content[] = '<NOTNULL/>';
1946                          }
1947                          
1948                          if( $details->has_default ) {
1949                              $content[] = '<DEFAULT value="' . $details->default_value . '"/>';
1950                          }
1951                          
1952                          if( $details->auto_increment ) {
1953                              $content[] = '<AUTOINCREMENT/>';
1954                          }
1955                          
1956                          // this stops the creation of 'R' columns,
1957                          // AUTOINCREMENT is used to create auto columns
1958                          $details->primary_key = 0;
1959                          //$type = $rs->MetaType( $details );
1960                          $type = $this->dict->MetaType($details);
1961                          
1962                          $schema_temp .= '        <field name="' . $details->name . '" type="' . $type . '"' . $extra . '>';
1963                          
1964                          if( !empty( $content ) ) {
1965                              $schema_temp .= "\n            " . implode( "\n            ", $content ) . "\n        ";
1966                          }
1967                          
1968                          $schema_temp .= '</field>' . "\n";
1969                      }
1970                  }
1971                  
1972                  if( is_array( $indexes ) ) {
1973                      foreach( $indexes as $index => $details ) {
1974                          $schema_temp .= '        <index name="' . $index . '">' . "\n";
1975                          
1976                          if( $details['unique'] ) {
1977                              $schema_temp .= '            <UNIQUE/>' . "\n";
1978                          }
1979                          
1980                          foreach( $details['columns'] as $column ) {
1981                              $schema_temp .= '            <col>' . $column . '</col>' . "\n";
1982                          }
1983                          
1984                          $schema_temp .= '        </index>' . "\n";
1985                      }
1986                  }
1987                  
1988                  if( $data ) {
1989                      $rs = $this->db->Execute( 'SELECT * FROM ' . $table );
1990                      
1991                      if( is_object( $rs ) ) {
1992                          $schema_temp .= '        <data>' . "\n";
1993                          
1994                          while(!$rs->EOF)
1995                          {
1996                              $row = $rs->fields;
1997                              
1998                              foreach( $row as $key => $val )
1999                              {
2000                                  $row[$key] = htmlentities($val);
2001                              }
2002                              
2003                              $schema_temp .= '            <row><f>' . implode( '</f><f>', $row ) . '</f></row>' . "\n";
2004                              $rs->MoveNext();
2005                          }
2006                          
2007                          $schema_temp .= '        </data>' . "\n";
2008                      }
2009                  }
2010                  
2011                  $schema_temp .= '    </table>' . "\n";
2012                  $schema .= $schema_temp;
2013                  $xml_table_array[] = $schema_header . $schema_temp . $schema_footer;
2014              }
2015          }
2016          
2017          $this->db->SetFetchMode( $old_mode );
2018          
2019          $schema .= '</schema>';
2020          if($sep_tables)
2021          {
2022              return $xml_table_array;
2023          }
2024          else
2025          {
2026              return $schema;
2027          }
2028      }
2029      
2030  
2031  	function ExtractTableSchema($tables, $data = FALSE )
2032      {
2033          $schema = '<?xml version="1.0"?>' . "\n"
2034                  . '<schema version="' . $this->schemaVersion . '">' . "\n";
2035  
2036          if(is_array($tables))
2037          {
2038              foreach($tables as $table)
2039              {
2040                  $schema .= $this->_ExtractTableSchema($table,$data);
2041              }
2042          }
2043          else
2044          {
2045              $schema .= $this->_ExtractTableSchema($tables,$data);
2046          }
2047  
2048          $schema .= '</schema>';
2049          return $schema;
2050  
2051      }
2052  	function _ExtractTableSchema($table, $data = FALSE )
2053      {
2054          $old_mode = $this->db->SetFetchMode( ADODB_FETCH_NUM );
2055          $schema = "";
2056  
2057                  $schema .= '    <table name="' . $table . '">' . "\n";
2058  
2059                  // grab details from database
2060                  $rs = $this->db->Execute( 'SELECT * FROM ' . $table . ' WHERE 1=1' );
2061                  $fields = $this->dict->MetaColumns( $table );
2062                  $indexes = $this->dict->MetaIndexes( $table );
2063  
2064                  if( is_array( $fields ) ) {
2065                      foreach( $fields as $details ) {
2066                          $extra = '';
2067                          $content = array();
2068  
2069                          if( $details->max_length > 0 ) {
2070                              $extra .= ' size="' . $details->max_length . '"';
2071                          }
2072  
2073                          if( $details->primary_key ) {
2074                              $content[] = '<KEY/>';
2075                          } elseif( $details->not_null ) {
2076                              $content[] = '<NOTNULL/>';
2077                          }
2078  
2079                          if( $details->has_default ) {
2080                              $content[] = '<DEFAULT value="' . $details->default_value . '"/>';
2081                          }
2082  
2083                          if( $details->auto_increment ) {
2084                              $content[] = '<AUTOINCREMENT/>';
2085                          }
2086  
2087                          // this stops the creation of 'R' columns,
2088                          // AUTOINCREMENT is used to create auto columns
2089                          $details->primary_key = 0;
2090                          //$type = $rs->MetaType( $details );
2091                          $type = $this->dict->MetaType($details);
2092  
2093                          $schema .= '        <field name="' . $details->name . '" type="' . $type . '"' . $extra . '>';
2094  
2095                          if( !empty( $content ) ) {
2096                              $schema .= "\n            " . implode( "\n            ", $content ) . "\n        ";
2097                          }
2098  
2099                          $schema .= '</field>' . "\n";
2100                      }
2101                  }
2102  
2103                  if( is_array( $indexes ) ) {
2104                      foreach( $indexes as $index => $details ) {
2105                          $schema .= '        <index name="' . $index . '">' . "\n";
2106  
2107                          if( $details['unique'] ) {
2108                              $schema .= '            <UNIQUE/>' . "\n";
2109                          }
2110  
2111                          foreach( $details['columns'] as $column ) {
2112                              $schema .= '            <col>' . $column . '</col>' . "\n";
2113                          }
2114  
2115                          $schema .= '        </index>' . "\n";
2116                      }
2117                  }
2118  
2119                  if( $data ) {
2120                      $rs = $this->db->Execute( 'SELECT * FROM ' . $table );
2121  
2122                      if( is_object( $rs ) ) {
2123                          $schema .= '        <data>' . "\n";
2124  
2125                          while(!$rs->EOF)
2126                          {
2127                              $row = $rs->fields;
2128  
2129                              foreach( $row as $key => $val )
2130                              {
2131                                  $row[$key] = htmlentities($val);
2132                              }
2133  
2134                              $schema .= '            <row><f>' . implode( '</f><f>', $row ) . '</f></row>' . "\n";
2135                              $rs->MoveNext();
2136                          }
2137  
2138                          $schema .= '        </data>' . "\n";
2139                      }
2140                  }
2141  
2142                  $schema .= '    </table>' . "\n";
2143  
2144  
2145  
2146          $this->db->SetFetchMode( $old_mode );
2147          return $schema;
2148      }
2149  
2150      /**
2151      * Sets a prefix for database objects
2152      *
2153      * Call this method to set a standard prefix that will be prepended to all database tables 
2154      * and indices when the schema is parsed. Calling setPrefix with no arguments clears the prefix.
2155      *
2156      * @param string $prefix Prefix that will be prepended.
2157      * @param boolean $underscore If TRUE, automatically append an underscore character to the prefix.
2158      * @return boolean TRUE if successful, else FALSE
2159      */
2160  	function SetPrefix( $prefix = '', $underscore = TRUE ) {
2161          switch( TRUE ) {
2162              // clear prefix
2163              case empty( $prefix ):
2164                  logMsg( 'Cleared prefix' );
2165                  $this->objectPrefix = '';
2166                  return TRUE;
2167              // prefix too long
2168              case strlen( $prefix ) > XMLS_PREFIX_MAXLEN:
2169              // prefix contains invalid characters
2170              case !preg_match( '/^[a-z][a-z0-9_]+$/i', $prefix ):
2171                  logMsg( 'Invalid prefix: ' . $prefix );
2172                  return FALSE;
2173          }
2174          
2175          if( $underscore AND substr( $prefix, -1 ) != '_' ) {
2176              $prefix .= '_';
2177          }
2178          
2179          // prefix valid
2180          logMsg( 'Set prefix: ' . $prefix );
2181          $this->objectPrefix = $prefix;
2182          return TRUE;
2183      }
2184      
2185      /**
2186      * Returns an object name with the current prefix prepended.
2187      *
2188      * @param string    $name Name
2189      * @return string    Prefixed name
2190      *
2191      * @access private
2192      */
2193  	function prefix( $name = '' ) {
2194          // if prefix is set
2195          if( !empty( $this->objectPrefix ) ) {
2196              // Prepend the object prefix to the table name
2197              // prepend after quote if used
2198              return preg_replace( '/^(`?)(.+)$/', '$1' . $this->objectPrefix . '$2', $name );
2199          }
2200          
2201          // No prefix set. Use name provided.
2202          return $name;
2203      }
2204      
2205      /**
2206      * Checks if element references a specific platform
2207      *
2208      * @param string $platform Requested platform
2209      * @returns boolean TRUE if platform check succeeds
2210      *
2211      * @access private
2212      */
2213  	function supportedPlatform( $platform = NULL ) {
2214          $regex = '/^(\w*\|)*' . $this->db->dbtype . '(\|\w*)*$/';
2215          
2216          if( !isset( $platform ) OR preg_match( $regex, $platform ) ) {
2217              logMsg( "Platform $platform is supported" );
2218              return TRUE;
2219          } else {
2220              logMsg( "Platform $platform is NOT supported" );
2221              return FALSE;
2222          }
2223      }
2224      
2225      /**
2226      * Clears the array of generated SQL.
2227      *
2228      * @access private
2229      */
2230  	function clearSQL() {
2231          $this->sqlArray = array();
2232      }
2233      
2234      /**
2235      * Adds SQL into the SQL array.
2236      *
2237      * @param mixed $sql SQL to Add
2238      * @return boolean TRUE if successful, else FALSE.
2239      *
2240      * @access private
2241      */    
2242  	function addSQL( $sql = NULL ) {
2243          if( is_array( $sql ) ) {
2244              foreach( $sql as $line ) {
2245                  $this->addSQL( $line );
2246              }
2247              
2248              return TRUE;
2249          }
2250          
2251          if( is_string( $sql ) ) {
2252              $this->sqlArray[] = $sql;
2253              
2254              // if executeInline is enabled, and either no errors have occurred or continueOnError is enabled, execute SQL.
2255              if( $this->ExecuteInline() && ( $this->success == 2 || $this->ContinueOnError() ) ) {
2256                  $saved = $this->db->debug;
2257                  $this->db->debug = $this->debug;
2258                  $ok = $this->db->Execute( $sql );
2259                  $this->db->debug = $saved;
2260                  
2261                  if( !$ok ) {
2262                      if( $this->debug ) {
2263                          ADOConnection::outp( $this->db->ErrorMsg() );
2264                      }
2265                      
2266                      $this->success = 1;
2267                  }
2268              }
2269              
2270              return TRUE;
2271          }
2272          
2273          return FALSE;
2274      }
2275      
2276      /**
2277      * Gets the SQL array in the specified format.
2278      *
2279      * @param string $format Format
2280      * @return mixed SQL
2281      *    
2282      * @access private
2283      */
2284  	function getSQL( $format = NULL, $sqlArray = NULL ) {
2285          if( !is_array( $sqlArray ) ) {
2286              $sqlArray = $this->sqlArray;
2287          }
2288          
2289          if( !is_array( $sqlArray ) ) {
2290              return FALSE;
2291          }
2292          
2293          switch( strtolower( $format ) ) {
2294              case 'string':
2295              case 'text':
2296                  return !empty( $sqlArray ) ? implode( ";\n\n", $sqlArray ) . ';' : '';
2297              case'html':
2298                  return !empty( $sqlArray ) ? nl2br( htmlentities( implode( ";\n\n", $sqlArray ) . ';' ) ) : '';
2299          }
2300          
2301          return $this->sqlArray;
2302      }
2303      
2304      /**
2305      * Destroys an adoSchema object.
2306      *
2307      * Call this method to clean up after an adoSchema object that is no longer in use.
2308      * @deprecated adoSchema now cleans up automatically.
2309      */
2310  	function Destroy() {
2311          set_magic_quotes_runtime( $this->mgq );
2312          unset( $this );
2313      }
2314  }
2315  
2316  /**
2317  * Message logging function
2318  *
2319  * @access private
2320  */
2321  function logMsg( $msg, $title = NULL, $force = FALSE ) {
2322      if( XMLS_DEBUG or $force ) {
2323          echo '<pre>';
2324          
2325          if( isset( $title ) ) {
2326              echo '<h3>' . htmlentities( $title ) . '</h3>';
2327          }
2328          
2329          if( is_object( $this ) ) {
2330              echo '[' . get_class( $this ) . '] ';
2331          }
2332          
2333          print_r( $msg );
2334          
2335          echo '</pre>';
2336      }
2337  }
2338  ?>


Généré le : Tue Apr 3 18:50:37 2007 par Balluche grâce à PHPXref 0.7