Initial commit on HEAD of all the XMLDB stuff.

This commit is contained in:
stronk7
2006-08-15 09:14:31 +00:00
parent f11bf81701
commit 8165877a17
12 changed files with 4181 additions and 0 deletions
+69
View File
@@ -0,0 +1,69 @@
<?php // $Id$
///////////////////////////////////////////////////////////////////////////
// //
// NOTICE OF COPYRIGHT //
// //
// Moodle - Modular Object-Oriented Dynamic Learning Environment //
// http://moodle.com //
// //
// Copyright (C) 2001-3001 Martin Dougiamas http://dougiamas.com //
// (C) 2001-3001 Eloy Lafuente (stronk7) http://contiento.com //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation; either version 2 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details: //
// //
// http://www.gnu.org/copyleft/gpl.html //
// //
///////////////////////////////////////////////////////////////////////////
/// This file contains all the constants and variables used
/// by the XMLDB interface
/// First, some constants to be used by actions
define('ACTION_NONE', 0); //Default flags for class
define('ACTION_GENERATE_HTML', 1); //The invoke function will return HTML
define('ACTION_GENERATE_XML', 2); //The invoke function will return HTML
define('ACTION_HAVE_SUBACTIONS', 1); //The class can have subaction
/// Now the allowed DB Field Types
define ('XMLDB_TYPE_INCORRECT', 0); //Wrong DB Type
define ('XMLDB_TYPE_INTEGER', 1); //Integer
define ('XMLDB_TYPE_NUMBER', 2); //Decimal number
define ('XMLDB_TYPE_FLOAT', 3); //Floating Point number
define ('XMLDB_TYPE_CHAR', 4); //String
define ('XMLDB_TYPE_TEXT', 5); //Text
define ('XMLDB_TYPE_BINARY', 6); //Binary
define ('XMLDB_TYPE_DATETIME', 7); //Datetime
define ('XMLDB_TYPE_TIMESTAMP', 8); //Timestamp
/// Now the allowed DB Keys
define ('XMLDB_KEY_INCORRECT', 0); //Wrong DB Key
define ('XMLDB_KEY_PRIMARY', 1); //Primary Keys
define ('XMLDB_KEY_UNIQUE', 2); //Unique Keys
define ('XMLDB_KEY_FOREIGN', 3); //Foreign Keys
define ('XMLDB_KEY_CHECK', 4); //Check Constraints - NOT USED!
define ('XMLDB_KEY_FOREIGN_UNIQUE',5); //Foreign Key + Unique Key
/// Now the allowed Statement Types
define ('XMLDB_STATEMENT_INCORRECT', 0); //Wrong Statement Type
define ('XMLDB_STATEMENT_INSERT', 1); //Insert Statements
define ('XMLDB_STATEMENT_UPDATE', 2); //Update Statements
define ('XMLDB_STATEMENT_DELETE', 3); //Delete Statements
define ('XMLDB_STATEMENT_CUSTOM', 4); //Custom Statements
/// Some other useful Constants
define ('XMLDB_UNSIGNED', true); //If the field is going to be unsigned
define ('XMLDB_NOTNULL', true); //If the field is going to be not null
define ('XMLDB_SEQUENCE', true); //If the field is going to be a sequence
define ('XMLDB_ENUM', true); //If the field is going to be a enumeration of possible fields
define ('XMLDB_INDEX_UNIQUE', true); //If the index is going to be unique
define ('XMLDB_INDEX_NOTUNIQUE',false); //If the index is NOT going to be unique
?>
+733
View File
@@ -0,0 +1,733 @@
<?php // $Id$
///////////////////////////////////////////////////////////////////////////
// //
// NOTICE OF COPYRIGHT //
// //
// Moodle - Modular Object-Oriented Dynamic Learning Environment //
// http://moodle.com //
// //
// Copyright (C) 2001-3001 Martin Dougiamas http://dougiamas.com //
// (C) 2001-3001 Eloy Lafuente (stronk7) http://contiento.com //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation; either version 2 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details: //
// //
// http://www.gnu.org/copyleft/gpl.html //
// //
///////////////////////////////////////////////////////////////////////////
/// This class represent one XMLDB Field
class XMLDBField extends XMLDBObject {
var $type;
var $length;
var $unsigned;
var $notnull;
var $default;
var $sequence;
var $enum;
var $enumvalues;
var $decimals;
/**
* Creates one new XMLDBField
*/
function XMLDBField($name) {
parent::XMLDBObject($name);
$this->type = NULL;
$this->length = NULL;
$this->unsigned = false;
$this->notnull = false;
$this->default = NULL;
$this->sequence = false;
$this->enum = false;
$this->enumvalues = NULL;
$this->decimals = NULL;
}
/**
* Get the type
*/
function getType() {
return $this->type;
}
/**
* Get the length
*/
function getLength() {
return $this->length;
}
/**
* Get the decimals
*/
function getDecimals() {
return $this->decimals;
}
/**
* Get the notnull
*/
function getNotNull() {
return $this->notnull;
}
/**
* Get the unsigned
*/
function getUnsigned() {
return $this->unsigned;
}
/**
* Get the sequence
*/
function getSequence() {
return $this->sequence;
}
/**
* Get the enum
*/
function getEnum() {
return $this->enum;
}
/**
* Get the enumvalues
*/
function getEnumValues() {
return $this->enumvalues;
}
/**
* Get the default
*/
function getDefault() {
return $this->default;
}
/**
* Set the field type
*/
function setType($type) {
$this->type = $type;
}
/**
* Set the field length
*/
function setLength($length) {
$this->length = $length;
}
/**
* Set the field decimals
*/
function setDecimals($decimals) {
$this->decimals = $decimals;
}
/**
* Set the field unsigned
*/
function setUnsigned($unsigned=true) {
$this->unsigned = $unsigned;
}
/**
* Set the field notnull
*/
function setNotNull($notnull=true) {
$this->notnull = $notnull;
}
/**
* Set the field sequence
*/
function setSequence($sequence=true) {
$this->sequence = $sequence;
}
/**
* Set the field enum
*/
function setEnum($enum=true) {
$this->enum = $enum;
}
/**
* Set the field enumvalues
*/
function setEnumValues($enumvalues) {
$this->enumvalues = $enumvalues;
}
/**
* Set the field default
*/
function setDefault($default) {
$this->default = $default;
}
/**
* Load data from XML to the table
*/
function arr2XMLDBField($xmlarr) {
$result = true;
/// Debug the table
/// traverse_xmlize($xmlarr); //Debug
/// print_object ($GLOBALS['traverse_array']); //Debug
/// $GLOBALS['traverse_array']=""; //Debug
/// Process table attributes (name, type, length, unsigned,
/// notnull, sequence, enum, enumvalues, decimals, comment,
/// previous, next)
if (isset($xmlarr['@']['NAME'])) {
$this->name = trim($xmlarr['@']['NAME']);
} else {
$this->errormsg = 'Missing NAME attribute';
$result = false;
}
if (isset($xmlarr['@']['TYPE'])) {
/// Check for valid type
$type = $this->getXMLDBFieldType(trim($xmlarr['@']['TYPE']));
if ($type) {
$this->type = $type;
} else {
$this->errormsg = 'Invalid TYPE attribute';
$result = false;
}
} else {
$this->errormsg = 'Missing TYPE attribute';
$result = false;
}
if (isset($xmlarr['@']['LENGTH'])) {
$length = trim($xmlarr['@']['LENGTH']);
/// Check for integer values
if ($this->type == XMLDB_TYPE_INTEGER ||
$this->type == XMLDB_TYPE_NUMBER ||
$this->type == XMLDB_TYPE_CHAR) {
if (!(is_numeric($length)&&(intval($length)==floatval($length)))) {
$this->errormsg = 'Incorrect LENGTH attribute for int, number or char fields';
$result = false;
} else if (!$length) {
$this->errormsg = 'Zero LENGTH attribute';
$result = false;
}
}
/// Check for big, medium, small to be applied to text and binary
if ($this->type == XMLDB_TYPE_TEXT ||
$this->type == XMLDB_TYPE_BINARY) {
if (!$length) {
$length == 'big';
}
if ($length != 'big' &&
$length != 'medium' &&
$length != 'small') {
$this->errormsg = 'Incorrect LENGTH attribute for text and binary fields (only big, medium and small allowed)';
$result = false;
}
}
/// Finally, set the length
$this->length = $length;
}
if (isset($xmlarr['@']['UNSIGNED'])) {
$unsigned = strtolower(trim($xmlarr['@']['UNSIGNED']));
if ($unsigned == 'true') {
$this->unsigned = true;
} else if ($unsigned == 'false') {
$this->unsigned = false;
} else {
$this->errormsg = 'Incorrect UNSIGNED attribute (true/false allowed)';
$result = false;
}
}
if (isset($xmlarr['@']['NOTNULL'])) {
$notnull = strtolower(trim($xmlarr['@']['NOTNULL']));
if ($notnull == 'true') {
$this->notnull = true;
} else if ($notnull == 'false') {
$this->notnull = false;
} else {
$this->errormsg = 'Incorrect NOTNULL attribute (true/false allowed)';
$result = false;
}
}
if (isset($xmlarr['@']['SEQUENCE'])) {
$sequence = strtolower(trim($xmlarr['@']['SEQUENCE']));
if ($sequence == 'true') {
$this->sequence = true;
} else if ($sequence == 'false') {
$this->sequence = false;
} else {
$this->errormsg = 'Incorrect SEQUENCE attribute (true/false allowed)';
$result = false;
}
}
if (isset($xmlarr['@']['DEFAULT'])) {
$this->default = trim($xmlarr['@']['DEFAULT']);
}
if (isset($xmlarr['@']['ENUM'])) {
$enum = strtolower(trim($xmlarr['@']['ENUM']));
if ($enum == 'true') {
$this->enum = true;
} else if ($enum == 'false') {
$this->enum = false;
} else {
$this->errormsg = 'Incorrect ENUM attribute (true/false allowed)';
$result = false;
}
}
if (isset($xmlarr['@']['ENUMVALUES'])) {
$enumvalues = strtolower(trim($xmlarr['@']['ENUMVALUES']));
if (!$this->enum) {
$this->errormsg = 'Wrong ENUMVALUES attribute (not ENUM)';
$result = false;
$this->enumvalues = $enumvalues;
} else {
/// Check we have a valid list (comma separated of quoted values)
$enumarr = explode(',',$enumvalues);
if ($enumarr) {
foreach ($enumarr as $key => $enumelement) {
/// Clear some spaces
$enumarr[$key] = trim($enumelement);
$enumelement = trim($enumelement);
/// Skip if under error
if (!$result) {
continue;
}
/// Look for quoted strings
if (substr($enumelement, 0, 1) != "'" ||
substr($enumelement, -1, 1) != "'") {
$this->errormsg = 'Incorrect ENUMVALUES attribute (some value is not properly quoted)';
$result = false;
}
}
} else {
$this->errormsg = 'Incorrect ENUMVALUES attribute (comma separated of quoted values)';
$result = false;
}
}
} else if ($this->enum) {
$this->errormsg = 'Incorrect ENUMVALUES attribute (field is not declared as ENUM)';
$result = false;
}
/// Finally, set the value
if ($this->enum) {
$this->enumvalues = $enumarr;
}
$decimals = NULL;
if (isset($xmlarr['@']['DECIMALS'])) {
$decimals = trim($xmlarr['@']['DECIMALS']);
/// Check for integer values
if ($this->type == XMLDB_TYPE_NUMBER ||
$this->type == XMLDB_TYPE_FLOAT) {
if (!(is_numeric($decimals)&&(intval($decimals)==floatval($decimals)))) {
$this->errormsg = 'Incorrect DECIMALS attribute for number field';
$result = false;
} else if ($this->length <= $decimals){
$this->errormsg = 'Incorrect DECIMALS attribute (bigget than length)';
$result = false;
}
} else {
$this->errormsg = 'Incorrect DECIMALS attribute for non-number field';
$result = false;
}
} else {
if ($this->type == XMLDB_TYPE_NUMBER) {
$decimals = 0;
}
}
// Finally, set the decimals
if ($this->type == XMLDB_TYPE_NUMBER ||
$this->type == XMLDB_TYPE_FLOAT) {
$this->decimals = $decimals;
}
if (isset($xmlarr['@']['COMMENT'])) {
$this->comment = trim($xmlarr['@']['COMMENT']);
}
if (isset($xmlarr['@']['PREVIOUS'])) {
$this->previous = trim($xmlarr['@']['PREVIOUS']);
}
if (isset($xmlarr['@']['NEXT'])) {
$this->next = trim($xmlarr['@']['NEXT']);
}
/// Set some attributes
if ($result) {
$this->loaded = true;
}
$this->calculateHash();
return $result;
}
/**
* This function returns the correct XMLDB_TYPE_XXX value for the
* string passed as argument
*/
function getXMLDBFieldType($type) {
$result = XMLDB_TYPE_INCORRECT;
switch (strtolower($type)) {
case 'int':
$result = XMLDB_TYPE_INTEGER;
break;
case 'number':
$result = XMLDB_TYPE_NUMBER;
break;
case 'float':
$result = XMLDB_TYPE_FLOAT;
break;
case 'char':
$result = XMLDB_TYPE_CHAR;
break;
case 'text':
$result = XMLDB_TYPE_TEXT;
break;
case 'binary':
$result = XMLDB_TYPE_BINARY;
break;
case 'datetime':
$result = XMLDB_TYPE_DATETIME;
break;
}
/// Return the normalized XMLDB_TYPE
return $result;
}
/**
* This function returns the correct name value for the
* XMLDB_TYPE_XXX passed as argument
*/
function getXMLDBTypeName($type) {
$result = "";
switch (strtolower($type)) {
case XMLDB_TYPE_INTEGER:
$result = 'int';
break;
case XMLDB_TYPE_NUMBER:
$result = 'number';
break;
case XMLDB_TYPE_FLOAT:
$result = 'float';
break;
case XMLDB_TYPE_CHAR:
$result = 'char';
break;
case XMLDB_TYPE_TEXT:
$result = 'text';
break;
case XMLDB_TYPE_BINARY:
$result = 'binary';
break;
case XMLDB_TYPE_DATETIME:
$result = 'datetime';
break;
}
/// Return the normalized name
return $result;
}
/**
* This function calculate and set the hash of one XMLDBField
*/
function calculateHash($recursive = false) {
if (!$this->loaded) {
$this->hash = NULL;
} else {
$key = $this->name . $this->type . $this->length .
$this->unsigned . $this->notnull . $this->sequence .
$this->decimals . $this->comment;
if ($this->enum) {
$key .= implode(', ',$this->enumvalues);
}
$this->hash = md5($key);
}
}
/**
*This function will output the XML text for one field
*/
function xmlOutput() {
$o = '';
$o.= ' <FIELD NAME="' . $this->name . '"';
$o.= ' TYPE="' . $this->getXMLDBTypeName($this->type) . '"';
if ($this->length) {
$o.= ' LENGTH="' . $this->length . '"';
}
if ($this->notnull) {
$notnull = 'true';
} else {
$notnull = 'false';
}
$o.= ' NOTNULL="' . $notnull . '"';
if ($this->unsigned) {
$unsigned = 'true';
} else {
$unsigned = 'false';
}
if ($this->type == XMLDB_TYPE_INTEGER ||
$this->type == XMLDB_TYPE_NUMBER ||
$this->type == XMLDB_TYPE_FLOAT) {
if ($this->unsigned) {
$unsigned = 'true';
} else {
$unsigned = 'false';
}
$o.= ' UNSIGNED="' . $unsigned . '"';
}
if (!$this->sequence && $this->default !== NULL) {
$o.= ' DEFAULT="' . $this->default . '"';
}
if ($this->sequence) {
$sequence = 'true';
} else {
$sequence = 'false';
}
$o.= ' SEQUENCE="' . $sequence . '"';
if ($this->enum) {
$enum = 'true';
} else {
$enum = 'false';
}
$o.= ' ENUM="' . $enum . '"';
if ($this->enum) {
$o.= ' ENUMVALUES="' . implode(', ', $this->enumvalues) . '"';
}
if ($this->decimals !== NULL) {
$o.= ' DECIMALS="' . $this->decimals . '"';
}
if ($this->comment) {
$o.= ' COMMENT="' . htmlspecialchars($this->comment) . '"';
}
if ($this->previous) {
$o.= ' PREVIOUS="' . $this->previous . '"';
}
if ($this->next) {
$o.= ' NEXT="' . $this->next . '"';
}
$o.= '/>' . "\n";
return $o;
}
/**
* This function will set all the attributes of the XMLDBField object
* based on information passed in one ADOField
*/
function setFromADOField($adofield) {
/// Calculate the XMLDB_TYPE
switch (strtolower($adofield->type)) {
case 'int':
case 'tinyint':
case 'smallint':
case 'bigint':
case 'integer':
$this->type = XMLDB_TYPE_INTEGER;
break;
case 'number':
case 'decimal':
case 'dec':
case 'numeric':
$this->type = XMLDB_TYPE_NUMBER;
break;
case 'float':
case 'double':
$this->type = XMLDB_TYPE_FLOAT;
break;
case 'char':
case 'varchar':
case 'enum':
$this->type = XMLDB_TYPE_CHAR;
break;
case 'text':
case 'tinytext':
case 'mediumtext':
case 'longtext':
$this->type = XMLDB_TYPE_TEXT;
break;
case 'blob':
case 'tinyblob':
case 'mediumblob':
case 'longblob':
$this->type = XMLDB_TYPE_BINARY;
break;
case 'datetime':
case 'timestamp':
$this->type = XMLDB_TYPE_DATETIME;
break;
default:
$this->type = XMLDB_TYPE_TEXT;
}
/// Calculate the length of the field
if ($adofield->max_length > 0 &&
($this->type == XMLDB_TYPE_INTEGER ||
$this->type == XMLDB_TYPE_NUMBER ||
$this->type == XMLDB_TYPE_FLOAT ||
$this->type == XMLDB_TYPE_CHAR)) {
$this->length = $adofield->max_length;
}
if ($this->type == XMLDB_TYPE_TEXT) {
switch (strtolower($adofield->type)) {
case 'tinytext':
case 'text':
$this->length = 'small';
break;
case 'mediumtext':
$this->length = 'medium';
break;
case 'longtext':
$this->length = 'big';
break;
default:
$this->length = 'small';
}
}
if ($this->type == XMLDB_TYPE_BINARY) {
switch (strtolower($adofield->type)) {
case 'tinyblob':
case 'blob':
$this->length = 'small';
break;
case 'mediumblob':
$this->length = 'medium';
break;
case 'longblob':
$this->length = 'big';
break;
default:
$this->length = 'small';
}
}
/// Calculate the decimals of the field
if ($adofield->max_length > 0 &&
$adofield->scale &&
($this->type == XMLDB_TYPE_NUMBER ||
$this->type == XMLDB_TYPE_FLOAT)) {
$this->decimals = $adofield->scale;
}
/// Calculate the unsigned field
if ($adofield->unsigned &&
($this->type == XMLDB_TYPE_INTEGER ||
$this->type == XMLDB_TYPE_NUMBER ||
$this->type == XMLDB_TYPE_FLOAT)) {
$this->unsigned = true;
}
/// Calculate the notnull field
if ($adofield->not_null) {
$this->notnull = true;
}
/// Calculate the default field
if ($adofield->has_default) {
$this->default = $adofield->default_value;
}
/// Calculate the sequence field
if ($adofield->auto_increment) {
$this->sequence = true;
/// Sequence fields are always unsigned
$this->unsigned = true;
}
/// Calculate the enum and enumvalues field
if ($adofield->type == 'enum') {
$this->enum = true;
$this->enumvalues = $adofield->enums;
}
/// Some more fields
$this->loaded = true;
$this->changed = true;
}
/**
* Shows info in a readable format
*/
function readableInfo() {
$o = '';
/// type
$o .= $this->getXMLDBTypeName($this->type);
/// length
if ($this->type == XMLDB_TYPE_INTEGER ||
$this->type == XMLDB_TYPE_NUMBER ||
$this->type == XMLDB_TYPE_FLOAT ||
$this->type == XMLDB_TYPE_CHAR) {
if ($this->length) {
$o .= ' (' . $this->length;
if ($this->type == XMLDB_TYPE_NUMBER ||
$this->type == XMLDB_TYPE_FLOAT) {
if ($this->decimals !== NULL) {
$o .= ', ' . $this->decimals;
}
}
$o .= ')';
}
}
if ($this->type == XMLDB_TYPE_TEXT ||
$this->type == XMLDB_TYPE_BINARY) {
$o .= ' (' . $this->length . ')';
}
/// enum
if ($this->enum) {
$o .= ' enum(' . implode(', ', $this->enumvalues) . ')';
}
/// unsigned
if ($this->type == XMLDB_TYPE_INTEGER ||
$this->type == XMLDB_TYPE_NUMBER ||
$this->type == XMLDB_TYPE_FLOAT) {
if ($this->unsigned) {
$o .= ' unsigned';
} else {
$o .= ' signed';
}
}
/// not null
if ($this->notnull) {
$o .= ' not null';
}
/// default
if ($this->default !== NULL) {
$o .= ' default ';
if ($this->type == XMLDB_TYPE_CHAR ||
$this->type == XMLDB_TYPE_TEXT) {
$o .= "'" . $this->default . "'";
} else {
$o .= $this->default;
}
}
/// sequence
if ($this->sequence) {
$o .= ' auto-numbered';
}
return $o;
}
}
?>
+112
View File
@@ -0,0 +1,112 @@
<?php // $Id$
///////////////////////////////////////////////////////////////////////////
// //
// NOTICE OF COPYRIGHT //
// //
// Moodle - Modular Object-Oriented Dynamic Learning Environment //
// http://moodle.com //
// //
// Copyright (C) 2001-3001 Martin Dougiamas http://dougiamas.com //
// (C) 2001-3001 Eloy Lafuente (stronk7) http://contiento.com //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation; either version 2 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details: //
// //
// http://www.gnu.org/copyleft/gpl.html //
// //
///////////////////////////////////////////////////////////////////////////
/// This class represents an entire XMLDB file
class XMLDBFile extends XMLDBObject {
var $path;
var $xmldb_structure;
/**
* Constructor of the XMLDBFile
*/
function XMLDBFile ($path) {
parent::XMLDBObject($path);
$this->path = $path;
$this->xmldb_structure = NULL;
}
/**
* Determine if the XML file exists
*/
function fileExists() {
if (file_exists($this->path) && is_readable($this->path)) {
return true;
}
return false;
}
/**
* Determine if the XML is writeable
*/
function fileWriteable() {
if (is_writeable(dirname($this->path))) {
return true;
}
return false;
}
function &getStructure() {
return $this->xmldb_structure;
}
/**
* Load and the XMLDB structure from file
*/
function loadXMLStructure() {
if ($this->fileExists()) {
/// File exists, so let's process it
/// Load everything to a big array
$xmlarr = xmlize(file_get_contents($this->path));
/// Convert array to xmldb structure
$this->xmldb_structure = $this->arr2XMLDBStructure($xmlarr);
/// Analize results
if ($this->xmldb_structure->isLoaded()) {
$this->loaded = true;
return true;
} else {
return false;
}
}
return true;
}
/**
* This function takes an xmlized array and put it into one XMLDBStructure
*/
function arr2XMLDBStructure ($xmlarr) {
$structure = new XMLDBStructure($this->path);
$structure->arr2XMLDBStructure($xmlarr);
return $structure;
}
/**
* This function saves the whole XMLDBStructure to its file
*/
function saveXMLFile() {
$result = true;
$structure =& $this->getStructure();
$result = file_put_contents($this->path, $structure->xmlOutput());
return $result;
}
}
?>
+221
View File
@@ -0,0 +1,221 @@
<?php // $Id$
///////////////////////////////////////////////////////////////////////////
// //
// NOTICE OF COPYRIGHT //
// //
// Moodle - Modular Object-Oriented Dynamic Learning Environment //
// http://moodle.com //
// //
// Copyright (C) 2001-3001 Martin Dougiamas http://dougiamas.com //
// (C) 2001-3001 Eloy Lafuente (stronk7) http://contiento.com //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation; either version 2 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details: //
// //
// http://www.gnu.org/copyleft/gpl.html //
// //
///////////////////////////////////////////////////////////////////////////
/// This class represent one XMLDB Index
class XMLDBIndex extends XMLDBObject {
var $unique;
var $fields;
/**
* Creates one new XMLDBIndex
*/
function XMLDBIndex($name) {
parent::XMLDBObject($name);
$this->unique = false;
$this->fields = array();
}
/**
* Get the index unique
*/
function getUnique() {
return $this->unique;
}
/**
* Set the index unique
*/
function setUnique($unique = true) {
$this->unique = $unique;
}
/**
* Set the index fields
*/
function setFields($fields) {
$this->fields = $fields;
}
/**
* Get the index fields
*/
function &getFields() {
return $this->fields;
}
/**
* Load data from XML to the index
*/
function arr2XMLDBIndex($xmlarr) {
$result = true;
/// Debug the table
/// traverse_xmlize($xmlarr); //Debug
/// print_object ($GLOBALS['traverse_array']); //Debug
/// $GLOBALS['traverse_array']=""; //Debug
/// Process key attributes (name, unique, fields, comment, previous, next)
if (isset($xmlarr['@']['NAME'])) {
$this->name = trim($xmlarr['@']['NAME']);
} else {
$this->errormsg = 'Missing NAME attribute';
$result = false;
}
if (isset($xmlarr['@']['UNIQUE'])) {
$unique = strtolower(trim($xmlarr['@']['UNIQUE']));
if ($unique == 'true') {
$this->unique = true;
} else if ($unique == 'false') {
$this->unique = false;
} else {
$this->errormsg = 'Incorrect UNIQUE attribute (true/false allowed)';
$result = false;
}
} else {
$this->errormsg = 'Undefined UNIQUE attribute';
$result = false;
}
if (isset($xmlarr['@']['FIELDS'])) {
$fields = strtolower(trim($xmlarr['@']['FIELDS']));
if ($fields) {
$fieldsarr = explode(',',$fields);
if ($fieldsarr) {
foreach ($fieldsarr as $key => $element) {
$fieldsarr [$key] = trim($element);
}
} else {
$this->errormsg = 'Incorrect FIELDS attribute (comma separated of fields)';
$result = false;
}
} else {
$this->errormsg = 'Empty FIELDS attribute';
$result = false;
}
} else {
$this->errormsg = 'Missing FIELDS attribute';
$result = false;
}
/// Finally, set the array of fields
$this->fields = $fieldsarr;
if (isset($xmlarr['@']['COMMENT'])) {
$this->comment = trim($xmlarr['@']['COMMENT']);
}
if (isset($xmlarr['@']['PREVIOUS'])) {
$this->previous = trim($xmlarr['@']['PREVIOUS']);
}
if (isset($xmlarr['@']['NEXT'])) {
$this->next = trim($xmlarr['@']['NEXT']);
}
/// Set some attributes
if ($result) {
$this->loaded = true;
}
$this->calculateHash();
return $result;
}
/**
* This function calculate and set the hash of one XMLDBIndex
*/
function calculateHash($recursive = false) {
if (!$this->loaded) {
$this->hash = NULL;
} else {
$key = $this->unique . implode (', ', $this->fields);
$this->hash = md5($key);
}
}
/**
*This function will output the XML text for one index
*/
function xmlOutput() {
$o = '';
$o.= ' <INDEX NAME="' . $this->name . '"';
if ($this->unique) {
$unique = 'true';
} else {
$unique = 'false';
}
$o.= ' UNIQUE="' . $unique . '"';
$o.= ' FIELDS="' . implode(', ', $this->fields) . '"';
if ($this->comment) {
$o.= ' COMMENT="' . htmlspecialchars($this->comment) . '"';
}
if ($this->previous) {
$o.= ' PREVIOUS="' . $this->previous . '"';
}
if ($this->next) {
$o.= ' NEXT="' . $this->next . '"';
}
$o.= '/>' . "\n";
return $o;
}
/**
* This function will set all the attributes of the XMLDBIndex object
* based on information passed in one ADOindex
*/
function setFromADOIndex($adoindex) {
/// Set the unique field
$this->unique = false;
/// Set the fields
$this->fields = $adoindex['columns'];
/// Some more fields
$this->loaded = true;
$this->changed = true;
}
/**
* Shows info in a readable format
*/
function readableInfo() {
$o = '';
/// unique
if ($this->unique) {
$o .= 'unique';
} else {
$o .= 'not unique';
}
/// fields
$o .= ' (' . implode(', ', $this->fields) . ')';
return $o;
}
}
?>
+381
View File
@@ -0,0 +1,381 @@
<?php // $Id$
///////////////////////////////////////////////////////////////////////////
// //
// NOTICE OF COPYRIGHT //
// //
// Moodle - Modular Object-Oriented Dynamic Learning Environment //
// http://moodle.com //
// //
// Copyright (C) 2001-3001 Martin Dougiamas http://dougiamas.com //
// (C) 2001-3001 Eloy Lafuente (stronk7) http://contiento.com //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation; either version 2 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details: //
// //
// http://www.gnu.org/copyleft/gpl.html //
// //
///////////////////////////////////////////////////////////////////////////
/// This class represent one XMLDB Key
class XMLDBKey extends XMLDBObject {
var $type;
var $fields;
var $reftable;
var $reffields;
/**
* Creates one new XMLDBKey
*/
function XMLDBKey($name) {
parent::XMLDBObject($name);
$this->type = NULL;
$this->fields = array();
$this->reftable = NULL;
$this->reffields = array();
}
/**
* Get the key type
*/
function getType() {
return $this->type;
}
/**
* Set the key type
*/
function setType($type) {
$this->type = $type;
}
/**
* Set the key fields
*/
function setFields($fields) {
$this->fields = $fields;
}
/**
* Set the key reftable
*/
function setRefTable($reftable) {
$this->reftable = $reftable;
}
/**
* Set the key reffields
*/
function setRefFields($reffields) {
$this->reffields = $reffields;
}
/**
* Get the key fields
*/
function &getFields() {
return $this->fields;
}
/**
* Get the key reftable
*/
function &getRefTable() {
return $this->reftable;
}
/**
* Get the key reffields
*/
function &getRefFields() {
return $this->reffields;
}
/**
* Load data from XML to the key
*/
function arr2XMLDBKey($xmlarr) {
$result = true;
/// Debug the table
/// traverse_xmlize($xmlarr); //Debug
/// print_object ($GLOBALS['traverse_array']); //Debug
/// $GLOBALS['traverse_array']=""; //Debug
/// Process key attributes (name, type, fields, reftable,
/// reffields, comment, previous, next)
if (isset($xmlarr['@']['NAME'])) {
$this->name = trim($xmlarr['@']['NAME']);
} else {
$this->errormsg = 'Missing NAME attribute';
$result = false;
}
if (isset($xmlarr['@']['TYPE'])) {
/// Check for valid type
$type = $this->getXMLDBKeyType(trim($xmlarr['@']['TYPE']));
if ($type) {
$this->type = $type;
} else {
$this->errormsg = 'Invalid TYPE attribute';
$result = false;
}
} else {
$this->errormsg = 'Missing TYPE attribute';
$result = false;
}
if (isset($xmlarr['@']['FIELDS'])) {
$fields = strtolower(trim($xmlarr['@']['FIELDS']));
if ($fields) {
$fieldsarr = explode(',',$fields);
if ($fieldsarr) {
foreach ($fieldsarr as $key => $element) {
$fieldsarr [$key] = trim($element);
}
} else {
$this->errormsg = 'Incorrect FIELDS attribute (comma separated of fields)';
$result = false;
}
} else {
$this->errormsg = 'Empty FIELDS attribute';
$result = false;
}
} else {
$this->errormsg = 'Missing FIELDS attribute';
$result = false;
}
/// Finally, set the array of fields
$this->fields = $fieldsarr;
if (isset($xmlarr['@']['REFTABLE'])) {
/// Check we are in a FK
if ($this->type == XMLDB_KEY_FOREIGN ||
$this->type == XMLDB_KEY_FOREIGN_UNIQUE) {
$reftable = strtolower(trim($xmlarr['@']['REFTABLE']));
if (!$reftable) {
$this->errormsg = 'Empty REFTABLE attribute';
$result = false;
}
} else {
$this->errormsg = 'Wrong REFTABLE attribute (only FK can have it)';
$result = false;
}
} else if ($this->type == XMLDB_KEY_FOREIGN ||
$this->type == XMLDB_KEY_FOREIGN_UNIQUE) {
$this->errormsg = 'Missing REFTABLE attribute';
$result = false;
}
/// Finally, set the reftable
if ($this->type == XMLDB_KEY_FOREIGN ||
$this->type == XMLDB_KEY_FOREIGN_UNIQUE) {
$this->reftable = $reftable;
}
if (isset($xmlarr['@']['REFFIELDS'])) {
/// Check we are in a FK
if ($this->type == XMLDB_KEY_FOREIGN ||
$this->type == XMLDB_KEY_FOREIGN_UNIQUE) {
$reffields = strtolower(trim($xmlarr['@']['REFFIELDS']));
if ($reffields) {
$reffieldsarr = explode(',',$reffields);
if ($reffieldsarr) {
foreach ($reffieldsarr as $key => $element) {
$reffieldsarr [$key] = trim($element);
}
} else {
$this->errormsg = 'Incorrect REFFIELDS attribute (comma separated of fields)';
$result = false;
}
} else {
$this->errormsg = 'Empty REFFIELDS attribute';
$result = false;
}
} else {
$this->errormsg = 'Wrong REFFIELDS attribute (only FK can have it)';
$result = false;
}
} else if ($this->type == XMLDB_KEY_FOREIGN ||
$this->type == XMLDB_KEY_FOREIGN_UNIQUE) {
$this->errormsg = 'Missing REFFIELDS attribute';
$result = false;
}
/// Finally, set the array of reffields
if ($this->type == XMLDB_KEY_FOREIGN ||
$this->type == XMLDB_KEY_FOREIGN_UNIQUE) {
$this->reffields = $reffieldsarr;
}
if (isset($xmlarr['@']['COMMENT'])) {
$this->comment = trim($xmlarr['@']['COMMENT']);
}
if (isset($xmlarr['@']['PREVIOUS'])) {
$this->previous = trim($xmlarr['@']['PREVIOUS']);
}
if (isset($xmlarr['@']['NEXT'])) {
$this->next = trim($xmlarr['@']['NEXT']);
}
/// Set some attributes
if ($result) {
$this->loaded = true;
}
$this->calculateHash();
return $result;
}
/**
* This function returns the correct XMLDB_KEY_XXX value for the
* string passed as argument
*/
function getXMLDBKeyType($type) {
$result = XMLDB_KEY_INCORRECT;
switch (strtolower($type)) {
case 'primary':
$result = XMLDB_KEY_PRIMARY;
break;
case 'unique':
$result = XMLDB_KEY_UNIQUE;
break;
case 'foreign':
$result = XMLDB_KEY_FOREIGN;
break;
case 'foreign-unique':
$result = XMLDB_KEY_FOREIGN_UNIQUE;
break;
/// case 'check': //Not supported
/// $result = XMLDB_KEY_CHECK;
/// break;
}
/// Return the normalized XMLDB_KEY
return $result;
}
/**
* This function returns the correct name value for the
* XMLDB_KEY_XXX passed as argument
*/
function getXMLDBKeyName($type) {
$result = '';
switch (strtolower($type)) {
case XMLDB_KEY_PRIMARY:
$result = 'primary';
break;
case XMLDB_KEY_UNIQUE:
$result = 'unique';
break;
case XMLDB_KEY_FOREIGN:
$result = 'foreign';
break;
case XMLDB_KEY_FOREIGN_UNIQUE:
$result = 'foreign-unique';
break;
/// case XMLDB_KEY_CHECK: //Not supported
/// $result = 'check';
/// break;
}
/// Return the normalized name
return $result;
}
/**
* This function calculate and set the hash of one XMLDBKey
*/
function calculateHash($recursive = false) {
if (!$this->loaded) {
$this->hash = NULL;
} else {
$key = $this->type . implode(', ', $this->fields);
if ($this->type == XMLDB_KEY_FOREIGN ||
$this->type == XMLDB_KEY_FOREIGN_UNIQUE) {
$key .= $this->reftable . implode(', ', $this->reffields);
}
;
$this->hash = md5($key);
}
}
/**
*This function will output the XML text for one key
*/
function xmlOutput() {
$o = '';
$o.= ' <KEY NAME="' . $this->name . '"';
$o.= ' TYPE="' . $this->getXMLDBKeyName($this->type) . '"';
$o.= ' FIELDS="' . implode(', ', $this->fields) . '"';
if ($this->type == XMLDB_KEY_FOREIGN ||
$this->type == XMLDB_KEY_FOREIGN_UNIQUE) {
$o.= ' REFTABLE="' . $this->reftable . '"';
$o.= ' REFFIELDS="' . implode(', ', $this->reffields) . '"';
}
if ($this->comment) {
$o.= ' COMMENT="' . htmlspecialchars($this->comment) . '"';
}
if ($this->previous) {
$o.= ' PREVIOUS="' . $this->previous . '"';
}
if ($this->next) {
$o.= ' NEXT="' . $this->next . '"';
}
$o.= '/>' . "\n";
return $o;
}
/**
* This function will set all the attributes of the XMLDBKey object
* based on information passed in one ADOkey
*/
function setFromADOKey($adokey) {
/// Calculate the XMLDB_KEY
switch (strtolower($adokey['name'])) {
case 'primary':
$this->type = XMLDB_KEY_PRIMARY;
break;
default:
$this->type = XMLDB_KEY_UNIQUE;
}
/// Set the fields
$this->fields = $adokey['columns'];
/// Some more fields
$this->loaded = true;
$this->changed = true;
}
/**
* Shows info in a readable format
*/
function readableInfo() {
$o = '';
/// type
$o .= $this->getXMLDBKeyName($this->type);
/// fields
$o .= ' (' . implode(', ', $this->fields) . ')';
/// foreign key
if ($this->type == XMLDB_KEY_FOREIGN ||
$this->type == XMLDB_KEY_FOREIGN_UNIQUE) {
$o .= ' references ' . $this->reftable . ' (' . implode(', ', $this->reffields) . ')';
}
return $o;
}
}
?>
+387
View File
@@ -0,0 +1,387 @@
<?php // $Id$
///////////////////////////////////////////////////////////////////////////
// //
// NOTICE OF COPYRIGHT //
// //
// Moodle - Modular Object-Oriented Dynamic Learning Environment //
// http://moodle.com //
// //
// Copyright (C) 2001-3001 Martin Dougiamas http://dougiamas.com //
// (C) 2001-3001 Eloy Lafuente (stronk7) http://contiento.com //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation; either version 2 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details: //
// //
// http://www.gnu.org/copyleft/gpl.html //
// //
///////////////////////////////////////////////////////////////////////////
/// This class represent the XMLDB base class where all the common piezes
/// are defined
class XMLDBObject {
var $name;
var $comment;
var $previous;
var $next;
var $hash;
var $loaded;
var $changed;
var $errormsg;
/**
* Creates one new XMLDBObject
*/
function XMLDBObject($name) {
$this->name = $name;
$this->comment = NULL;
$this->previous = NULL;
$this->next = NULL;
$this->hash = NULL;
$this->loaded = false;
$this->changed = false;
$this->errormsg = NULL;
}
/**
* This function returns true/false, if the XMLDBObject has been loaded
*/
function isLoaded() {
return $this->loaded;
}
/**
* This function returns true/false, if the XMLDBObject has changed
*/
function hasChanged() {
return $this->changed;
}
/**
* This function returns the comment of one XMLDBObject
*/
function getComment() {
return $this->comment;
}
/**
* This function returns the hash of one XMLDBObject
*/
function getHash() {
return $this->hash;
}
/**
* This function will return the name of the previous XMLDBObject
*/
function getPrevious() {
return $this->previous;
}
/**
* This function will return the name of the next XMLDBObject
*/
function getNext() {
return $this->next;
}
/**
* This function will return the name of the XMLDBObject
*/
function getName() {
return $this->name;
}
/**
* This function will return the error detected in the object
*/
function getError() {
return $this->errormsg;
}
/**
* This function will set the comment of the XMLDB object
*/
function setComment($comment) {
$this->comment = $comment;
}
/**
* This function will set the previous of the XMLDB object
*/
function setPrevious($previous) {
$this->previous = $previous;
}
/**
* This function will set the next of the XMLDB object
*/
function setNext($next) {
$this->next = $next;
}
/**
* This function will set the hash of the XMLDB object
*/
function setHash($hash) {
$this->hash = $hash;
}
/**
* This function will set the loaded field of the XMLDB object
*/
function setLoaded($loaded = true) {
$this->loaded = $loaded;
}
/**
* This function will set the changed field of the XMLDB object
*/
function setChanged($changed = true) {
$this->changed = $changed;
}
/**
* This function will set the name field of the XMLDB object
*/
function setName($name) {
$this->name = $name;
}
/**
* This function will check if one key name is ok or no (true/false)
* only lowercase a-z, 0-9 and _ are allowed
*/
function checkName () {
$result = true;
if ($this->name != eregi_replace('[^a-z0-9_ -]', '', $this->name)) {
$result = false;
}
return $result;
}
/**
* This function will check that all the elements in one array
* have a correct name [a-z0-9_]
*/
function checkNameValues(&$arr) {
$result = true;
/// TODO: Perhaps, add support for reserved words
/// Check the name only contains valid chars
if ($arr) {
foreach($arr as $element) {
if (!$element->checkName()) {
$result = false;
}
}
}
return $result;
}
/**
* This function will check that all the elements in one array
* have a consistent info in their previous/next fields
*/
function checkPreviousNextValues(&$arr) {
$result = true;
/// Check that only one element has the previous not set
if ($arr) {
$counter = 0;
foreach($arr as $element) {
if (!$element->getPrevious()) {
$counter++;
}
}
if ($counter != 1) {
$result = false;
}
}
/// Check that only one element has the next not set
if ($result && $arr) {
$counter = 0;
foreach($arr as $element) {
if (!$element->getNext()) {
$counter++;
}
}
if ($counter != 1) {
$result = false;
}
}
/// Check that all the previous elements are existing elements
if ($result && $arr) {
foreach($arr as $element) {
if ($element->getPrevious()) {
$i = $this->findObjectInArray($element->getPrevious(), $arr);
if ($i === NULL) {
$result = false;
}
}
}
}
/// Check that all the next elements are existing elements
if ($result && $arr) {
foreach($arr as $element) {
if ($element->getNext()) {
$i = $this->findObjectInArray($element->getNext(), $arr);
if ($i === NULL) {
$result = false;
}
}
}
}
/// Check that there aren't duplicates in the previous values
if ($result && $arr) {
$existarr = array();
foreach($arr as $element) {
if (in_array($element->getPrevious(), $existarr)) {
$result = false;
} else {
$existarr[] = $element->getPrevious();
}
}
}
/// Check that there aren't duplicates in the next values
if ($result && $arr) {
$existarr = array();
foreach($arr as $element) {
if (in_array($element->getNext(), $existarr)) {
$result = false;
} else {
$existarr[] = $element->getNext();
}
}
}
return $result;
}
/**
* This function will order all the elements in one array, following
* the previous/next rules
*/
function orderElements($arr) {
$result = true;
/// Create a new array
$newarr = array();
if (!empty($arr)) {
$currentelement = NULL;
/// Get the element without previous
foreach($arr as $key => $element) {
if (!$element->getPrevious()) {
$currentelement = $arr[$key];
$newarr[0] = $arr[$key];
}
}
if (!$currentelement) {
$result = false;
}
/// Follow the next rules
$counter = 1;
while ($result && $currentelement->getNext()) {
$i = $this->findObjectInArray($currentelement->getNext(), $arr);
$currentelement = $arr[$i];
$newarr[$counter] = $arr[$i];
$counter++;
}
/// Compare number of elements between original and new array
if ($result && count($arr) != count($newarr)) {
$result = false;
}
/// Check that previous/next is ok (redundant but...)
if ($this->checkPreviousNextValues($newarr)) {
$result = $newarr;
} else {
$result = false;
}
} else {
$result = array();
}
return $result;
}
/**
* Returns the position of one object in the array.
*/
function &findObjectInArray($objectname, $arr) {
foreach ($arr as $i => $object) {
if ($objectname == $object->getName()) {
return $i;
}
}
$null = NULL;
return $null;
}
/**
* This function will display a readable info about the XMLDBObject
* (should be implemented inside each XMLDBxxx object)
*/
function readableInfo() {
return get_class($this);
}
/**
* Returns one array of elements from one comma separated string,
* supporting quoted strings containing commas and concat function calls
*/
function comma2array($string) {
$arr = array();
$foundquotes = array();
$foundconcats = array();
/// Extract all the concat elements from the string
preg_match_all("/(CONCAT\(.*?\))/is", $string, $matches);
foreach (array_unique($matches[0]) as $key=>$value) {
$foundconcats['<#'.$key.'#>'] = $value;
}
if (!empty($foundconcats)) {
$string = str_replace($foundconcats,array_keys($foundconcats),$string);
}
/// Extract all the quoted elements from the string
preg_match_all("/('.*?')/is", $string, $matches);
foreach (array_unique($matches[0]) as $key=>$value) {
$foundquotes['<%'.$key.'%>'] = $value;
}
if (!empty($foundquotes)) {
$string = str_replace($foundquotes,array_keys($foundquotes),$string);
}
/// Explode safely the string
$arr = explode (',', $string);
/// Put the concat and quoted elements back again, triming every element
if ($arr) {
foreach ($arr as $key => $element) {
/// Clear some spaces
$element = trim($element);
/// Replace the quoted elements if exists
if (!empty($foundquotes)) {
$element = str_replace(array_keys($foundquotes), $foundquotes, $element);
}
/// Replace the concat elements if exists
if (!empty($foundconcats)) {
$element = str_replace(array_keys($foundconcats), $foundconcats, $element);
}
$arr[$key] = $element;
}
}
return $arr;
}
}
?>
+365
View File
@@ -0,0 +1,365 @@
<?php // $Id$
///////////////////////////////////////////////////////////////////////////
// //
// NOTICE OF COPYRIGHT //
// //
// Moodle - Modular Object-Oriented Dynamic Learning Environment //
// http://moodle.com //
// //
// Copyright (C) 2001-3001 Martin Dougiamas http://dougiamas.com //
// (C) 2001-3001 Eloy Lafuente (stronk7) http://contiento.com //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation; either version 2 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details: //
// //
// http://www.gnu.org/copyleft/gpl.html //
// //
///////////////////////////////////////////////////////////////////////////
/// This class represent one XMLDB Statement
/// (a group of SQL arbitrary sentences)
/// (only INSERT is allowed for now)
class XMLDBStatement extends XMLDBObject {
var $table; // Table we are handling
var $type; // XMLDB_STATEMENT_TYPE
var $sentences; // Collection of sentences in the statement
/**
* Creates one new XMLDBStatement
*/
function XMLDBStatement($name) {
parent::XMLDBObject($name);
$this->table = NULL;
$this->type = XMLDB_STATEMENT_INCORRECT;
$this->sentences = array();
}
/**
* Get the statement table
*/
function getTable() {
return $this->table;
}
/**
* Get the statement type
*/
function getType() {
return $this->type;
}
/**
* Get the statement sentences
*/
function &getSentences() {
return $this->sentences;
}
/**
* Set the statement table
*/
function setTable($table) {
$this->table = $table;
}
/**
* Set the statement type
*/
function setType($type) {
$this->type = $type;
}
/**
* Add one statement sentence
*/
function addSentence($sentence) {
$this->sentences[] = $sentence;
}
/**
* Load data from XML to the index
*/
function arr2XMLDBStatement($xmlarr) {
$result = true;
/// Debug the table
/// traverse_xmlize($xmlarr); //Debug
/// print_object ($GLOBALS['traverse_array']); //Debug
/// $GLOBALS['traverse_array']=""; //Debug
/// Process key attributes (table, type, comment, previous, next)
if (isset($xmlarr['@']['TABLE'])) {
$this->table = strtolower(trim($xmlarr['@']['TABLE']));
} else {
$this->errormsg = 'Missing TABLE attribute';
$result = false;
}
if (isset($xmlarr['@']['TYPE'])) {
/// Check for valid type
$type = $this->getXMLDBStatementType(trim($xmlarr['@']['TYPE']));
if ($type) {
$this->type = $type;
} else {
$this->errormsg = 'Invalid TYPE attribute';
$result = false;
}
} else {
$this->errormsg = 'Missing TYPE attribute';
$result = false;
}
/// Look for sentences
$sentencesarr = array();
if (isset($xmlarr['#']['SENTENCES'])) {
$sentences = $xmlarr['#']['SENTENCES'][0]['#']['SENTENCE'];
if ($sentences) {
foreach ($sentences as $sentence) {
if (isset($sentence['@']['TEXT'])) {
$sentencesarr[] = trim($sentence['@']['TEXT']);
} else {
$this->errormsg = 'Missing TEXT attribute in sentence';
$result = false;
}
}
}
}
/// Finally, set the array of sentences
$this->sentences = $sentencesarr;
/// Now, perform some validations over sentences
/// XMLDB_STATEMENT_INSERT checks
if ($this->type == XMLDB_STATEMENT_INSERT) {
/// Separate fields and values into two arrays
if ($this->sentences) {
foreach ($this->sentences as $sentence) {
$fields = $this->getFieldsFromInsertSentence($sentence);
$values = $this->getValuesFromInsertSentence($sentence);
/// Check that we aren't inserting the id field
if (in_array('id', $fields)) {
$this->errormsg = 'Cannot insert the "id" field. It is an autonumeric column';
$result = false;
}
if ($result && count($fields) == 0) {
$this->errormsg = 'Missing fields in sentence "' . $sentence . '"';
$result = false;
}
if ($result && count($values) == 0) {
$this->errormsg = 'Missing values in sentence "' . $sentence . '"';
$result = false;
}
if ($result && count($fields) != count($values)) {
$this->errormsg = 'Incorrect number of fields (' .implode(', ', $fields) . ') or values (' . implode(', ', $values) . ')';
$result = false;
}
}
}
} else {
/// Sentences different from INSERT are not valid for now
$this->errormsg = 'Only INSERT statements are supported';
$result = false;
}
if (isset($xmlarr['@']['COMMENT'])) {
$this->comment = trim($xmlarr['@']['COMMENT']);
}
if (isset($xmlarr['@']['PREVIOUS'])) {
$this->previous = trim($xmlarr['@']['PREVIOUS']);
}
if (isset($xmlarr['@']['NEXT'])) {
$this->next = trim($xmlarr['@']['NEXT']);
}
/// Set some attributes
if ($result) {
$this->loaded = true;
}
$this->calculateHash();
return $result;
}
/**
* This function returns the correct XMLDB_STATEMENT_XXX value for the
* string passed as argument
*/
function getXMLDBStatementType($type) {
$result = XMLDB_STATEMENT_INCORRECT;
switch (strtolower($type)) {
case 'insert':
$result = XMLDB_STATEMENT_INSERT;
break;
case 'update':
$result = XMLDB_STATEMENT_UPDATE;
break;
case 'delete':
$result = XMLDB_STATEMENT_DELETE;
break;
case 'custom':
$result = XMLDB_STATEMENT_CUSTOM;
break;
}
/// Return the normalized XMLDB_STATEMENT
return $result;
}
/**
* This function returns the correct name value for the
* XMLDB_STATEMENT_XXX passed as argument
*/
function getXMLDBStatementName($type) {
$result = '';
switch (strtolower($type)) {
case XMLDB_STATEMENT_INSERT:
$result = 'insert';
break;
case XMLDB_STATEMENT_UPDATE:
$result = 'update';
break;
case XMLDB_STATEMENT_DELETE:
$result = 'delete';
break;
case XMLDB_STATEMENT_CUSTOM:
$result = 'custom';
break;
}
/// Return the normalized name
return $result;
}
/**
* This function calculate and set the hash of one XMLDBStatement
*/
function calculateHash($recursive = false) {
if (!$this->loaded) {
$this->hash = NULL;
} else {
$key = $this->table . $this->type . implode (', ', $this->sentences);
$this->hash = md5($key);
}
}
/**
* This function will output the XML text for one statement
*/
function xmlOutput() {
$o = '';
$o.= ' <STATEMENT NAME="' . $this->name . '" TYPE="' . XMLDBStatement::getXMLDBStatementName($this->type) . '" TABLE="' . $this->table . '"';
if ($this->comment) {
$o.= ' COMMENT="' . htmlspecialchars($this->comment) . '"';
}
if ($this->previous) {
$o.= ' PREVIOUS="' . $this->previous . '"';
}
if ($this->next) {
$o.= ' NEXT="' . $this->next . '"';
}
if ($this->sentences) {
$o.= '>' . "\n";
$o.= ' <SENTENCES>' . "\n";
foreach ($this->sentences as $sentence) {
$o.= ' <SENTENCE TEXT="' . htmlspecialchars($sentence) . '" />' . "\n";
}
$o.= ' </SENTENCES>' . "\n";
$o.= ' </STATEMENT>' . "\n";
} else {
$o.= '/>' . "\n";
}
return $o;
}
/**
* This function will set all the attributes of the XMLDBIndex object
* based on information passed in one ADOindex
*/
function setFromADOIndex($adoindex) {
/// Set the unique field
$this->unique = false;
/// Set the fields
$this->fields = $adoindex['columns'];
/// Some more fields
$this->loaded = true;
$this->changed = true;
}
/**
* Shows info in a readable format
*/
function readableInfo() {
$o = '';
/// unique
if ($this->unique) {
$o .= 'unique';
} else {
$o .= 'not unique';
}
/// fields
$o .= ' (' . implode(', ', $this->fields) . ')';
return $o;
}
/**
* This function will return an array of fields from one INSERT sentence
*/
function getFieldsFromInsertSentence($sentence) {
$fields = array();
/// Get first part from the sentence (before VALUES)
preg_match('/^\((.*)\)\s+VALUES/is', $sentence, $matches);
if (isset($matches[1])) {
$part = $matches[1];
/// Convert the comma separated string to an array
$arr = $this->comma2array($part);
if ($arr) {
$fields = $arr;
}
}
return $fields;
}
/**
* This function will return an array of values from one INSERT sentence
*/
function getValuesFromInsertSentence($sentence) {
$values = array();
/// Get second part from the sentence (after VALUES)
preg_match('/VALUES\s+\((.*)\)$/is', $sentence, $matches);
if (isset($matches[1])) {
$part = $matches[1];
/// Convert the comma separated string to an array
$arr = $this->comma2array($part);
if ($arr) {
$values = $arr;
}
}
return $values;
}
}
?>
+697
View File
@@ -0,0 +1,697 @@
<?php // $Id$
///////////////////////////////////////////////////////////////////////////
// //
// NOTICE OF COPYRIGHT //
// //
// Moodle - Modular Object-Oriented Dynamic Learning Environment //
// http://moodle.com //
// //
// Copyright (C) 2001-3001 Martin Dougiamas http://dougiamas.com //
// (C) 2001-3001 Eloy Lafuente (stronk7) http://contiento.com //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation; either version 2 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details: //
// //
// http://www.gnu.org/copyleft/gpl.html //
// //
///////////////////////////////////////////////////////////////////////////
/// This class represent one XMLDB structure
class XMLDBStructure extends XMLDBObject {
var $path;
var $version;
var $tables;
var $statements;
/**
* Creates one new XMLDBStructure
*/
function XMLDBStructure($name) {
parent::XMLDBObject($name);
$this->path = NULL;
$this->version = NULL;
$this->tables = array();
$this->statements = array();
}
/**
* Returns the path of the structure
*/
function getPath() {
return $this->path;
}
/**
* Returns the version of the structure
*/
function getVersion() {
return $this->version;
}
/**
* Returns one XMLDBTable
*/
function &getTable($tablename) {
$i = $this->findTableInArray($tablename);
if ($i !== NULL) {
return $this->tables[$i];
}
$null = NULL;
return $null;
}
/**
* Returns the position of one table in the array.
*/
function &findTableInArray($tablename) {
foreach ($this->tables as $i => $table) {
if ($tablename == $table->getName()) {
return $i;
}
}
$null = NULL;
return $null;
}
/**
* Returns the position of one statement in the array.
*/
function &findStatementInArray($statementname) {
foreach ($this->statements as $i => $statement) {
if ($statementname == $statement->getName()) {
return $i;
}
}
$null = NULL;
return $null;
}
/**
* This function will reorder the array of tables
*/
function orderTables() {
$result =& $this->orderElements($this->tables);
if ($result) {
$this->setTables($result);
return true;
} else {
return false;
}
}
/**
* This function will reorder the array of statements
*/
function orderStatements() {
$result =& $this->orderElements($this->statements);
if ($result) {
$this->setStatements($result);
return true;
} else {
return false;
}
}
/**
* Returns the tables of the structure
*/
function &getTables() {
return $this->tables;
}
/**
* Returns one XMLDBStatement
*/
function &getStatement($statementname) {
$i = $this->findStatementInArray($statementname);
if ($i !== NULL) {
return $this->statements[$i];
}
$null = NULL;
return $null;
}
/**
* Returns the statements of the structure
*/
function &getStatements() {
return $this->statements;
}
/**
* Set the structure version
*/
function setVersion($version) {
$this->version = $version;
}
/**
* Add one table to the structure, allowing to specify the desired order
* If it's not specified, then the table is added at the end.
*/
function addTable(&$table, $after=NULL) {
/// Calculate the previous and next tables
$prevtable = NULL;
$nexttable = NULL;
if (!$after) {
$alltables =& $this->getTables();
if ($alltables) {
end($alltables);
$prevtable =& $alltables[key($alltables)];
}
} else {
$prevtable =& $this->getTable($after);
}
if ($prevtable && $prevtable->getNext()) {
$nexttable =& $this->getTable($prevtable->getNext());
}
/// Set current table previous and next attributes
if ($prevtable) {
$table->setPrevious($prevtable->getName());
$prevtable->setNext($table->getName());
}
if ($nexttable) {
$table->setNext($nexttable->getName());
$nexttable->setPrevious($table->getName());
}
/// Some more attributes
$table->setLoaded(true);
$table->setChanged(true);
/// Add the new table
$this->tables[] =& $table;
/// Reorder the whole structure
$this->orderTables($this->tables);
/// Recalculate the hash
$this->calculateHash(true);
/// We have one new table, so the structure has changed
$this->setVersion(userdate(time(), '%Y%m%d', 99, false));
$this->setChanged(true);
}
/**
* Add one statement to the structure, allowing to specify the desired order
* If it's not specified, then the statement is added at the end.
*/
function addStatement(&$statement, $after=NULL) {
/// Calculate the previous and next tables
$prevstatement = NULL;
$nextstatement = NULL;
if (!$after) {
$allstatements =& $this->getStatements();
if ($allstatements) {
end($allstatements);
$prevstatement =& $allstatements[key($allstatements)];
}
} else {
$prevstatement =& $this->getStatement($after);
}
if ($prevstatement && $prevstatement->getNext()) {
$nextstatement =& $this->getStatement($prevstatement->getNext());
}
/// Set current statement previous and next attributes
if ($prevstatement) {
$statement->setPrevious($prevstatement->getName());
$prevstatement->setNext($statement->getName());
}
if ($nextstatement) {
$statement->setNext($nextstatement->getName());
$nextstatement->setPrevious($statement->getName());
}
/// Some more attributes
$statement->setLoaded(true);
$statement->setChanged(true);
/// Add the new statement
$this->statements[] =& $statement;
/// Reorder the whole structure
$this->orderStatements($this->statements);
/// Recalculate the hash
$this->calculateHash(true);
/// We have one new statement, so the structure has changed
$this->setVersion(userdate(time(), '%Y%m%d', 99, false));
$this->setChanged(true);
}
/**
* Delete one table from the Structure
*/
function deleteTable($tablename) {
$table =& $this->getTable($tablename);
if ($table) {
$i = $this->findTableInArray($tablename);
$prevtable = NULL;
$nexttable = NULL;
/// Look for prev and next table
$prevtable =& $this->getTable($table->getPrevious());
$nexttable =& $this->getTable($table->getNext());
/// Change their previous and next attributes
if ($prevtable) {
$prevtable->setNext($table->getNext());
}
if ($nexttable) {
$nexttable->setPrevious($table->getPrevious());
}
/// Delete the table
unset($this->tables[$i]);
/// Reorder the tables
$this->orderTables($this->tables);
/// Recalculate the hash
$this->calculateHash(true);
/// We have one deleted table, so the structure has changed
$this->setVersion(userdate(time(), '%Y%m%d', 99, false));
$this->setChanged(true);
}
}
/**
* Delete one statement from the Structure
*/
function deleteStatement($statementname) {
$statement =& $this->getStatement($statementname);
if ($statement) {
$i = $this->findStatementInArray($statementname);
$prevstatement = NULL;
$nextstatement = NULL;
/// Look for prev and next statement
$prevstatement =& $this->getStatement($statement->getPrevious());
$nextstatement =& $this->getStatement($statement->getNext());
/// Change their previous and next attributes
if ($prevstatement) {
$prevstatement->setNext($statement->getNext());
}
if ($nextstatement) {
$nextstatement->setPrevious($statement->getPrevious());
}
/// Delete the statement
unset($this->statements[$i]);
/// Reorder the statements
$this->orderStatements($this->statements);
/// Recalculate the hash
$this->calculateHash(true);
/// We have one deleted statement, so the structure has changed
$this->setVersion(userdate(time(), '%Y%m%d', 99, false));
$this->setChanged(true);
}
}
/**
* Set the tables
*/
function setTables(&$tables) {
$this->tables = $tables;
}
/**
* Set the statements
*/
function setStatements(&$statements) {
$this->statements = $statements;
}
/**
* Load data from XML to the structure
*/
function arr2XMLDBStructure($xmlarr) {
$result = true;
/// Debug the structure
/// traverse_xmlize($xmlarr); //Debug
/// print_object ($GLOBALS['traverse_array']); //Debug
/// $GLOBALS['traverse_array']=""; //Debug
/// Process structure attributes (path, comment and version)
if (isset($xmlarr['XMLDB']['@']['PATH'])) {
$this->path = trim($xmlarr['XMLDB']['@']['PATH']);
} else {
$this->errormsg = 'Missing PATH attribute';
$result = false;
}
if (isset($xmlarr['XMLDB']['@']['VERSION'])) {
$this->version = trim($xmlarr['XMLDB']['@']['VERSION']);
} else {
$this->errormsg = 'Missing VERSION attribute';
$result = false;
}
if (isset($xmlarr['XMLDB']['@']['COMMENT'])) {
$this->comment = trim($xmlarr['XMLDB']['@']['COMMENT']);
} else {
$this->errormsg = 'Missing COMMENT attribute';
$result = false;
}
/// Iterate over tables
if (isset($xmlarr['XMLDB']['#']['TABLES']['0']['#']['TABLE'])) {
foreach ($xmlarr['XMLDB']['#']['TABLES']['0']['#']['TABLE'] as $xmltable) {
if (!$result) { //Skip on error
continue;
}
$name = trim($xmltable['@']['NAME']);
$table = new XMLDBTable($name);
$table->arr2XMLDBTable($xmltable);
$this->tables[] = $table;
if (!$table->isLoaded()) {
$this->errormsg = 'Problem loading table ' . $name;
$result = false;
}
}
} else {
$this->errormsg = 'Missing TABLES section';
$result = false;
}
/// Perform some general checks over tables
if ($result && $this->tables) {
/// Check tables names are ok (lowercase, a-z _-)
if (!$this->checkNameValues($this->tables)) {
$this->errormsg = 'Some TABLES name values are incorrect';
$result = false;
}
/// Check previous & next are ok (duplicates and existing tables)
if ($result && !$this->checkPreviousNextValues($this->tables)) {
$this->errormsg = 'Some TABLES previous/next values are incorrect';
$result = false;
}
/// Order tables
if ($result && !$this->orderTables($this->tables)) {
$this->errormsg = 'Error ordering the tables';
$result = false;
}
}
/// Iterate over statements
if (isset($xmlarr['XMLDB']['#']['STATEMENTS']['0']['#']['STATEMENT'])) {
foreach ($xmlarr['XMLDB']['#']['STATEMENTS']['0']['#']['STATEMENT'] as $xmlstatement) {
if (!$result) { //Skip on error
continue;
}
$name = trim($xmlstatement['@']['NAME']);
$statement = new XMLDBStatement($name);
$statement->arr2XMLDBStatement($xmlstatement);
$this->statements[] = $statement;
if (!$statement->isLoaded()) {
$this->errormsg = 'Problem loading statement ' . $name;
$result = false;
}
}
}
/// Perform some general checks over statements
if ($result && $this->statements) {
/// Check statements names are ok (lowercase, a-z _-)
if (!$this->checkNameValues($this->statements)) {
$this->errormsg = 'Some STATEMENTS name values are incorrect';
$result = false;
}
/// Check previous & next are ok (duplicates and existing statements)
if ($result && !$this->checkPreviousNextValues($this->statements)) {
$this->errormsg = 'Some STATEMENTS previous/next values are incorrect';
$result = false;
}
/// Order statements
if ($result && !$this->orderStatements($this->statements)) {
$this->errormsg = 'Error ordering the statements';
$result = false;
}
}
/// Set some attributes
if ($result) {
$this->loaded = true;
}
$this->calculateHash();
return $result;
}
/**
* This function calculate and set the hash of one XMLDBStructure
*/
function calculateHash($recursive = false) {
if (!$this->loaded) {
$this->hash = NULL;
} else {
$key = $this->name . $this->path . $this->comment;
if ($this->tables) {
foreach ($this->tables as $tbl) {
$table =& $this->getTable($tbl->getName());
if ($recursive) {
$table->calculateHash($recursive);
}
$key .= $table->getHash();
}
}
if ($this->statements) {
foreach ($this->statements as $sta) {
$statement =& $this->getStatement($sta->getName());
if ($recursive) {
$statement->calculateHash($recursive);
}
$key .= $statement->getHash();
}
}
$this->hash = md5($key);
}
}
/**
* This function will output the XML text for one structure
*/
function xmlOutput() {
$o = '<?xml version="1.0" encoding="UTF-8" ?>' . "\n";
$o.= '<XMLDB PATH="' . $this->path . '"';
$o.= ' VERSION="' . $this->version . '"';
if ($this->comment) {
$o.= ' COMMENT="' . htmlspecialchars($this->comment) . '"';
}
$o.= '>' . "\n";
/// Now the tables
if ($this->tables) {
$o.= ' <TABLES>' . "\n";
foreach ($this->tables as $table) {
$o.= $table->xmlOutput();
}
$o.= ' </TABLES>' . "\n";
}
/// Now the statements
if ($this->statements) {
$o.= ' <STATEMENTS>' . "\n";
foreach ($this->statements as $statement) {
$o.= $statement->xmlOutput();
}
$o.= ' </STATEMENTS>' . "\n";
}
$o.= '</XMLDB>';
return $o;
}
/**
* This function returns the number of uses of one table inside
* a whole XMLDStructure. Useful to detect if the table must be
* locked. Return false if no uses are found.
*/
function getTableUses($tablename) {
$uses = array();
/// Check if some foreign key in the whole structure is using it
/// (by comparing the reftable with the tablename)
$alltables = $this->getTables();
if ($alltables) {
foreach ($alltables as $table) {
$keys = $table->getKeys();
if ($keys) {
foreach ($keys as $key) {
if ($key->getType() == XMLDB_KEY_FOREIGN) {
if ($tablename == $key->getRefTable()) {
$uses[] = 'table ' . $table->getName() . ' key ' . $key->getName();
}
}
}
}
}
}
/// Return result
if (!empty($uses)) {
return $uses;
} else {
return false;
}
}
/**
* This function returns the number of uses of one field inside
* a whole XMLDBStructure. Useful to detect if the field must be
* locked. Return false if no uses are found.
*/
function getFieldUses($tablename, $fieldname) {
$uses = array();
/// Check if any key in the table is using it
$table = $this->getTable($tablename);
if ($keys = $table->getKeys()) {
foreach ($keys as $key) {
if (in_array($fieldname, $key->getFields()) ||
in_array($fieldname, $key->getRefFields())) {
$uses[] = 'table ' . $table->getName() . ' key ' . $key->getName();
}
}
}
/// Check if any index in the table is using it
$table = $this->getTable($tablename);
if ($indexes = $table->getIndexes()) {
foreach ($indexes as $index) {
if (in_array($fieldname, $index->getFields())) {
$uses[] = 'table ' . $table->getName() . ' index ' . $index->getName();
}
}
}
/// Check if some foreign key in the whole structure is using it
/// By comparing the reftable and refields with the field)
$alltables = $this->getTables();
if ($alltables) {
foreach ($alltables as $table) {
$keys = $table->getKeys();
if ($keys) {
foreach ($keys as $key) {
if ($key->getType() == XMLDB_KEY_FOREIGN) {
if ($tablename == $key->getRefTable()) {
$reffieds = $key->getRefFields();
if (in_array($fieldname, $key->getRefFields())) {
$uses[] = 'table ' . $table->getName() . ' key ' . $key->getName();
}
}
}
}
}
}
}
/// Return result
if (!empty($uses)) {
return $uses;
} else {
return false;
}
}
/**
* This function returns the number of uses of one key inside
* a whole XMLDBStructure. Useful to detect if the key must be
* locked. Return false if no uses are found.
*/
function getKeyUses($tablename, $keyname) {
$uses = array();
/// Check if some foreign key in the whole structure is using it
/// (by comparing the reftable and reffields with the fields in the key)
$mytable = $this->getTable($tablename);
$mykey = $mytable->getKey($keyname);
$alltables = $this->getTables();
if ($alltables && $mykey) {
foreach ($alltables as $table) {
$allkeys = $table->getKeys();
if ($allkeys) {
foreach ($allkeys as $key) {
if ($key->getType() != XMLDB_KEY_FOREIGN) {
continue;
}
if ($key->getRefTable() == $tablename &&
implode(',', $key->getRefFields()) == implode(',', $mykey->getFields())) {
$uses[] = 'table ' . $table->getName() . ' key ' . $key->getName();
}
}
}
}
}
/// Return result
if (!empty($uses)) {
return $uses;
} else {
return false;
}
}
/**
* This function returns the number of uses of one index inside
* a whole XMLDBStructure. Useful to detect if the index must be
* locked. Return false if no uses are found.
*/
function getIndexUses($tablename, $indexname) {
$uses = array();
/// Nothing to check, beause indexes haven't uses! Leave it here
/// for future checks...
/// Return result
if (!empty($uses)) {
return $uses;
} else {
return false;
}
}
/**
* This function will return all the errors found in one structure
* looking recursively inside each table/statement. Returns
* an array of errors or false
*/
function getAllErrors() {
$errors = array();
/// First the structure itself
if ($this->getError()) {
$errors[] = $this->getError();
}
/// Delegate to tables
if ($tables = $this->getTables()) {
foreach ($tables as $table) {
if ($tableerrors = $table->getAllErrors()) {
}
}
/// Add them to the errors array
if ($tableerrors) {
$errors = array_merge($errors, $tableerrors);
}
}
/// Delegate to statements
if ($statements = $this->getStatements()) {
foreach ($statements as $statement) {
if ($statement->getError()) {
$errors[] = $statement->getError();
}
}
}
/// Return decision
if (count($errors)) {
return $errors;
} else {
return false;
}
}
}
?>
+729
View File
@@ -0,0 +1,729 @@
<?php // $Id$
///////////////////////////////////////////////////////////////////////////
// //
// NOTICE OF COPYRIGHT //
// //
// Moodle - Modular Object-Oriented Dynamic Learning Environment //
// http://moodle.com //
// //
// Copyright (C) 2001-3001 Martin Dougiamas http://dougiamas.com //
// (C) 2001-3001 Eloy Lafuente (stronk7) http://contiento.com //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation; either version 2 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details: //
// //
// http://www.gnu.org/copyleft/gpl.html //
// //
///////////////////////////////////////////////////////////////////////////
/// This class represent one XMLDB table
class XMLDBTable extends XMLDBObject {
var $fields;
var $keys;
var $indexes;
/**
* Creates one new XMLDBTable
*/
function XMLDBTable($name) {
parent::XMLDBObject($name);
$this->fields = array();
$this->keys = array();
$this->indexes = array();
}
/**
* Add one field to the table, allowing to specify the desired order
* If it's not specified, then the field is added at the end
*/
function addField(&$field, $after=NULL) {
/// Calculate the previous and next fields
$prevfield = NULL;
$nextfield = NULL;
if (!$after) {
$allfields =& $this->getFields();
if (!empty($allfields)) {
end($allfields);
$prevfield =& $allfields[key($allfields)];
}
} else {
$prevfield =& $this->getField($after);
}
if ($prevfield && $prevfield->getNext()) {
$nextfield =& $this->getField($prevfield->getNext());
}
/// Set current field previous and next attributes
if ($prevfield) {
$field->setPrevious($prevfield->getName());
$prevfield->setNext($field->getName());
}
if ($nextfield) {
$field->setNext($nextfield->getName());
$nextfield->setPrevious($field->getName());
}
/// Some more attributes
$field->setLoaded(true);
$field->setChanged(true);
/// Add the new field
$this->fields[] = $field;
/// Reorder the field
$this->orderFields($this->fields);
/// Recalculate the hash
$this->calculateHash(true);
/// We have one new field, so the table has changed
$this->setChanged(true);
}
/**
* Add one key to the table, allowing to specify the desired order
* If it's not specified, then the key is added at the end
*/
function addKey(&$key, $after=NULL) {
/// Calculate the previous and next keys
$prevkey = NULL;
$nextkey = NULL;
if (!$after) {
$allkeys =& $this->getKeys();
if (!empty($allkeys)) {
end($allkeys);
$prevkey =& $allkeys[key($allkeys)];
}
} else {
$prevkey =& $this->getKey($after);
}
if ($prevkey && $prevkey->getNext()) {
$nextkey =& $this->getKey($prevkey->getNext());
}
/// Set current key previous and next attributes
if ($prevkey) {
$key->setPrevious($prevkey->getName());
$prevkey->setNext($key->getName());
}
if ($nextkey) {
$key->setNext($nextkey->getName());
$nextkey->setPrevious($key->getName());
}
/// Some more attributes
$key->setLoaded(true);
$key->setChanged(true);
/// Add the new key
$this->keys[] = $key;
/// Reorder the keys
$this->orderKeys($this->keys);
/// Recalculate the hash
$this->calculateHash(true);
/// We have one new field, so the table has changed
$this->setChanged(true);
}
/**
* Add one index to the table, allowing to specify the desired order
* If it's not specified, then the index is added at the end
*/
function addIndex(&$index, $after=NULL) {
/// Calculate the previous and next indexes
$previndex = NULL;
$nextindex = NULL;
if (!$after) {
$allindexes =& $this->getIndexes();
if (!empty($allindexes)) {
end($allindexes);
$previndex =& $allindexes[key($allindexes)];
}
} else {
$previndex =& $this->getIndex($after);
}
if ($previndex && $previndex->getNext()) {
$nextindex =& $this->getIndex($previndex->getNext());
}
/// Set current index previous and next attributes
if ($previndex) {
$index->setPrevious($previndex->getName());
$previndex->setNext($index->getName());
}
if ($nextindex) {
$index->setNext($nextindex->getName());
$nextindex->setPrevious($index->getName());
}
/// Some more attributes
$index->setLoaded(true);
$index->setChanged(true);
/// Add the new index
$this->indexes[] = $index;
/// Reorder the indexes
$this->orderIndexes($this->indexes);
/// Recalculate the hash
$this->calculateHash(true);
/// We have one new index, so the table has changed
$this->setChanged(true);
}
/**
* This function will return the array of fields in the table
*/
function &getFields() {
return $this->fields;
}
/**
* This function will return the array of keys in the table
*/
function &getKeys() {
return $this->keys;
}
/**
* This function will return the array of indexes in the table
*/
function &getIndexes() {
return $this->indexes;
}
/**
* Returns one XMLDBField
*/
function &getField($fieldname) {
$i = $this->findFieldInArray($fieldname);
if ($i !== NULL) {
return $this->fields[$i];
}
$null = NULL;
return $null;
}
/**
* Returns the position of one field in the array.
*/
function &findFieldInArray($fieldname) {
foreach ($this->fields as $i => $field) {
if ($fieldname == $field->getName()) {
return $i;
}
}
$null = NULL;
return $null;
}
/**
* This function will reorder the array of fields
*/
function orderFields() {
$result =& $this->orderElements($this->fields);
if ($result) {
$this->setFields($result);
return true;
} else {
return false;
}
}
/**
* Returns one XMLDBKey
*/
function &getKey($keyname) {
$i = $this->findKeyInArray($keyname);
if ($i !== NULL) {
return $this->keys[$i];
}
$null = NULL;
return $null;
}
/**
* Returns the position of one key in the array.
*/
function &findKeyInArray($keyname) {
foreach ($this->keys as $i => $key) {
if ($keyname == $key->getName()) {
return $i;
}
}
$null = NULL;
return $null;
}
/**
* This function will reorder the array of keys
*/
function orderKeys() {
$result =& $this->orderElements($this->keys);
if ($result) {
$this->setKeys($result);
return true;
} else {
return false;
}
}
/**
* Returns one XMLDBIndex
*/
function &getIndex($indexname) {
$i = $this->findIndexInArray($indexname);
if ($i !== NULL) {
return $this->indexes[$i];
}
$null = NULL;
return $null;
}
/**
* Returns the position of one index in the array.
*/
function &findIndexInArray($indexname) {
foreach ($this->indexes as $i => $index) {
if ($indexname == $index->getName()) {
return $i;
}
}
$null = NULL;
return $null;
}
/**
* This function will reorder the array of indexes
*/
function orderIndexes() {
$result =& $this->orderElements($this->indexes);
if ($result) {
$this->setIndexes($result);
return true;
} else {
return false;
}
}
/**
* This function will set the array of fields in the table
*/
function setFields($fields) {
$this->fields = $fields;
}
/**
* This function will set the array of keys in the table
*/
function setKeys($keys) {
$this->keys = $keys;
}
/**
* This function will set the array of indexes in the table
*/
function setIndexes($indexes) {
$this->indexes = $indexes;
}
/**
* Delete one field from the table
*/
function deleteField($fieldname) {
$field =& $this->getField($fieldname);
if ($field) {
$i = $this->findFieldInArray($fieldname);
$prevfield = NULL;
$nextfield = NULL;
/// Look for prev and next field
$prevfield =& $this->getField($field->getPrevious());
$nextfield =& $this->getField($field->getNext());
/// Change their previous and next attributes
if ($prevfield) {
$prevfield->setNext($field->getNext());
}
if ($nextfield) {
$nextfield->setPrevious($field->getPrevious());
}
/// Delete the field
unset($this->fields[$i]);
/// Reorder the whole structure
$this->orderFields($this->fields);
/// Recalculate the hash
$this->calculateHash(true);
/// We have one deleted field, so the table has changed
$this->setChanged(true);
}
}
/**
* Delete one key from the table
*/
function deleteKey($keyname) {
$key =& $this->getKey($keyname);
if ($key) {
$i = $this->findKeyInArray($keyname);
$prevkey = NULL;
$nextkey = NULL;
/// Look for prev and next key
$prevkey =& $this->getKey($key->getPrevious());
$nextkey =& $this->getKey($key->getNext());
/// Change their previous and next attributes
if ($prevkey) {
$prevkey->setNext($key->getNext());
}
if ($nextkey) {
$nextkey->setPrevious($key->getPrevious());
}
/// Delete the key
unset($this->keys[$i]);
/// Reorder the Keys
$this->orderKeys($this->keys);
/// Recalculate the hash
$this->calculateHash(true);
/// We have one deleted key, so the table has changed
$this->setChanged(true);
}
}
/**
* Delete one index from the table
*/
function deleteIndex($indexname) {
$index =& $this->getIndex($indexname);
if ($index) {
$i = $this->findIndexInArray($indexname);
$previndex = NULL;
$nextindex = NULL;
/// Look for prev and next index
$previndex =& $this->getIndex($index->getPrevious());
$nextindex =& $this->getIndex($index->getNext());
/// Change their previous and next attributes
if ($previndex) {
$previndex->setNext($index->getNext());
}
if ($nextindex) {
$nextindex->setPrevious($index->getPrevious());
}
/// Delete the index
unset($this->indexes[$i]);
/// Reorder the indexes
$this->orderIndexes($this->indexes);
/// Recalculate the hash
$this->calculateHash(true);
/// We have one deleted index, so the table has changed
$this->setChanged(true);
}
}
/**
* Load data from XML to the table
*/
function arr2XMLDBTable($xmlarr) {
$result = true;
/// Debug the table
/// traverse_xmlize($xmlarr); //Debug
/// print_object ($GLOBALS['traverse_array']); //Debug
/// $GLOBALS['traverse_array']=""; //Debug
/// Process table attributes (name, comment, previoustable and nexttable)
if (isset($xmlarr['@']['NAME'])) {
$this->name = trim($xmlarr['@']['NAME']);
} else {
$this->errormsg = 'Missing NAME attribute';
$result = false;
}
if (isset($xmlarr['@']['COMMENT'])) {
$this->comment = trim($xmlarr['@']['COMMENT']);
} else {
$this->errormsg = 'Missing COMMENT attribute';
$result = false;
}
if (isset($xmlarr['@']['PREVIOUS'])) {
$this->previous = trim($xmlarr['@']['PREVIOUS']);
}
if (isset($xmlarr['@']['NEXT'])) {
$this->next = trim($xmlarr['@']['NEXT']);
}
/// Iterate over fields
if (isset($xmlarr['#']['FIELDS']['0']['#']['FIELD'])) {
foreach ($xmlarr['#']['FIELDS']['0']['#']['FIELD'] as $xmlfield) {
if (!$result) { //Skip on error
continue;
}
$name = trim($xmlfield['@']['NAME']);
$field = new XMLDBField($name);
$field->arr2XMLDBField($xmlfield);
$this->fields[] = $field;
if (!$field->isLoaded()) {
$this->errormsg = 'Problem loading field ' . $name;
$result = false;
}
}
} else {
$this->errormsg = 'Missing FIELDS section';
$result = false;
}
/// Perform some general checks over fields
if ($result && $this->fields) {
/// Check field names are ok (lowercase, a-z _-)
if (!$this->checkNameValues($this->fields)) {
$this->errormsg = 'Some FIELDS name values are incorrect';
$result = false;
}
/// Check previous & next are ok (duplicates and existing fields)
if ($result && !$this->checkPreviousNextValues($this->fields)) {
$this->errormsg = 'Some FIELDS previous/next values are incorrect';
$result = false;
}
/// Order fields
if ($result && !$this->orderFields($this->fields)) {
$this->errormsg = 'Error ordering the fields';
$result = false;
}
}
/// Iterate over keys
if (isset($xmlarr['#']['KEYS']['0']['#']['KEY'])) {
foreach ($xmlarr['#']['KEYS']['0']['#']['KEY'] as $xmlkey) {
if (!$result) { //Skip on error
continue;
}
$name = trim($xmlkey['@']['NAME']);
$key = new XMLDBKey($name);
$key->arr2XMLDBKey($xmlkey);
$this->keys[] = $key;
if (!$key->isLoaded()) {
$this->errormsg = 'Problem loading key ' . $name;
$result = false;
}
}
} else {
$this->errormsg = 'Missing KEYS section (at least one PK must exist)';
$result = false;
}
/// Perform some general checks over keys
if ($result && $this->keys) {
/// Check keys names are ok (lowercase, a-z _-)
if (!$this->checkNameValues($this->keys)) {
$this->errormsg = 'Some KEYS name values are incorrect';
$result = false;
}
/// Check previous & next are ok (duplicates and existing keys)
if ($result && !$this->checkPreviousNextValues($this->keys)) {
$this->errormsg = 'Some KEYS previous/next values are incorrect';
$result = false;
}
/// Order keys
if ($result && !$this->orderKeys($this->keys)) {
$this->errormsg = 'Error ordering the keys';
$result = false;
}
/// TODO: Only one PK
/// TODO: Not keys with repeated fields
/// TODO: Check fields and reffieds exist in table
}
/// Iterate over indexes
if (isset($xmlarr['#']['INDEXES']['0']['#']['INDEX'])) {
foreach ($xmlarr['#']['INDEXES']['0']['#']['INDEX'] as $xmlindex) {
if (!$result) { //Skip on error
continue;
}
$name = trim($xmlindex['@']['NAME']);
$index = new XMLDBIndex($name);
$index->arr2XMLDBIndex($xmlindex);
$this->indexes[] = $index;
if (!$index->isLoaded()) {
$this->errormsg = 'Problem loading index ' . $name;
$result = false;
}
}
}
/// Perform some general checks over indexes
if ($result && $this->indexes) {
/// Check field names are ok (lowercase, a-z _-)
if (!$this->checkNameValues($this->indexes)) {
$this->errormsg = 'Some INDEXES name values are incorrect';
$result = false;
}
/// Check previous & next are ok (duplicates and existing INDEXES)
if ($result && !$this->checkPreviousNextValues($this->indexes)) {
$this->errormsg = 'Some INDEXES previous/next values are incorrect';
$result = false;
}
/// Order indexes
if ($result && !$this->orderIndexes($this->indexes)) {
$this->errormsg = 'Error ordering the indexes';
$result = false;
}
/// TODO: Not indexes with repeated fields
/// TODO: Check fields exist in table
}
/// Set some attributes
if ($result) {
$this->loaded = true;
}
$this->calculateHash();
return $result;
}
/**
* This function calculate and set the hash of one XMLDBTable
*/
function calculateHash($recursive = false) {
if (!$this->loaded) {
$this->hash = NULL;
} else {
$key = $this->name . $this->comment;
if ($this->fields) {
foreach ($this->fields as $fie) {
$field =& $this->getField($fie->getName());
if ($recursive) {
$field->calculateHash($recursive);
}
$key .= $field->getHash();
}
}
if ($this->keys) {
foreach ($this->keys as $ke) {
$k =& $this->getKey($ke->getName());
if ($recursive) {
$k->calculateHash($recursive);
}
$key .= $k->getHash();
}
}
if ($this->indexes) {
foreach ($this->indexes as $in) {
$index =& $this->getIndex($in->getName());
if ($recursive) {
$index->calculateHash($recursive);
}
$key .= $index->getHash();
}
}
$this->hash = md5($key);
}
}
/**
* This function will output the XML text for one table
*/
function xmlOutput() {
$o = '';
$o.= ' <TABLE NAME="' . $this->name . '"';
if ($this->comment) {
$o.= ' COMMENT="' . htmlspecialchars($this->comment) . '"';
}
if ($this->previous) {
$o.= ' PREVIOUS="' . $this->previous . '"';
}
if ($this->next) {
$o.= ' NEXT="' . $this->next . '"';
}
$o.= '>' . "\n";
/// Now the fields
if ($this->fields) {
$o.= ' <FIELDS>' . "\n";
foreach ($this->fields as $field) {
$o.= $field->xmlOutput();
}
$o.= ' </FIELDS>' . "\n";
}
/// Now the keys
if ($this->keys) {
$o.= ' <KEYS>' . "\n";
foreach ($this->keys as $key) {
$o.= $key->xmlOutput();
}
$o.= ' </KEYS>' . "\n";
}
/// Now the indexes
if ($this->indexes) {
$o.= ' <INDEXES>' . "\n";
foreach ($this->indexes as $index) {
$o.= $index->xmlOutput();
}
$o.= ' </INDEXES>' . "\n";
}
$o.= ' </TABLE>' . "\n";
return $o;
}
/**
* This function will return all the errors found in one table
* looking recursively inside each field/key/index. Returns
* an array of errors or false
*/
function getAllErrors() {
$errors = array();
/// First the table itself
if ($this->getError()) {
$errors[] = $this->getError();
}
/// Delegate to fields
if ($fields = $this->getFields()) {
foreach ($fields as $field) {
if ($field->getError()) {
$errors[] = $field->getError();
}
}
}
/// Delegate to keys
if ($keys = $this->getKeys()) {
foreach ($keys as $key) {
if ($key->getError()) {
$errors[] = $key->getError();
}
}
}
/// Delegate to indexes
if ($indexes = $this->getIndexes()) {
foreach ($indexes as $index) {
if ($index->getError()) {
$errors[] = $index->getError();
}
}
}
/// Return decision
if (count($errors)) {
return $errors;
} else {
return false;
}
}
/**
* This function will return the SQL code needed to create the table for the specified DB and
* prefix. Just one simple wrapper over generators.
*/
function getCreateTableSQL ($dbtype, $prefix) {
$classname = 'XMLDB' . $dbtype;
$generator = new $classname();
$generator->setPrefix($prefix);
return $generator->getCreateTableSQL($this);
}
}
?>
@@ -0,0 +1,228 @@
<?php // $Id$
///////////////////////////////////////////////////////////////////////////
// //
// NOTICE OF COPYRIGHT //
// //
// Moodle - Modular Object-Oriented Dynamic Learning Environment //
// http://moodle.com //
// //
// Copyright (C) 2001-3001 Martin Dougiamas http://dougiamas.com //
// (C) 2001-3001 Eloy Lafuente (stronk7) http://contiento.com //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation; either version 2 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details: //
// //
// http://www.gnu.org/copyleft/gpl.html //
// //
///////////////////////////////////////////////////////////////////////////
/// This class represent the base generator class where all the
/// needed functions to generate proper SQL are defined.
/// If fact, this class generate SQL code to be used against MySQL
/// so the rest of classes will inherit, by default, the same logic.
/// Functions will be overriden as needed to generate correct SQL.
class XMLDBmysql {
var $quote_string = '`'; // String used to quote names
var $primary_keys = true; // Does the constructor build primary keys
var $unique_keys = false; // Does the constructor build unique keys
var $foreign_keys = false; // Does the constructor build foreign keys
var $primary_index = false;// Does the constructor need to build one index for primary keys
var $unique_index = true; // Does the constructor need to build one index for unique keys
var $foreign_index = true; // Does the constructor need to build one index for foreign keys
var $prefix; // Prefix to be used for all the DB objects
/**
* Creates one new XMLDBmysql
*/
function XMLDBmysql() {
global $CFG;
$this->prefix = '';
}
/**
* Set the prefix
*/
function setPrefix($prefix) {
$this->prefix = $prefix;
}
/**
* Given one XMLDB Type, lenght and decimals, returns the DB proper SQL type
*/
function getType ($xmldb_type, $xmldb_length=null, $xmldb_decimals=null) {
switch ($xmldb_type) {
case XMLDB_TYPE_INTEGER: // From http://mysql.com/doc/refman/5.0/en/numeric-types.html!
if (empty($xmldb_length)) {
$xmldb_length = 10;
}
if ($xmldb_length > 9) {
$dbtype = 'BIGINT';
$xmldb_length = 10;
} else if ($xmldb_length > 6) {
$dbtype = 'INT';
} else if ($xmldb_length > 4) {
$dbtype = 'MEDIUMINT';
} else if ($xmldb_length > 2) {
$dbtype = 'SMALLINT';
} else {
$dbtype = 'TINTINT';
}
$dbtype .= '(' . $xmldb_length . ')';
break;
case XMLDB_TYPE_NUMBER:
$dbtype = 'DECIMAL';
if (!empty($xmldb_length)) {
$dbtype .= '(' . $xmldb_length;
if (!empty($xmldb_decimals)) {
$dbtype .= ',' . $xmldb_decimals;
}
$dbtype .= ')';
}
break;
case XMLDB_TYPE_FLOAT:
$dbtype = 'FLOAT';
if (!empty($xmldb_length)) {
$dbtype .= '(' . $xmldb_length;
if (!empty($xmldb_decimals)) {
$dbtype .= ',' . $xmldb_decimals;
}
$dbtype .= ')';
}
break;
case XMLDB_TYPE_CHAR:
$dbtype = 'VARCHAR';
if (!empty($xmldb_length)) {
$xmldb_length='255';
}
$dbtype .= '(' . $xmldb_length . ')';
break;
case XMLDB_TYPE_TEXT:
if (empty($xmldb_length)) {
$xmldb_length = 'small';
}
if ($xmldb_length = 'small') {
$dbtype = 'TEXT';
} else if ($xmldb_length = 'medium') {
$dbtype = 'MEDIUMTEXT';
} else {
$dbtype = 'BIGTEXT';
}
break;
case XMLDB_TYPE_BINARY:
if (empty($xmldb_length)) {
$xmldb_length = 'small';
}
if ($xmldb_length = 'small') {
$dbtype = 'BLOB';
} else if ($xmldb_length = 'medium') {
$dbtype = 'MEDIUMBLOB';
} else {
$dbtype = 'BIGBLOB';
}
break;
case XMLDB_TYPE_DATETIME:
$dbtype = 'DATETIME';
}
return $dbtype;
}
/**
* Given one correct XMLDBTable, returns the complete SQL lines to create it
*/
function getCreateTableSQL($xmldb_table) {
/// Table header
$table = 'CREATE TABLE ' . $this->getEncQuoted($this->prefix . $xmldb_table->getName()) . ' (';
if (!$xmldb_fields = $xmldb_table->getFields()) {
return false;
}
/// Add the fields, separated by commas
foreach ($xmldb_fields as $xmldb_field) {
$table .= "\n " . $this->getCreateFieldSQL($xmldb_field) . ',';
}
/// Table footer, trim the latest comma
$table = trim($table,',');
$table .= "\n)";
if ($xmldb_table->getComment()) {
$table .= " COMMENT='" . $xmldb_table->getComment() . "';\n\n";
}
return $table;
}
/**
* Given one correct XMLDBField, returns the complete SQL line to create it
*/
function getCreateFieldSQL($xmldb_field) {
/// The name
$field = $this->getEncQuoted($xmldb_field->getName());
/// The type and length (if the field isn't enum)
if (!$xmldb_field->getEnum()) {
$field .= ' ' . $this->getType($xmldb_field->getType(), $xmldb_field->getLength(), $xmldb_field->getDecimals());
} else {
/// If enum, do it with its values
$field .= ' enum(' . implode(', ', $xmldb_field->getEnumValues()) . ')';
}
/// The unsigned
if ($xmldb_field->getType() == XMLDB_TYPE_INTEGER ||
$xmldb_field->getType() == XMLDB_TYPE_NUMBER ||
$xmldb_field->getType() == XMLDB_TYPE_FLOAT) {
if ($xmldb_field->getUnsigned()) {
$field .= ' unsigned';
}
}
/// The not null
if ($xmldb_field->getNotNull()) {
$field .= ' NOT NULL';
}
/// The sequence
if ($xmldb_field->getSequence()) {
$field .= ' auto_increment';
}
/// The default
if ($xmldb_field->getDefault() != NULL) {
$field .= ' default ';
if ($xmldb_field->getType() == XMLDB_TYPE_CHAR ||
$xmldb_field->getType() == XMLDB_TYPE_TEXT) {
$field .= "'" . $xmldb_field->getDefault() . "'";
} else {
$field .= $xmldb_field->getDefault();
}
} else {
/// We force default '' for not null char columns without proper default
/// some day this should be out!
if ($xmldb_field->getType() == XMLDB_TYPE_CHAR &&
$xmldb_field->getNotNull()) {
$field .= ' default ' . "''";
}
}
return $field;
}
/**
* Given any string, enclose it by the proper quotes
*/
function getEncQuoted($string) {
return $this->quote_string . $string . $this->quote_string;
}
}
?>
+62
View File
@@ -0,0 +1,62 @@
<!ELEMENT FIELD EMPTY >
<!ATTLIST FIELD DECIMALS NMTOKEN #IMPLIED >
<!ATTLIST FIELD DEFAULT NMTOKEN #IMPLIED >
<!ATTLIST FIELD ENUM ( false | true ) #REQUIRED >
<!ATTLIST FIELD ENUMVALUES CDATA #IMPLIED >
<!ATTLIST FIELD LENGTH NMTOKEN #REQUIRED >
<!ATTLIST FIELD NAME NMTOKEN #REQUIRED >
<!ATTLIST FIELD NEXT NMTOKEN #IMPLIED >
<!ATTLIST FIELD NOTNULL ( false | true ) #REQUIRED >
<!ATTLIST FIELD PREVIOUS NMTOKEN #IMPLIED >
<!ATTLIST FIELD SEQUENCE ( false | true ) #REQUIRED >
<!ATTLIST FIELD TYPE ( binary | char | float | int | number | text ) #REQUIRED >
<!ATTLIST FIELD UNSIGNED ( false | true ) #IMPLIED >
<!ELEMENT FIELDS ( FIELD+ ) >
<!ELEMENT INDEX EMPTY >
<!ATTLIST INDEX COMMENT CDATA #IMPLIED >
<!ATTLIST INDEX FIELDS CDATA #REQUIRED >
<!ATTLIST INDEX NAME NMTOKEN #REQUIRED >
<!ATTLIST INDEX NEXT NMTOKEN #IMPLIED >
<!ATTLIST INDEX PREVIOUS NMTOKEN #IMPLIED >
<!ATTLIST INDEX UNIQUE ( false | true ) #REQUIRED >
<!ELEMENT INDEXES ( INDEX+ ) >
<!ELEMENT KEY EMPTY >
<!ATTLIST KEY COMMENT CDATA #IMPLIED >
<!ATTLIST KEY FIELDS CDATA #REQUIRED >
<!ATTLIST KEY NAME NMTOKEN #REQUIRED >
<!ATTLIST KEY NEXT NMTOKEN #IMPLIED >
<!ATTLIST KEY PREVIOUS NMTOKEN #IMPLIED >
<!ATTLIST KEY TYPE ( primary | unique | foreign ) #REQUIRED >
<!ELEMENT KEYS ( KEY+ ) >
<!ELEMENT SENTENCE EMPTY >
<!ATTLIST SENTENCE TEXT CDATA #REQUIRED >
<!ELEMENT SENTENCES ( SENTENCE+ ) >
<!ELEMENT STATEMENT ( SENTENCES ) >
<!ATTLIST STATEMENT COMMENT CDATA #REQUIRED >
<!ATTLIST STATEMENT NAME CDATA #REQUIRED >
<!ATTLIST STATEMENT TABLE NMTOKEN #REQUIRED >
<!ATTLIST STATEMENT TYPE NMTOKEN #REQUIRED >
<!ELEMENT STATEMENTS ( STATEMENT ) >
<!ELEMENT TABLE ( FIELDS, KEYS, INDEXES? ) >
<!ATTLIST TABLE COMMENT CDATA #REQUIRED >
<!ATTLIST TABLE NAME ID #REQUIRED >
<!ATTLIST TABLE NEXT NMTOKEN #IMPLIED >
<!ATTLIST TABLE PREVIOUS NMTOKEN #IMPLIED >
<!ELEMENT TABLES ( TABLE+ ) >
<!ELEMENT XMLDB ( TABLES, STATEMENTS ) >
<!ATTLIST XMLDB COMMENT CDATA #REQUIRED >
<!ATTLIST XMLDB PATH CDATA #REQUIRED >
<!ATTLIST XMLDB VERSION NMTOKEN #REQUIRED >
+197
View File
@@ -0,0 +1,197 @@
<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="FIELD">
<xs:complexType>
<xs:attribute name="ENUM" use="required">
<xs:simpleType>
<xs:restriction base="xs:NMTOKEN">
<xs:enumeration value="false" />
<xs:enumeration value="true" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="LENGTH" type="xs:NMTOKEN" use="required" />
<xs:attribute name="DECIMALS" type="xs:NMTOKEN" use="optional" />
<xs:attribute name="NEXT" type="xs:NMTOKEN" use="optional" />
<xs:attribute name="SEQUENCE" use="required">
<xs:simpleType>
<xs:restriction base="xs:NMTOKEN">
<xs:enumeration value="false" />
<xs:enumeration value="true" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="ENUMVALUES" type="xs:string" use="optional" />
<xs:attribute name="DEFAULT" type="xs:NMTOKEN" use="optional" />
<xs:attribute name="TYPE" use="required">
<xs:simpleType>
<xs:restriction base="xs:NMTOKEN">
<xs:enumeration value="binary" />
<xs:enumeration value="char" />
<xs:enumeration value="float" />
<xs:enumeration value="int" />
<xs:enumeration value="number" />
<xs:enumeration value="text" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="UNSIGNED" use="optional">
<xs:simpleType>
<xs:restriction base="xs:NMTOKEN">
<xs:enumeration value="false" />
<xs:enumeration value="true" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="PREVIOUS" type="xs:NMTOKEN" use="optional" />
<xs:attribute name="NOTNULL" use="required">
<xs:simpleType>
<xs:restriction base="xs:NMTOKEN">
<xs:enumeration value="false" />
<xs:enumeration value="true" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="NAME" type="xs:NMTOKEN" use="required" />
</xs:complexType>
</xs:element>
<xs:element name="FIELDS">
<xs:complexType>
<xs:sequence>
<xs:element ref="FIELD" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="INDEX">
<xs:complexType>
<xs:attribute name="PREVIOUS" type="xs:NMTOKEN" use="optional" />
<xs:attribute name="COMMENT" type="xs:string" use="optional" />
<xs:attribute name="UNIQUE" use="required">
<xs:simpleType>
<xs:restriction base="xs:NMTOKEN">
<xs:enumeration value="false" />
<xs:enumeration value="true" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="NAME" type="xs:NMTOKEN" use="required" />
<xs:attribute name="FIELDS" type="xs:string" use="required" />
<xs:attribute name="NEXT" type="xs:NMTOKEN" use="optional" />
</xs:complexType>
</xs:element>
<xs:element name="INDEXES">
<xs:complexType>
<xs:sequence>
<xs:element ref="INDEX" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="KEY">
<xs:complexType>
<xs:attribute name="PREVIOUS" type="xs:NMTOKEN" use="optional" />
<xs:attribute name="COMMENT" type="xs:string" use="optional" />
<xs:attribute name="NAME" use="required">
<xs:simpleType>
<xs:restriction base="xs:NMTOKEN">
<xs:enumeration value="name" />
<xs:enumeration value="plugin_name" />
<xs:enumeration value="primary" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="FIELDS" type="xs:string" use="required" />
<xs:attribute name="TYPE" use="required">
<xs:simpleType>
<xs:restriction base="xs:NMTOKEN">
<xs:enumeration value="primary" />
<xs:enumeration value="unique" />
<xs:enumeration value="foreign" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="NEXT" type="xs:NMTOKEN" use="optional" />
</xs:complexType>
</xs:element>
<xs:element name="KEYS">
<xs:complexType>
<xs:sequence>
<xs:element ref="KEY" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="SENTENCE">
<xs:complexType>
<xs:attribute name="TEXT" type="xs:string" use="required" />
</xs:complexType>
</xs:element>
<xs:element name="SENTENCES">
<xs:complexType>
<xs:sequence>
<xs:element ref="SENTENCE" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="STATEMENT">
<xs:complexType>
<xs:sequence>
<xs:element ref="SENTENCES" />
</xs:sequence>
<xs:attribute name="COMMENT" type="xs:string" use="required" />
<xs:attribute name="TABLE" type="xs:NMTOKEN" use="required" />
<xs:attribute name="NAME" type="xs:string" use="required" />
<xs:attribute name="TYPE" type="xs:NMTOKEN" use="required" />
</xs:complexType>
</xs:element>
<xs:element name="STATEMENTS">
<xs:complexType>
<xs:sequence>
<xs:element ref="STATEMENT" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="TABLE">
<xs:complexType>
<xs:sequence>
<xs:element ref="FIELDS" />
<xs:element ref="KEYS" />
<xs:element ref="INDEXES" minOccurs="0" />
</xs:sequence>
<xs:attribute name="PREVIOUS" type="xs:NMTOKEN" use="optional" />
<xs:attribute name="COMMENT" type="xs:string" use="required" />
<xs:attribute name="NAME" type="xs:ID" use="required" />
<xs:attribute name="NEXT" type="xs:NMTOKEN" use="optional" />
</xs:complexType>
</xs:element>
<xs:element name="TABLES">
<xs:complexType>
<xs:sequence>
<xs:element ref="TABLE" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="XMLDB">
<xs:complexType>
<xs:sequence>
<xs:element ref="TABLES" />
<xs:element ref="STATEMENTS" />
</xs:sequence>
<xs:attribute name="PATH" type="xs:string" use="required" />
<xs:attribute name="COMMENT" type="xs:string" use="required" />
<xs:attribute name="VERSION" type="xs:NMTOKEN" use="required" />
</xs:complexType>
</xs:element>
</xs:schema>