diff --git a/admin/xmldb/README.txt b/admin/xmldb/README.txt
new file mode 100644
index 00000000000..fd1b3a4ccf5
--- /dev/null
+++ b/admin/xmldb/README.txt
@@ -0,0 +1,78 @@
+XMLDB - Base classes and edition interface.
+
+Complete Documentation:
+
+ http://docs.moodle.org/en/XMLDB_Defining_one_XML_structure
+
+Ciao, Eloy Lafuente (stronk7)
+
+========== ========== ========== ========== ==========
+========== ========== HISTORY ========== ==========
+========== ========== ========== ========== ==========
+
+2006-08-07 - Editor working on production
+
+The editor has been used succesfully to build
+a bunch of install.xml files and everything
+seems to be working properly.
+
+========== ========== ========== ========== ==========
+
+2006-07-11 - PHP4 compatible release
+
+Now everything seems to be working under PHP 4. What
+a horrible OOP implementation!
+
+Note that write permissions to */db dirs are required.
+
+Now working in the 3 missing forms, to manually edit
+fields, keys and indexes.
+
+Ciao, Eloy Lafuente (stronk7)
+
+========== ========== ========== ========== ==========
+
+2006-07-11 - Important notes
+
+I've just discovered this some seconds ago, in order
+to test properly the XMLDB classes and editor:
+
+1.- PHP 5 required for now. Will change this soon.
+2.- Perms to "apache" user needed in */db
+ dirs in order to allow the XMDBD interface
+ to write files.
+
+Ciao, Eloy Lafuente (stronk7)
+
+========== ========== ========== ========== ==========
+
+2006-07-11 - Initial commit
+
+This directory contains the XMLDB classes to be used
+under Moodle > 1.7 to store all the DB info in a
+neutral form (classes dir). Also it contains one simple
+interface to edit all those structures.
+
+To install and test it, simply copy the whole xmldb directory
+under your moodle/admin dir and point your browser (as admin)
+to http://your.server/moodle/admin/xmldb
+
+The edition interface isn't completed yet (it laks 3 more forms
+to edit fields, keys and indexes) and there isn't any lang file
+(although I hope everything is really clear).
+
+The edition interface includes one reverse-engineering tool that
+provides an easy way to retroffit and to generate any table from
+MySQL to the new XMLDB format.
+
+Once the XMLDB format was approved, we'll be able to build all the
+"generators" needed in order to use it to create Moodle DB structures
+for each RDBMS flavour.
+
+Once the interface was finished (2-3 days from now) related documentation
+will be sent to http://docs.moodle.org/en/XML_database_schema in order
+to comment/modify/approve the final XML format.
+
+All the code is, obviously GPL, with its copyrights and so on...
+
+Ciao, Eloy Lafuente (stronk7) :-)
diff --git a/admin/xmldb/actions/XMLDBAction.class.php b/admin/xmldb/actions/XMLDBAction.class.php
new file mode 100644
index 00000000000..1847471641c
--- /dev/null
+++ b/admin/xmldb/actions/XMLDBAction.class.php
@@ -0,0 +1,191 @@
+init();
+ }
+
+ /**
+ * Constructor to keep PHP5 happy
+ */
+ function __construct() {
+ $this->XMLDBAction();
+ }
+
+ /**
+ * Init method, every subclass will have its own,
+ * always calling the parent one
+ */
+ function init() {
+ $this->does_generate = ACTION_NONE;
+ $this->title = strtolower(get_class($this));
+ $this->str = array();
+ $this->output = NULL;
+ $this->errormsg = NULL;
+ $this->subaction = NULL;
+ }
+
+ /**
+ * returns the type of output of the file
+ */
+ function getDoesGenerate() {
+ return $this->does_generate;
+ }
+
+ /**
+ * getError method, returns the last error string.
+ * Used if the invoke() methods returns false
+ */
+ function getError() {
+ return $this->errormsg;
+ }
+
+ /**
+ * getOutput method, returns the output generated by the action.
+ * Used after execution of the invoke() methods if they return true
+ */
+ function getOutput() {
+ return $this->output;
+ }
+
+ /**
+ * getPostAtion method, returns the action to launch after executing
+ * another one
+ */
+ function getPostAction() {
+ return $this->postaction;
+ }
+
+ /**
+ * getTitle method returns the title of the action (that is part
+ * of the $str array attribute
+ */
+ function getTitle() {
+ return $this->str['title'];
+ }
+
+ /**
+ * loadStrings method, loads the required strings specified in the
+ * array parameter
+ */
+ function loadStrings($strings) {
+ /// Load some commonly used strings
+ $this->str['title'] = get_string($this->title, 'xmldb');
+
+ /// Now process the $strings array loading it in the $str atribute
+ if ($strings) {
+ foreach ($strings as $key => $module) {
+ $this->str[$key] = get_string($key, $module);
+ }
+ }
+ }
+
+ /**
+ * main invoke method, it simply sets the postaction attribute
+ * if possible
+ */
+ function invoke() {
+
+ global $SESSION;
+
+ /// If we are used any dir, save it in the lastused session object
+ /// Some actions can use it to perform positioning
+ if ($lastused = optional_param ('dir', NULL, PARAM_CLEAN)) {
+ $SESSION->lastused = stripslashes_safe($lastused);
+ }
+
+ $this->postaction = optional_param ('postaction', NULL, PARAM_ALPHAEXT);
+ /// Avoid being recursive
+ if ($this->title == $this->postaction) {
+ $this->postaction = NULL;
+ }
+ }
+
+ /**
+ * launch method, used to easily call invoke methods between actions
+ */
+ function launch($action) {
+
+ global $CFG;
+
+ /// Get the action path and invoke it
+ $actionsroot = "$CFG->dirroot/$CFG->admin/xmldb/actions";
+ $actionclass = $action . '.class.php';
+ $actionpath = "$actionsroot/$action/$actionclass";
+
+ /// Load and invoke the proper action
+ $result = false;
+ if (file_exists($actionpath) && is_readable($actionpath)) {
+ require_once($actionpath);
+ if ($xmldb_action = new $action) {
+ $result = $xmldb_action->invoke();
+ if ($result) {
+ if ($xmldb_action->does_generate != ACTION_NONE &&
+ $xmldb_action->getOutput()) {
+ $this->does_generate = $xmldb_action->does_generate;
+ $this->title = $xmldb_action->title;
+ $this->str = $xmldb_action->str;
+ $this->output .= $xmldb_action->getOutput();
+ }
+ } else {
+ $this->errormsg = $xmldb_action->getError();
+ }
+ } else {
+ $this->errormsg = "Error: cannot instantiate class (actions/$action/$actionclass)";
+ }
+ } else {
+ $this->errormsg = "Error: wrong action specified ($action)";
+ }
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/create_xml_file/create_xml_file.class.php b/admin/xmldb/actions/create_xml_file/create_xml_file.class.php
new file mode 100644
index 00000000000..8ec80ffce2b
--- /dev/null
+++ b/admin/xmldb/actions/create_xml_file/create_xml_file.class.php
@@ -0,0 +1,108 @@
+can_subaction = ACTION_NONE;
+ //$this->can_subaction = ACTION_HAVE_SUBACTIONS;
+
+ /// Set own custom attributes
+
+ /// Get needed strings
+ $this->loadStrings(array(
+ /// 'key' => 'module',
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_NONE;
+ //$this->does_generate = ACTION_GENERATE_HTML;
+
+ /// These are always here
+ global $CFG, $XMLDB;
+
+ /// Do the job, setting result as needed
+
+ /// Get the dir containing the file
+ $dirpath = required_param('dir', PARAM_CLEAN);
+ $dirpath = stripslashes_safe($dirpath);
+ $file = $dirpath . '/install.xml';
+
+ /// Some variables
+ $xmlpath = dirname(str_replace($CFG->dirroot . '/', '', $file));
+ $xmlversion = userdate(time(), '%Y%m%d', 99, false);
+ $xmlcomment = 'XMLDB file for Moodle ' . dirname($xmlpath);
+
+ $xmltable = strtolower(basename(dirname($xmlpath)));
+
+ /// Initial contents
+ $c = '' . "\n";
+ $c.= ' ' . "\n";
+ $c.= ' ' . "\n";
+ $c.= ' ' . "\n";
+ $c.= ' ' . "\n";
+ $c.= ' ' . "\n";
+ $c.= ' ' . "\n";
+ $c.= ' ' . "\n";
+ $c.= ' ' . "\n";
+ $c.= ' ' . "\n";
+ $c.= '
' . "\n";
+ $c.= ' ' . "\n";
+ $c.= ' ';
+
+ if (!file_put_contents($file, $c)) {
+ $errormsg = 'Error creando fichero ' . $file;
+ $result = false;
+ }
+
+ /// Launch postaction if exists
+ if ($this->getPostAction() && $result) {
+ return $this->launch($this->getPostAction());
+ }
+
+ /// Return ok if arrived here
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/delete_field/delete_field.class.php b/admin/xmldb/actions/delete_field/delete_field.class.php
new file mode 100644
index 00000000000..b7b7ba5e3b6
--- /dev/null
+++ b/admin/xmldb/actions/delete_field/delete_field.class.php
@@ -0,0 +1,140 @@
+loadStrings(array(
+ 'confirmdeletefield' => 'xmldb',
+ 'yes' => '',
+ 'no' => ''
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_GENERATE_HTML;
+
+ /// These are always here
+ global $CFG, $XMLDB;
+
+ /// Do the job, setting result as needed
+
+ /// Get the dir containing the file
+ $dirpath = required_param('dir', PARAM_CLEAN);
+ $dirpath = stripslashes_safe($dirpath);
+ $tableparam = required_param('table', PARAM_CLEAN);
+ $fieldparam = required_param('field', PARAM_CLEAN);
+
+ $confirmed = optional_param('confirmed', false, PARAM_BOOL);
+
+ /// If not confirmed, show confirmation box
+ if (!$confirmed) {
+ $o = '
';
+ $o.= ' ';
+ $o.= ' ' . $this->str['confirmdeletefield'] . ' ' . $fieldparam . '
';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= '
';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= '
';
+ $o.= ' ';
+ $o.= '
';
+ $o.= ' ';
+ $o.= '
';
+
+ $this->output = $o;
+ } else {
+ /// Get the edited dir
+ if (!empty($XMLDB->editeddirs)) {
+ if (isset($XMLDB->editeddirs[$dirpath])) {
+ $dbdir =& $XMLDB->dbdirs[$dirpath];
+ $editeddir =& $XMLDB->editeddirs[$dirpath];
+ if ($editeddir) {
+ $structure =& $editeddir->xml_file->getStructure();
+ /// Move adjacent fields prev and next attributes
+ $tables =& $structure->getTables();
+ $table =& $structure->getTable($tableparam);
+ $fields =& $table->getFields();
+ $field =& $table->getField($fieldparam);
+ if ($field->getPrevious()) {
+ $prev =& $table->getField($field->getPrevious());
+ $prev->setNext($field->getNext());
+ }
+ if ($field->getNext()) {
+ $next =& $table->getField($field->getNext());
+ $next->setPrevious($field->getPrevious());
+ }
+ /// Remove the field
+ $table->deleteField($fieldparam);
+
+ /// Recalculate the hash
+ $structure->calculateHash(true);
+
+ /// If the hash has changed from the original one, change the version
+ /// and mark the structure as changed
+ $origstructure =& $dbdir->xml_file->getStructure();
+ if ($structure->getHash() != $origstructure->getHash()) {
+ $structure->setVersion(userdate(time(), '%Y%m%d', 99, false));
+ $structure->setChanged(true);
+ }
+ }
+ }
+ }
+ }
+
+ /// Launch postaction if exists (leave this here!)
+ if ($this->getPostAction() && $result) {
+ return $this->launch($this->getPostAction());
+ }
+
+ /// Return ok if arrived here
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/delete_index/delete_index.class.php b/admin/xmldb/actions/delete_index/delete_index.class.php
new file mode 100644
index 00000000000..aab33f8affd
--- /dev/null
+++ b/admin/xmldb/actions/delete_index/delete_index.class.php
@@ -0,0 +1,140 @@
+loadStrings(array(
+ 'confirmdeleteindex' => 'xmldb',
+ 'yes' => '',
+ 'no' => ''
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_GENERATE_HTML;
+
+ /// These are always here
+ global $CFG, $XMLDB;
+
+ /// Do the job, setting result as needed
+
+ /// Get the dir containing the file
+ $dirpath = required_param('dir', PARAM_CLEAN);
+ $dirpath = stripslashes_safe($dirpath);
+ $tableparam = required_param('table', PARAM_CLEAN);
+ $indexparam = required_param('index', PARAM_CLEAN);
+
+ $confirmed = optional_param('confirmed', false, PARAM_BOOL);
+
+ /// If not confirmed, show confirmation box
+ if (!$confirmed) {
+ $o = '';
+ $o.= ' ';
+ $o.= ' ' . $this->str['confirmdeleteindex'] . ' ' . $indexparam . '
';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= '
';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= '
';
+ $o.= ' ';
+ $o.= '
';
+ $o.= ' ';
+ $o.= '
';
+
+ $this->output = $o;
+ } else {
+ /// Get the edited dir
+ if (!empty($XMLDB->editeddirs)) {
+ if (isset($XMLDB->editeddirs[$dirpath])) {
+ $dbdir =& $XMLDB->dbdirs[$dirpath];
+ $editeddir =& $XMLDB->editeddirs[$dirpath];
+ if ($editeddir) {
+ $structure =& $editeddir->xml_file->getStructure();
+ /// Move adjacent indexes prev and next attributes
+ $tables =& $structure->getTables();
+ $table =& $structure->getTable($tableparam);
+ $indexes =& $table->getIndexes();
+ $index =& $table->getIndex($indexparam);
+ if ($index->getPrevious()) {
+ $prev =& $table->getIndex($index->getPrevious());
+ $prev->setNext($index->getNext());
+ }
+ if ($index->getNext()) {
+ $next =& $table->getIndex($index->getNext());
+ $next->setPrevious($index->getPrevious());
+ }
+ /// Remove the index
+ $table->deleteIndex($indexparam);
+
+ /// Recalculate the hash
+ $structure->calculateHash(true);
+
+ /// If the hash has changed from the original one, change the version
+ /// and mark the structure as changed
+ $origstructure =& $dbdir->xml_file->getStructure();
+ if ($structure->getHash() != $origstructure->getHash()) {
+ $structure->setVersion(userdate(time(), '%Y%m%d', 99, false));
+ $structure->setChanged(true);
+ }
+ }
+ }
+ }
+ }
+
+ /// Launch postaction if exists (leave this here!)
+ if ($this->getPostAction() && $result) {
+ return $this->launch($this->getPostAction());
+ }
+
+ /// Return ok if arrived here
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/delete_key/delete_key.class.php b/admin/xmldb/actions/delete_key/delete_key.class.php
new file mode 100644
index 00000000000..462a3c6ab5f
--- /dev/null
+++ b/admin/xmldb/actions/delete_key/delete_key.class.php
@@ -0,0 +1,140 @@
+loadStrings(array(
+ 'confirmdeletekey' => 'xmldb',
+ 'yes' => '',
+ 'no' => ''
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_GENERATE_HTML;
+
+ /// These are always here
+ global $CFG, $XMLDB;
+
+ /// Do the job, setting result as needed
+
+ /// Get the dir containing the file
+ $dirpath = required_param('dir', PARAM_CLEAN);
+ $dirpath = stripslashes_safe($dirpath);
+ $tableparam = required_param('table', PARAM_CLEAN);
+ $keyparam = required_param('key', PARAM_CLEAN);
+
+ $confirmed = optional_param('confirmed', false, PARAM_BOOL);
+
+ /// If not confirmed, show confirmation box
+ if (!$confirmed) {
+ $o = '';
+ $o.= ' ';
+ $o.= ' ' . $this->str['confirmdeletekey'] . ' ' . $keyparam . '
';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= '
';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= '
';
+ $o.= ' ';
+ $o.= '
';
+ $o.= ' ';
+ $o.= '
';
+
+ $this->output = $o;
+ } else {
+ /// Get the edited dir
+ if (!empty($XMLDB->editeddirs)) {
+ if (isset($XMLDB->editeddirs[$dirpath])) {
+ $dbdir =& $XMLDB->dbdirs[$dirpath];
+ $editeddir =& $XMLDB->editeddirs[$dirpath];
+ if ($editeddir) {
+ $structure =& $editeddir->xml_file->getStructure();
+ /// Move adjacent keys prev and next attributes
+ $tables =& $structure->getTables();
+ $table =& $structure->getTable($tableparam);
+ $keys =& $table->getKeys();
+ $key =& $table->getKey($keyparam);
+ if ($key->getPrevious()) {
+ $prev =& $table->getKey($key->getPrevious());
+ $prev->setNext($key->getNext());
+ }
+ if ($key->getNext()) {
+ $next =& $table->getKey($key->getNext());
+ $next->setPrevious($key->getPrevious());
+ }
+ /// Remove the key
+ $table->deleteKey($keyparam);
+
+ /// Recalculate the hash
+ $structure->calculateHash(true);
+
+ /// If the hash has changed from the original one, change the version
+ /// and mark the structure as changed
+ $origstructure =& $dbdir->xml_file->getStructure();
+ if ($structure->getHash() != $origstructure->getHash()) {
+ $structure->setVersion(userdate(time(), '%Y%m%d', 99, false));
+ $structure->setChanged(true);
+ }
+ }
+ }
+ }
+ }
+
+ /// Launch postaction if exists (leave this here!)
+ if ($this->getPostAction() && $result) {
+ return $this->launch($this->getPostAction());
+ }
+
+ /// Return ok if arrived here
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/delete_sentence/delete_sentence.class.php b/admin/xmldb/actions/delete_sentence/delete_sentence.class.php
new file mode 100644
index 00000000000..1b3035cea78
--- /dev/null
+++ b/admin/xmldb/actions/delete_sentence/delete_sentence.class.php
@@ -0,0 +1,133 @@
+loadStrings(array(
+ 'confirmdeletesentence' => 'xmldb',
+ 'yes' => '',
+ 'no' => ''
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_GENERATE_HTML;
+
+ /// These are always here
+ global $CFG, $XMLDB;
+
+ /// Do the job, setting result as needed
+
+ /// Get the dir containing the file
+ $dirpath = required_param('dir', PARAM_CLEAN);
+ $dirpath = stripslashes_safe($dirpath);
+ $statementparam = required_param('statement', PARAM_CLEAN);
+ $sentenceparam = required_param('sentence', PARAM_CLEAN);
+
+ $confirmed = optional_param('confirmed', false, PARAM_BOOL);
+
+ /// If not confirmed, show confirmation box
+ if (!$confirmed) {
+ $o = '';
+ $o.= ' ';
+ $o.= ' ' . $this->str['confirmdeletesentence'] . '
';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= '
';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= '
';
+ $o.= ' ';
+ $o.= '
';
+ $o.= ' ';
+ $o.= '
';
+
+ $this->output = $o;
+ } else {
+ /// Get the edited dir
+ if (!empty($XMLDB->editeddirs)) {
+ if (isset($XMLDB->editeddirs[$dirpath])) {
+ $dbdir =& $XMLDB->dbdirs[$dirpath];
+ $editeddir =& $XMLDB->editeddirs[$dirpath];
+ if ($editeddir) {
+ $structure =& $editeddir->xml_file->getStructure();
+ $statements =& $structure->getStatements();
+ $statement =& $structure->getStatement($statementparam);
+ $sentences =& $statement->getSentences();
+ /// Remove the sentence
+ unset ($sentences[$sentenceparam]);
+
+ /// The statement has changed
+ $statement->setChanged(true);
+
+ /// Recalculate the hash
+ $structure->calculateHash(true);
+
+ /// If the hash has changed from the original one, change the version
+ /// and mark the structure as changed
+ $origstructure =& $dbdir->xml_file->getStructure();
+ if ($structure->getHash() != $origstructure->getHash()) {
+ $structure->setVersion(userdate(time(), '%Y%m%d', 99, false));
+ $structure->setChanged(true);
+ }
+ }
+ }
+ }
+ }
+
+ /// Launch postaction if exists (leave this here!)
+ if ($this->getPostAction() && $result) {
+ return $this->launch($this->getPostAction());
+ }
+
+ /// Return ok if arrived here
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/delete_statement/delete_statement.class.php b/admin/xmldb/actions/delete_statement/delete_statement.class.php
new file mode 100644
index 00000000000..51d54c1964c
--- /dev/null
+++ b/admin/xmldb/actions/delete_statement/delete_statement.class.php
@@ -0,0 +1,115 @@
+loadStrings(array(
+ 'confirmdeletestatement' => 'xmldb',
+ 'yes' => '',
+ 'no' => ''
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_GENERATE_HTML;
+
+ /// These are always here
+ global $CFG, $XMLDB;
+
+ /// Do the job, setting result as needed
+
+ /// Get the dir containing the file
+ $dirpath = required_param('dir', PARAM_CLEAN);
+ $dirpath = stripslashes_safe($dirpath);
+ $statementparam = required_param('statement', PARAM_CLEAN);
+
+ $confirmed = optional_param('confirmed', false, PARAM_BOOL);
+
+ /// If not confirmed, show confirmation box
+ if (!$confirmed) {
+ $o = '';
+ $o.= ' ';
+ $o.= ' ' . $this->str['confirmdeletestatement'] . ' ' . $statementparam . '
';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= '
';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= '
';
+ $o.= ' ';
+ $o.= '
';
+ $o.= ' ';
+ $o.= '
';
+
+ $this->output = $o;
+ } else {
+ /// Get the edited dir
+ if (!empty($XMLDB->editeddirs)) {
+ if (isset($XMLDB->editeddirs[$dirpath])) {
+ $dbdir =& $XMLDB->dbdirs[$dirpath];
+ $editeddir =& $XMLDB->editeddirs[$dirpath];
+ if ($editeddir) {
+ $structure =& $editeddir->xml_file->getStructure();
+ /// Remove the table
+ $structure->deleteStatement($statementparam);
+ }
+ }
+ }
+ }
+
+ /// Launch postaction if exists (leave this here!)
+ if ($this->getPostAction() && $result) {
+ return $this->launch($this->getPostAction());
+ }
+
+ /// Return ok if arrived here
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/delete_table/delete_table.class.php b/admin/xmldb/actions/delete_table/delete_table.class.php
new file mode 100644
index 00000000000..537a3e0a61f
--- /dev/null
+++ b/admin/xmldb/actions/delete_table/delete_table.class.php
@@ -0,0 +1,115 @@
+loadStrings(array(
+ 'confirmdeletetable' => 'xmldb',
+ 'yes' => '',
+ 'no' => ''
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_GENERATE_HTML;
+
+ /// These are always here
+ global $CFG, $XMLDB;
+
+ /// Do the job, setting result as needed
+
+ /// Get the dir containing the file
+ $dirpath = required_param('dir', PARAM_CLEAN);
+ $dirpath = stripslashes_safe($dirpath);
+ $tableparam = required_param('table', PARAM_CLEAN);
+
+ $confirmed = optional_param('confirmed', false, PARAM_BOOL);
+
+ /// If not confirmed, show confirmation box
+ if (!$confirmed) {
+ $o = '';
+ $o.= ' ';
+ $o.= ' ' . $this->str['confirmdeletetable'] . ' ' . $tableparam . '
';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= '
';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= '
';
+ $o.= ' ';
+ $o.= '
';
+ $o.= ' ';
+ $o.= '
';
+
+ $this->output = $o;
+ } else {
+ /// Get the edited dir
+ if (!empty($XMLDB->editeddirs)) {
+ if (isset($XMLDB->editeddirs[$dirpath])) {
+ $dbdir =& $XMLDB->dbdirs[$dirpath];
+ $editeddir =& $XMLDB->editeddirs[$dirpath];
+ if ($editeddir) {
+ $structure =& $editeddir->xml_file->getStructure();
+ /// Remove the table
+ $structure->deleteTable($tableparam);
+ }
+ }
+ }
+ }
+
+ /// Launch postaction if exists (leave this here!)
+ if ($this->getPostAction() && $result) {
+ return $this->launch($this->getPostAction());
+ }
+
+ /// Return ok if arrived here
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/delete_xml_file/delete_xml_file.class.php b/admin/xmldb/actions/delete_xml_file/delete_xml_file.class.php
new file mode 100644
index 00000000000..27d42081c2a
--- /dev/null
+++ b/admin/xmldb/actions/delete_xml_file/delete_xml_file.class.php
@@ -0,0 +1,111 @@
+loadStrings(array(
+ 'confirmdeletexmlfile' => 'xmldb',
+ 'yes' => '',
+ 'no' => ''
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_GENERATE_HTML;
+
+ /// These are always here
+ global $CFG, $XMLDB;
+
+ /// Do the job, setting result as needed
+
+ /// Get the dir containing the file
+ $dirpath = required_param('dir', PARAM_CLEAN);
+ $dirpath = stripslashes_safe($dirpath);
+
+ $confirmed = optional_param('confirmed', false, PARAM_BOOL);
+
+ /// If not confirmed, show confirmation box
+ if (!$confirmed) {
+ $o = '';
+ $o.= ' ';
+ $o.= ' ' . $this->str['confirmdeletexmlfile'] . ' ' . $dirpath . '
';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= '
';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= '
';
+ $o.= ' ';
+ $o.= '
';
+ $o.= ' ';
+ $o.= '
';
+
+ $this->output = $o;
+ } else {
+ /// Get the original dir and delete the xml file
+ if (!empty($XMLDB->dbdirs)) {
+ if (isset($XMLDB->dbdirs[$dirpath])) {
+ $dbdir =& $XMLDB->dbdirs[$dirpath];
+ if ($dbdir) {
+ @unlink($dirpath . '/install.xml');
+ }
+ }
+ }
+ }
+
+ /// Launch postaction if exists (leave this here!)
+ if ($this->getPostAction() && $result) {
+ return $this->launch($this->getPostAction());
+ }
+
+ /// Return ok if arrived here
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/edit_field/edit_field.class.php b/admin/xmldb/actions/edit_field/edit_field.class.php
new file mode 100644
index 00000000000..f21f4b690a4
--- /dev/null
+++ b/admin/xmldb/actions/edit_field/edit_field.class.php
@@ -0,0 +1,204 @@
+loadStrings(array(
+ 'change' => 'xmldb',
+ 'vieworiginal' => 'xmldb',
+ 'viewedited' => 'xmldb',
+ 'yes' => '',
+ 'no' => '',
+ 'back' => 'xmldb'
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_GENERATE_HTML;
+
+ /// These are always here
+ global $CFG, $XMLDB;
+
+ /// Do the job, setting result as needed
+ /// Get the dir containing the file
+ $dirpath = required_param('dir', PARAM_CLEAN);
+ $dirpath = stripslashes_safe($dirpath);
+
+ /// Get the correct dirs
+ if (!empty($XMLDB->dbdirs)) {
+ $dbdir =& $XMLDB->dbdirs[$dirpath];
+ } else {
+ return false;
+ }
+ if (!empty($XMLDB->editeddirs)) {
+ $editeddir =& $XMLDB->editeddirs[$dirpath];
+ $structure =& $editeddir->xml_file->getStructure();
+ }
+
+ /// ADD YOUR CODE HERE
+
+ /// Fetch request data
+ $tableparam = required_param('table', PARAM_CLEAN);
+ if (!$table =& $structure->getTable($tableparam)) {
+ $this->errormsg = 'Wrong table specified: ' . $tableparm;
+ return false;
+ }
+ $fieldparam = required_param('field', PARAM_CLEAN);
+ if (!$field =& $table->getField($fieldparam)) {
+ /// Arriving here from a name change, looking for the new field name
+ $fieldparam = required_param('name', PARAM_CLEAN);
+ $field =& $table->getField($fieldparam);
+ }
+
+ $dbdir =& $XMLDB->dbdirs[$dirpath];
+ $origstructure =& $dbdir->xml_file->getStructure();
+
+ /// Add the main form
+ $o = '';
+ /// Calculate the buttons
+ $b = ' ';
+ /// The view original XML button
+ if ($table->getField($fieldparam)) {
+ $b .= ' [' . $this->str['vieworiginal'] . '] ';
+ } else {
+ $b .= ' [' . $this->str['vieworiginal'] . ']';
+ }
+ /// The view edited XML button
+ if ($field->hasChanged()) {
+ $b .= ' [' . $this->str['viewedited'] . '] ';
+ } else {
+ $b .= ' [' . $this->str['viewedited'] . ']';
+ }
+ /// The back to edit table button
+ $b .= ' [' . $this->str['back'] . '] ';
+ $b .= '
';
+ $o .= $b;
+
+ $this->output = $o;
+
+ /// Launch postaction if exists (leave this here!)
+ if ($this->getPostAction() && $result) {
+ return $this->launch($this->getPostAction());
+ }
+
+ /// Return ok if arrived here
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/edit_field/edit_field.js b/admin/xmldb/actions/edit_field/edit_field.js
new file mode 100644
index 00000000000..d9727ae0467
--- /dev/null
+++ b/admin/xmldb/actions/edit_field/edit_field.js
@@ -0,0 +1,187 @@
+/// $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 //
+// //
+///////////////////////////////////////////////////////////////////////////
+
+
+/// Register the needed events
+
+ onload=function() {
+ /// Adjust the form on load
+ transformForm();
+
+ /// Get the required fields
+ var typeField = document.getElementById('menutype');
+ var sequenceField = document.getElementById('menusequence');
+ var enumField = document.getElementById('menuenum');
+
+ /// Register the rest of events
+ if (typeField.addEventListener) {
+ /// Standard
+ typeField.addEventListener('change', transformForm, false);
+ sequenceField.addEventListener('change', transformForm, false);
+ enumField.addEventListener('change', transformForm, false);
+ } else {
+ /// IE 5.5
+ typeField.attachEvent('onchange', transformForm);
+ sequenceField.attachEvent('onchange', transformForm);
+ enumField.attachEvent('onchange', transformForm);
+ }
+ }
+
+/**
+ * This function controls all modifications to perform when any field changes
+ */
+function transformForm(event) {
+
+/// Initialize all the needed variables
+ var typeField = document.getElementById('menutype');
+ var lengthField = document.getElementById('length');
+ var decimalsField = document.getElementById('decimals');
+ var unsignedField = document.getElementById('menuunsigned');
+ var notnullField = document.getElementById('menunotnull');
+ var sequenceField = document.getElementById('menusequence');
+ var enumField = document.getElementById('menuenum');
+ var enumvaluesField = document.getElementById('enumvalues');
+ var defaultField = document.getElementById('default');
+
+ var lengthTip = document.getElementById('lengthtip');
+ var decimalsTip = document.getElementById('decimalstip');
+
+/// Initially, enable everything
+ decimalsField.disabled = false;
+ unsignedField.disabled = false;
+ notnullField.disabled = false;
+ sequenceField.disabled = false;
+ enumField.disabled = false;
+ enumvaluesField.disabled = false;
+ defaultField.disabled = false;
+
+/// Based on enum, disable some items
+ if (enumField.value == '0') {
+ enumvaluesField.disabled = true;
+ enumvaluesField.value = '';
+ };
+
+/// Based on sequence, disable some items
+ if (sequenceField.value == '1') {
+ unsignedField.disabled = true;
+ unsignedField.value = '1';
+ notnullField.disabled = true;
+ notnullField.value = '1';
+ defaultField.disabled = true;
+ defaultField.value = '';
+ enumField.disabled = true;
+ enumField.value = '0';
+ enumvaluesField.disabled = true;
+ enumvaluesField.value = '';
+ }
+
+
+/// Based on type, disable some items
+ switch (typeField.value) {
+ case '1': // XMLDB_TYPE_INTEGER
+ lengthTip.innerHTML = ' 1...20';
+ decimalsTip.innerHTML = '';
+ decimalsField.disabled = true;
+ decimalsField.value = '';
+ enumField.disabled = true;
+ enumField.value = '0';
+ enumvaluesField.disabled = true;
+ enumvaluesField.value = '';
+ break;
+ case '2': // XMLDB_TYPE_NUMBER
+ lengthTip.innerHTML = ' 1...20';
+ decimalsTip.innerHTML = ' 0...length or empty';
+ enumField.disabled = true;
+ enumField.value = '0';
+ enumvaluesField.disabled = true;
+ enumvaluesField.value = '';
+ break;
+ case '3': // XMLDB_TYPE_FLOAT
+ lengthTip.innerHTML = ' 1...20 or empty';
+ decimalsTip.innerHTML = ' 0...length or empty';
+ enumField.disabled = true;
+ enumField.value = '0';
+ enumvaluesField.disabled = true;
+ enumvaluesField.value = '';
+ break;
+ case '4': // XMLDB_TYPE_CHAR
+ lengthTip.innerHTML = ' 1...255';
+ decimalsTip.innerHTML = '';
+ decimalsField.disabled = true;
+ decimalsField.value = '';
+ unsignedField.disabled = true;
+ unsignedField.value = '0';
+ sequenceField.disabled = true;
+ sequenceField.value = '0';
+ break;
+ case '5': // XMLDB_TYPE_TEXT
+ lengthTip.innerHTML = ' small, medium, big';
+ decimalsTip.innerHTML = '';
+ decimalsField.disabled = true;
+ decimalsField.value = '';
+ unsignedField.disabled = true;
+ unsignedField.value = '0';
+ sequenceField.disabled = true;
+ sequenceField.value = '0';
+ defaultField.disabled = true;
+ defaultField.value = '';
+ break;
+ case '6': // XMLDB_TYPE_BINARY
+ lengthTip.innerHTML = ' small, medium, big';
+ decimalsTip.innerHTML = '';
+ decimalsField.disabled = true;
+ decimalsField.value = '';
+ unsignedField.disabled = true;
+ unsignedField.value = '0';
+ sequenceField.disabled = true;
+ sequenceField.value = '0';
+ enumField.disabled = true;
+ enumField.value = '0';
+ enumvaluesField.disabled = true;
+ enumvaluesField.value = '';
+ defaultField.disabled = true;
+ defaultField.value = '';
+ break;
+ case '7': // XMLDB_TYPE_DATETIME
+ lengthTip.innerHTML = '';
+ lengthField.disabled = true;
+ lengthField.value = '';
+ decimalsTip.innerHTML = '';
+ decimalsField.disabled = true;
+ decimalsField.value = '';
+ unsignedField.disabled = true;
+ unsignedField.value = '0';
+ sequenceField.disabled = true;
+ sequenceField.value = '0';
+ enumField.disabled = true;
+ enumField.value = '0';
+ enumvaluesField.disabled = true;
+ enumvaluesField.value = '';
+ defaultField.disabled = true;
+ defaultField.value = '';
+ break;
+ }
+}
diff --git a/admin/xmldb/actions/edit_field_save/edit_field_save.class.php b/admin/xmldb/actions/edit_field_save/edit_field_save.class.php
new file mode 100644
index 00000000000..e0d9b885d84
--- /dev/null
+++ b/admin/xmldb/actions/edit_field_save/edit_field_save.class.php
@@ -0,0 +1,346 @@
+loadStrings(array(
+ 'fieldnameempty' => 'xmldb',
+ 'incorrectfieldname' => 'xmldb',
+ 'duplicatefieldname' => 'xmldb',
+ 'integerincorrectlength' => 'xmldb',
+ 'numberincorrectlength' => 'xmldb',
+ 'floatincorrectlength' => 'xmldb',
+ 'charincorrectlength' => 'xmldb',
+ 'textincorrectlength' => 'xmldb',
+ 'binaryincorrectlength' => 'xmldb',
+ 'numberincorrectdecimals' => 'xmldb',
+ 'floatincorrectdecimals' => 'xmldb',
+ 'enumvaluesincorrect' => 'xmldb',
+ 'wronglengthforenum' => 'xmldb',
+ 'defaultincorrect' => 'xmldb',
+ 'administration' => ''
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_NONE;
+ //$this->does_generate = ACTION_GENERATE_HTML;
+
+ /// These are always here
+ global $CFG, $XMLDB;
+
+ /// Do the job, setting result as needed
+
+ /// Get parameters
+ $dirpath = required_param('dir', PARAM_CLEAN);
+ $dirpath = stripslashes_safe($dirpath);
+
+ $tableparam = strtolower(required_param('table', PARAM_CLEAN));
+ $fieldparam = strtolower(required_param('field', PARAM_CLEAN));
+ $name = substr(trim(strtolower(optional_param('name', $fieldparam, PARAM_CLEAN))),0,30);
+
+ $comment = required_param('comment', PARAM_CLEAN);
+ $comment = trim(stripslashes_safe($comment));
+
+ $type = required_param('type', PARAM_INT);
+ $length = strtolower(optional_param('length', NULL, PARAM_CLEAN));
+ $decimals = optional_param('decimals', NULL, PARAM_CLEAN);
+ $unsigned = optional_param('unsigned', false, PARAM_BOOL);
+ $notnull = optional_param('notnull', false, PARAM_BOOL);
+ $sequence = optional_param('sequence', false, PARAM_BOOL);
+ $enum = optional_param('enum', false, PARAM_BOOL);
+ $enumvalues = optional_param('enumvalues', 0, PARAM_CLEAN);
+ $enumvalues = trim(stripslashes_safe($enumvalues));
+ $default = optional_param('default', NULL, PARAM_CLEAN);
+ $default = trim(stripslashes_safe($default));
+
+ $editeddir =& $XMLDB->editeddirs[$dirpath];
+ $structure =& $editeddir->xml_file->getStructure();
+ $table =& $structure->getTable($tableparam);
+ $field =& $table->getField($fieldparam);
+ $oldhash = $field->getHash();
+
+ $errors = array(); /// To store all the errors found
+
+ /// Perform some automatic asumptions
+ if ($sequence) {
+ $unsigned = true;
+ $notnull = true;
+ $enum = false;
+ $default = NULL;
+ }
+ if ($type != XMLDB_TYPE_NUMBER && $type != XMLDB_TYPE_FLOAT) {
+ $decimals = NULL;
+ }
+ if ($type != XMLDB_TYPE_CHAR && $type != XMLDB_TYPE_TEXT) {
+ $enum = false;
+ }
+ if ($type == XMLDB_TYPE_BINARY) {
+ $default = NULL;
+ }
+ if (!$enum) {
+ $enumvalues = NULL;
+ }
+ if ($default === '') {
+ $default = NULL;
+ }
+
+ /// Perform some checks
+ /// Check empty name
+ if (empty($name)) {
+ $errors[] = $this->str['fieldnameempty'];
+ }
+ /// Check incorrect name
+ if ($name == 'changeme') {
+ $errors[] = $this->str['incorrectfieldname'];
+ }
+ /// Check duplicate name
+ if ($fieldparam != $name && $table->getField($name)) {
+ $errors[] = $this->str['duplicatefieldname'];
+ }
+ /// Integer checks
+ if ($type == XMLDB_TYPE_INTEGER) {
+ if (!(is_numeric($length) && !empty($length) && intval($length)==floatval($length) &&
+ $length > 0 && $length <= 20)) {
+ $errors[] = $this->str['integerincorrectlength'];
+ }
+ if (!(empty($default) || (is_numeric($default) &&
+ !empty($default) &&
+ intval($default)==floatval($default)))) {
+ $errors[] = $this->str['defaultincorrect'];
+ }
+ }
+ /// Number checks
+ if ($type == XMLDB_TYPE_NUMBER) {
+ if (!(is_numeric($length) && !empty($length) && intval($length)==floatval($length) &&
+ $length > 0 && $length <= 20)) {
+ $errors[] = $this->str['numberincorrectlength'];
+ }
+ if (!(empty($decimals) || (is_numeric($decimals) &&
+ !empty($decimals) &&
+ intval($decimals)==floatval($decimals) &&
+ $decimals >= 0 &&
+ $decimals < $length))) {
+ $errors[] = $this->str['numberincorrectdecimals'];
+ }
+ if (!(empty($default) || (is_numeric($default) &&
+ !empty($default)))) {
+ $errors[] = $this->str['defaultincorrect'];
+ }
+ }
+ /// Float checks
+ if ($type == XMLDB_TYPE_FLOAT) {
+ if (!(empty($length) || (is_numeric($length) &&
+ !empty($length) &&
+ intval($length)==floatval($length) &&
+ $length > 0 &&
+ $length <= 20))) {
+ $errors[] = $this->str['floatincorrectlength'];
+ }
+ if (!(empty($decimals) || (is_numeric($decimals) &&
+ !empty($decimals) &&
+ intval($decimals)==floatval($decimals) &&
+ $decimals >= 0 &&
+ $decimals < $length))) {
+ $errors[] = $this->str['floatincorrectdecimals'];
+ }
+ if (!(empty($default) || (is_numeric($default) &&
+ !empty($default)))) {
+ $errors[] = $this->str['defaultincorrect'];
+ }
+ }
+ /// Char checks
+ if ($type == XMLDB_TYPE_CHAR) {
+ if (!(is_numeric($length) && !empty($length) && intval($length)==floatval($length) &&
+ $length > 0 && $length <= 255)) {
+ $errors[] = $this->str['charincorrectlength'];
+ }
+ if ($default !== NULL && $default !== '') {
+ if (substr($default, 0, 1) == "'" ||
+ substr($default, -1, 1) == "'") {
+ $errors[] = $this->str['defaultincorrect'];
+ }
+ }
+ }
+ /// Text checks
+ if ($type == XMLDB_TYPE_TEXT) {
+ if ($length != 'small' &&
+ $length != 'medium' &&
+ $length != 'big') {
+ $errors[] = $this->str['textincorrectlength'];
+ }
+ if ($default !== NULL && $default !== '') {
+ if (substr($default, 0, 1) == "'" ||
+ substr($default, -1, 1) == "'") {
+ $errors[] = $this->str['defaultincorrect'];
+ }
+ }
+ }
+ /// Binary checks
+ if ($type == XMLDB_TYPE_BINARY) {
+ if ($length != 'small' &&
+ $length != 'medium' &&
+ $length != 'big') {
+ $errors[] = $this->str['binaryincorrectlength'];
+ }
+ }
+ /// Enum checks
+ if ($enum) {
+ $enumerr = false;
+ $enumarr = explode(',',$enumvalues);
+ $maxlength = 0;
+ if ($enumarr) {
+ foreach ($enumarr as $key => $enumelement) {
+ /// Clear some spaces
+ $enumarr[$key] = trim($enumelement);
+ $enumelement = trim($enumelement);
+ /// Calculate needed length
+ $le = strlen(str_replace("'", '', $enumelement));
+ if ($le > $maxlength) {
+ $maxlength = $le;
+ }
+ /// Skip if under error
+ if ($enumerr) {
+ continue;
+ }
+ /// Look for quoted strings
+ if (substr($enumelement, 0, 1) != "'" ||
+ substr($enumelement, -1, 1) != "'") {
+ $enumerr = true;
+ }
+ }
+ } else {
+ $enumerr = true;
+ }
+ if ($enumerr) {
+ $errors[] = $this->str['enumvaluesincorrect'];
+ } else {
+ $enumvalues = $enumarr;
+ }
+ if ($length < $maxlength) {
+ $errors[] = $this->str['wronglengthforenum'];
+ }
+ }
+
+ if (!empty($errors)) {
+ $tempfield = new XMLDBField($name);
+ $tempfield->setType($type);
+ $tempfield->setLength($length);
+ $tempfield->setDecimals($decimals);
+ $tempfield->setUnsigned($unsigned);
+ $tempfield->setNotNull($notnull);
+ $tempfield->setSequence($sequence);
+ $tempfield->setEnum($enum);
+ $tempfield->setEnumValues($enumvalues);
+ $tempfield->setDefault($default);
+ /// Prepare the output
+ $site = get_site();
+ print_header("$site->shortname: XMLDB",
+ "$site->fullname",
+ "" . $this->str['administration'] . " -> XMLDB ");
+ notice ('' .implode(', ', $errors) . '
+ ' . $tempfield->readableInfo(),
+ 'index.php?action=edit_field&field=' .$field->getName() . '&table=' . $table->getName() . '&dir=' . urlencode($dirpath));
+ die; /// re-die :-P
+ }
+
+ /// Continue if we aren't under errors
+ if (empty($errors)) {
+ /// If there is one name change, do it, changing the prev and next
+ /// atributes of the adjacent fields
+ if ($fieldparam != $name) {
+ $field->setName($name);
+ if ($field->getPrevious()) {
+ $prev =& $table->getField($field->getPrevious());
+ $prev->setNext($name);
+ $prev->setChanged(true);
+ }
+ if ($field->getNext()) {
+ $next =& $table->getField($field->getNext());
+ $next->setPrevious($name);
+ $next->setChanged(true);
+ }
+ }
+
+ /// Set comment
+ $field->setComment($comment);
+
+ /// Set the rest of fields
+ $field->setType($type);
+ $field->setLength($length);
+ $field->setDecimals($decimals);
+ $field->setUnsigned($unsigned);
+ $field->setNotNull($notnull);
+ $field->setSequence($sequence);
+ $field->setEnum($enum);
+ $field->setEnumValues($enumvalues);
+ $field->setDefault($default);
+
+ /// If the hash has changed from the old one, change the version
+ /// and mark the structure as changed
+ $field->calculateHash(true);
+ if ($oldhash != $field->getHash()) {
+ $field->setChanged(true);
+ $table->setChanged(true);
+ /// Recalculate the structure hash
+ $structure->calculateHash(true);
+ $structure->setVersion(userdate(time(), '%Y%m%d', 99, false));
+ /// Mark as changed
+ $structure->setChanged(true);
+ }
+
+ /// Launch postaction if exists (leave this here!)
+ if ($this->getPostAction() && $result) {
+ return $this->launch($this->getPostAction());
+ }
+ }
+
+ /// Return ok if arrived here
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/edit_index/edit_index.class.php b/admin/xmldb/actions/edit_index/edit_index.class.php
new file mode 100644
index 00000000000..61a44f18033
--- /dev/null
+++ b/admin/xmldb/actions/edit_index/edit_index.class.php
@@ -0,0 +1,159 @@
+loadStrings(array(
+ 'change' => 'xmldb',
+ 'vieworiginal' => 'xmldb',
+ 'viewedited' => 'xmldb',
+ 'yes' => '',
+ 'no' => '',
+ 'back' => 'xmldb'
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_GENERATE_HTML;
+
+ /// These are always here
+ global $CFG, $XMLDB;
+
+ /// Do the job, setting result as needed
+ /// Get the dir containing the file
+ $dirpath = required_param('dir', PARAM_CLEAN);
+ $dirpath = stripslashes_safe($dirpath);
+
+ /// Get the correct dirs
+ if (!empty($XMLDB->dbdirs)) {
+ $dbdir =& $XMLDB->dbdirs[$dirpath];
+ } else {
+ return false;
+ }
+ if (!empty($XMLDB->editeddirs)) {
+ $editeddir =& $XMLDB->editeddirs[$dirpath];
+ $structure =& $editeddir->xml_file->getStructure();
+ }
+
+ /// ADD YOUR CODE HERE
+
+ /// Fetch request data
+ $tableparam = required_param('table', PARAM_CLEAN);
+ if (!$table =& $structure->getTable($tableparam)) {
+ $this->errormsg = 'Wrong table specified: ' . $tableparm;
+ return false;
+ }
+ $indexparam = required_param('index', PARAM_CLEAN);
+ if (!$index =& $table->getIndex($indexparam)) {
+ /// Arriving here from a name change, looking for the new key name
+ $indexparam = required_param('name', PARAM_CLEAN);
+ $index =& $table->getIndex($indexparam);
+ }
+
+ $dbdir =& $XMLDB->dbdirs[$dirpath];
+ $origstructure =& $dbdir->xml_file->getStructure();
+
+ /// Add the main form
+ $o = '
';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= ' ';
+ /// Calculate the buttons
+ $b = ' ';
+ /// The view original XML button
+ if ($table->getIndex($indexparam)) {
+ $b .= ' [' . $this->str['vieworiginal'] . '] ';
+ } else {
+ $b .= ' [' . $this->str['vieworiginal'] . ']';
+ }
+ /// The view edited XML button
+ if ($index->hasChanged()) {
+ $b .= ' [' . $this->str['viewedited'] . '] ';
+ } else {
+ $b .= ' [' . $this->str['viewedited'] . ']';
+ }
+ /// The back to edit table button
+ $b .= ' [' . $this->str['back'] . '] ';
+ $b .= '
';
+ $o .= $b;
+
+ $this->output = $o;
+
+ /// Launch postaction if exists (leave this here!)
+ if ($this->getPostAction() && $result) {
+ return $this->launch($this->getPostAction());
+ }
+
+ /// Return ok if arrived here
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/edit_index_save/edit_index_save.class.php b/admin/xmldb/actions/edit_index_save/edit_index_save.class.php
new file mode 100644
index 00000000000..374d52a2ba1
--- /dev/null
+++ b/admin/xmldb/actions/edit_index_save/edit_index_save.class.php
@@ -0,0 +1,220 @@
+loadStrings(array(
+ 'indexnameempty' => 'xmldb',
+ 'incorrectindexname' => 'xmldb',
+ 'duplicateindexname' => 'xmldb',
+ 'nofieldsspecified' => 'xmldb',
+ 'duplicatefieldsused' => 'xmldb',
+ 'fieldsnotintable' => 'xmldb',
+ 'fieldsusedinkey' => 'xmldb',
+ 'fieldsusedinindex' => 'xmldb',
+ 'administration' => ''
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_NONE;
+ //$this->does_generate = ACTION_GENERATE_HTML;
+
+ /// These are always here
+ global $CFG, $XMLDB;
+
+ /// Do the job, setting result as needed
+
+ /// Get parameters
+ $dirpath = required_param('dir', PARAM_CLEAN);
+ $dirpath = stripslashes_safe($dirpath);
+
+ $tableparam = strtolower(required_param('table', PARAM_CLEAN));
+ $indexparam = strtolower(required_param('index', PARAM_CLEAN));
+ $name = trim(strtolower(optional_param('name', $indexparam, PARAM_CLEAN)));
+
+ $comment = required_param('comment', PARAM_CLEAN);
+ $comment = trim(stripslashes_safe($comment));
+
+ $unique = required_param('unique', PARAM_INT);
+ $fields = required_param('fields', PARAM_CLEAN);
+ $fields = str_replace(' ', '', trim(strtolower(stripslashes_safe($fields))));
+
+ $editeddir =& $XMLDB->editeddirs[$dirpath];
+ $structure =& $editeddir->xml_file->getStructure();
+ $table =& $structure->getTable($tableparam);
+ $index =& $table->getIndex($indexparam);
+ $oldhash = $index->getHash();
+
+ $errors = array(); /// To store all the errors found
+
+ /// Perform some checks
+ /// Check empty name
+ if (empty($name)) {
+ $errors[] = $this->str['indexnameempty'];
+ }
+ /// Check incorrect name
+ if ($name == 'changeme') {
+ $errors[] = $this->str['incorrectindexname'];
+ }
+ /// Check duplicate name
+ if ($indexparam != $name && $table->getIndex($name)) {
+ $errors[] = $this->str['duplicateindexname'];
+ }
+ $fieldsarr = explode(',', $fields);
+ /// Check the fields isn't empty
+ if (empty($fieldsarr[0])) {
+ $errors[] = $this->str['nofieldsspecified'];
+ } else {
+ /// Check that there aren't duplicate column names
+ $uniquearr = array_unique($fieldsarr);
+ if (count($fieldsarr) != count($uniquearr)) {
+ $errors[] = $this->str['duplicatefieldsused'];
+ }
+ /// Check that all the fields in belong to the table
+ foreach ($fieldsarr as $field) {
+ if (!$table->getField($field)) {
+ $errors[] = $this->str['fieldsnotintable'];
+ break;
+ }
+ }
+ /// Check that there isn't any key using exactly the same fields
+ $tablekeys = $table->getKeys();
+ if ($tablekeys) {
+ foreach ($tablekeys as $tablekey) {
+ $keyfieldsarr = $tablekey->getFields();
+ /// Compare both arrays, looking for diferences
+ $diferences = array_merge(array_diff($fieldsarr, $keyfieldsarr), array_diff($keyfieldsarr, $fieldsarr));
+ if (empty($diferences)) {
+ $errors[] = $this->str['fieldsusedinkey'];
+ break;
+ }
+ }
+ }
+ /// Check that there isn't any index using exactlt the same fields
+ $tableindexes = $table->getIndexes();
+ if ($tableindexes) {
+ foreach ($tableindexes as $tableindex) {
+ /// Skip checking against itself
+ if ($indexparam == $tableindex->getName()) {
+ continue;
+ }
+ $indexfieldsarr = $tableindex->getFields();
+ /// Compare both arrays, looking for diferences
+ $diferences = array_merge(array_diff($fieldsarr, $indexfieldsarr), array_diff($indexfieldsarr, $fieldsarr));
+ if (empty($diferences)) {
+ $errors[] = $this->str['fieldsusedinindex'];
+ break;
+ }
+ }
+ }
+ }
+
+ if (!empty($errors)) {
+ $tempindex = new XMLDBIndex($name);
+ $tempindex->setUnique($unique);
+ $tempindex->setFields($fieldsarr);
+ /// Prepare the output
+ $site = get_site();
+ print_header("$site->shortname: XMLDB",
+ "$site->fullname",
+ "" . $this->str['administration'] . " -> XMLDB ");
+ notice ('' .implode(', ', $errors) . '
+ ' . $tempindex->readableInfo(),
+ 'index.php?action=edit_index&index=' .$index->getName() . '&table=' . $table->getName() . '&dir=' . urlencode($dirpath));
+ die; /// re-die :-P
+ }
+
+ /// Continue if we aren't under errors
+ if (empty($errors)) {
+ /// If there is one name change, do it, changing the prev and next
+ /// atributes of the adjacent fields
+ if ($indexparam != $name) {
+ $index->setName($name);
+ if ($index->getPrevious()) {
+ $prev =& $table->getIndex($index->getPrevious());
+ $prev->setNext($name);
+ $prev->setChanged(true);
+ }
+ if ($index->getNext()) {
+ $next =& $table->getIndex($index->getNext());
+ $next->setPrevious($name);
+ $next->setChanged(true);
+ }
+ }
+
+ /// Set comment
+ $index->setComment($comment);
+
+ /// Set the rest of fields
+ $index->setUnique($unique);
+ $index->setFields($fieldsarr);
+
+ /// If the hash has changed from the old one, change the version
+ /// and mark the structure as changed
+ $index->calculateHash(true);
+ if ($oldhash != $index->getHash()) {
+ $index->setChanged(true);
+ $table->setChanged(true);
+ /// Recalculate the structure hash
+ $structure->calculateHash(true);
+ $structure->setVersion(userdate(time(), '%Y%m%d', 99, false));
+ /// Mark as changed
+ $structure->setChanged(true);
+ }
+
+ /// Launch postaction if exists (leave this here!)
+ if ($this->getPostAction() && $result) {
+ return $this->launch($this->getPostAction());
+ }
+ }
+
+ /// Return ok if arrived here
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/edit_key/edit_key.class.php b/admin/xmldb/actions/edit_key/edit_key.class.php
new file mode 100644
index 00000000000..4971be65379
--- /dev/null
+++ b/admin/xmldb/actions/edit_key/edit_key.class.php
@@ -0,0 +1,171 @@
+loadStrings(array(
+ 'change' => 'xmldb',
+ 'vieworiginal' => 'xmldb',
+ 'viewedited' => 'xmldb',
+ 'yes' => '',
+ 'no' => '',
+ 'back' => 'xmldb'
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_GENERATE_HTML;
+
+ /// These are always here
+ global $CFG, $XMLDB;
+
+ /// Do the job, setting result as needed
+ /// Get the dir containing the file
+ $dirpath = required_param('dir', PARAM_CLEAN);
+ $dirpath = stripslashes_safe($dirpath);
+
+ /// Get the correct dirs
+ if (!empty($XMLDB->dbdirs)) {
+ $dbdir =& $XMLDB->dbdirs[$dirpath];
+ } else {
+ return false;
+ }
+ if (!empty($XMLDB->editeddirs)) {
+ $editeddir =& $XMLDB->editeddirs[$dirpath];
+ $structure =& $editeddir->xml_file->getStructure();
+ }
+
+ /// ADD YOUR CODE HERE
+
+ /// Fetch request data
+ $tableparam = required_param('table', PARAM_CLEAN);
+ if (!$table =& $structure->getTable($tableparam)) {
+ $this->errormsg = 'Wrong table specified: ' . $tableparm;
+ return false;
+ }
+ $keyparam = required_param('key', PARAM_CLEAN);
+ if (!$key =& $table->getKey($keyparam)) {
+ /// Arriving here from a name change, looking for the new key name
+ $keyparam = required_param('name', PARAM_CLEAN);
+ $key =& $table->getKey($keyparam);
+ }
+
+ $dbdir =& $XMLDB->dbdirs[$dirpath];
+ $origstructure =& $dbdir->xml_file->getStructure();
+
+ /// Add the main form
+ $o = '
';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= ' ';
+ /// Calculate the buttons
+ $b = ' ';
+ /// The view original XML button
+ if ($table->getKey($keyparam)) {
+ $b .= ' [' . $this->str['vieworiginal'] . '] ';
+ } else {
+ $b .= ' [' . $this->str['vieworiginal'] . ']';
+ }
+ /// The view edited XML button
+ if ($key->hasChanged()) {
+ $b .= ' [' . $this->str['viewedited'] . '] ';
+ } else {
+ $b .= ' [' . $this->str['viewedited'] . ']';
+ }
+ /// The back to edit table button
+ $b .= ' [' . $this->str['back'] . '] ';
+ $b .= '
';
+ $o .= $b;
+
+ $this->output = $o;
+
+ /// Launch postaction if exists (leave this here!)
+ if ($this->getPostAction() && $result) {
+ return $this->launch($this->getPostAction());
+ }
+
+ /// Return ok if arrived here
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/edit_key/edit_key.js b/admin/xmldb/actions/edit_key/edit_key.js
new file mode 100644
index 00000000000..8230e0f1434
--- /dev/null
+++ b/admin/xmldb/actions/edit_key/edit_key.js
@@ -0,0 +1,77 @@
+/// $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 //
+// //
+///////////////////////////////////////////////////////////////////////////
+
+
+/// Register the needed events
+
+ onload=function() {
+ /// Adjust the form on load
+ transformForm();
+
+ /// Get the required fields
+ var typeField = document.getElementById('menutype');
+
+ /// Register the rest of events
+ if (typeField.addEventListener) {
+ /// Standard
+ typeField.addEventListener('change', transformForm, false);
+ } else {
+ /// IE 5.5
+ typeField.attachEvent('onchange', transformForm);
+ }
+ }
+
+/**
+ * This function controls all modifications to perform when any field changes
+ */
+function transformForm(event) {
+
+/// Initialize all the needed variables
+ var typeField = document.getElementById('menutype');
+ var fieldsField = document.getElementById('fields');
+ var reftableField = document.getElementById('reftable');
+ var reffieldsField = document.getElementById('reffields');
+
+/// Initially, enable everything
+ typeField.disabled = false;
+ fieldsField.disabled = false;
+ reftableField.disabled = false;
+ reffieldsField.disabled = false;
+
+/// Based on type, disable some items
+ switch (typeField.value) {
+ case '1': // XMLDB_KEY_PRIMARY
+ case '2': // XMLDB_KEY_UNIQUE
+ reftableField.disabled = true;
+ reftableField.value = '';
+ reffieldsField.disabled = true;
+ reffieldsField.value = '';
+ break;
+ case '3': // XMLDB_KEY_FOREIGN
+ case '5': // XMLDB_KEY_FOREIGN_UNIQUE
+ break;
+ }
+}
diff --git a/admin/xmldb/actions/edit_key_save/edit_key_save.class.php b/admin/xmldb/actions/edit_key_save/edit_key_save.class.php
new file mode 100644
index 00000000000..48d252a03b7
--- /dev/null
+++ b/admin/xmldb/actions/edit_key_save/edit_key_save.class.php
@@ -0,0 +1,301 @@
+loadStrings(array(
+ 'keynameempty' => 'xmldb',
+ 'incorrectkeyname' => 'xmldb',
+ 'duplicatekeyname' => 'xmldb',
+ 'nofieldsspecified' => 'xmldb',
+ 'duplicatefieldsused' => 'xmldb',
+ 'fieldsnotintable' => 'xmldb',
+ 'fieldsusedinkey' => 'xmldb',
+ 'fieldsusedinindex' => 'xmldb',
+ 'noreftablespecified' => 'xmldb',
+ 'wrongnumberofreffields' => 'xmldb',
+ 'noreffieldsspecified' => 'xmldb',
+ 'nomasterprimaryuniquefound' => 'xmldb',
+ 'masterprimaryuniqueordernomatch' => 'xmldb',
+ 'primarykeyonlyallownotnullfields' => 'xmldb',
+ 'administration' => ''
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_NONE;
+ //$this->does_generate = ACTION_GENERATE_HTML;
+
+ /// These are always here
+ global $CFG, $XMLDB;
+
+ /// Do the job, setting result as needed
+
+ /// Get parameters
+ $dirpath = required_param('dir', PARAM_CLEAN);
+ $dirpath = stripslashes_safe($dirpath);
+
+ $tableparam = strtolower(required_param('table', PARAM_CLEAN));
+ $keyparam = strtolower(required_param('key', PARAM_CLEAN));
+ $name = trim(strtolower(optional_param('name', $keyparam, PARAM_CLEAN)));
+
+ $comment = required_param('comment', PARAM_CLEAN);
+ $comment = trim(stripslashes_safe($comment));
+
+ $type = required_param('type', PARAM_INT);
+ $fields = required_param('fields', PARAM_CLEAN);
+ $fields = str_replace(' ', '', trim(strtolower(stripslashes_safe($fields))));
+
+ if ($type == XMLDB_KEY_FOREIGN ||
+ $type == XMLDB_KEY_FOREIGN_UNIQUE) {
+ $reftable = trim(strtolower(required_param('reftable', PARAM_CLEAN)));
+ $reffields= required_param('reffields', PARAM_CLEAN);
+ $reffields = str_replace(' ', '', trim(strtolower(stripslashes_safe($reffields))));
+ }
+
+ $editeddir =& $XMLDB->editeddirs[$dirpath];
+ $structure =& $editeddir->xml_file->getStructure();
+ $table =& $structure->getTable($tableparam);
+ $key =& $table->getKey($keyparam);
+ $oldhash = $key->getHash();
+
+ $errors = array(); /// To store all the errors found
+
+ /// Perform some checks
+ /// Check empty name
+ if (empty($name)) {
+ $errors[] = $this->str['keynameempty'];
+ }
+ /// Check incorrect name
+ if ($name == 'changeme') {
+ $errors[] = $this->str['incorrectkeyname'];
+ }
+ /// Check duplicate name
+ if ($keyparam != $name && $table->getKey($name)) {
+ $errors[] = $this->str['duplicatekeyname'];
+ }
+ $fieldsarr = explode(',', $fields);
+ /// Check the fields isn't empty
+ if (empty($fieldsarr[0])) {
+ $errors[] = $this->str['nofieldsspecified'];
+ } else {
+ /// Check that there aren't duplicate column names
+ $uniquearr = array_unique($fieldsarr);
+ if (count($fieldsarr) != count($uniquearr)) {
+ $errors[] = $this->str['duplicatefieldsused'];
+ }
+ /// Check that all the fields in belong to the table
+ foreach ($fieldsarr as $field) {
+ if (!$table->getField($field)) {
+ $errors[] = $this->str['fieldsnotintable'];
+ break;
+ }
+ }
+ /// If primary, check that all the fields are not null
+ if ($type == XMLDB_KEY_PRIMARY) {
+ foreach ($fieldsarr as $field) {
+ if ($fi = $table->getField($field)) {
+ if (!$fi->getNotNull()) {
+ $errors[] = $this->str['primarykeyonlyallownotnullfields'];
+ break;
+ }
+ }
+ }
+ }
+ /// Check that there isn't any key using exactly the same fields
+ $tablekeys = $table->getKeys();
+ if ($tablekeys) {
+ foreach ($tablekeys as $tablekey) {
+ /// Skip checking against itself
+ if ($keyparam == $tablekey->getName()) {
+ continue;
+ }
+ $keyfieldsarr = $tablekey->getFields();
+ /// Compare both arrays, looking for diferences
+ $diferences = array_merge(array_diff($fieldsarr, $keyfieldsarr), array_diff($keyfieldsarr, $fieldsarr));
+ if (empty($diferences)) {
+ $errors[] = $this->str['fieldsusedinkey'];
+ break;
+ }
+ }
+ }
+ /// Check that there isn't any index using exactlt the same fields
+ $tableindexes = $table->getIndexes();
+ if ($tableindexes) {
+ foreach ($tableindexes as $tableindex) {
+ $indexfieldsarr = $tableindex->getFields();
+ /// Compare both arrays, looking for diferences
+ $diferences = array_merge(array_diff($fieldsarr, $indexfieldsarr), array_diff($indexfieldsarr, $fieldsarr));
+ if (empty($diferences)) {
+ $errors[] = $this->str['fieldsusedinindex'];
+ break;
+ }
+ }
+ }
+ /// If foreign key
+ if ($type == XMLDB_KEY_FOREIGN ||
+ $type == XMLDB_KEY_FOREIGN_UNIQUE) {
+ $reffieldsarr = explode(',', $reffields);
+ /// Check reftable is not empty
+ if (empty($reftable)) {
+ $errors[] = $this->str['noreftablespecified'];
+ } else
+ /// Check reffields are not empty
+ if (empty($reffieldsarr[0])) {
+ $errors[] = $this->str['noreffieldsspecified'];
+ } else
+ /// Check the number of fields is correct
+ if (count($fieldsarr) != count($reffieldsarr)) {
+ $errors[] = $this->str['wrongnumberofreffields'];
+ } else {
+ /// Check, if pointing to one structure table, that there is one master key for this key
+ if ($rt = $structure->getTable($reftable)) {
+ $masterfound = false;
+ $reftablekeys = $rt->getKeys();
+ if ($reftablekeys) {
+ foreach ($reftablekeys as $reftablekey) {
+ /// Only compare with primary and unique keys
+ if ($reftablekey->getType() != XMLDB_KEY_PRIMARY && $reftablekey->getType() != XMLDB_KEY_UNIQUE) {
+ continue;
+ }
+ $keyfieldsarr = $reftablekey->getFields();
+ /// Compare both arrays, looking for diferences
+ $diferences = array_merge(array_diff($reffieldsarr, $keyfieldsarr), array_diff($keyfieldsarr, $reffieldsarr));
+ if (empty($diferences)) {
+ $masterfound = true;
+ break;
+ }
+ }
+ if (!$masterfound) {
+ $errors[] = $this->str['nomasterprimaryuniquefound'];
+ } else {
+ /// Quick test of the order
+ if (implode(',', $reffieldsarr) != implode(',', $keyfieldsarr)) {
+ $errors[] = $this->str['masterprimaryuniqueordernomatch'];
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ if (!empty($errors)) {
+ $tempkey = new XMLDBKey($name);
+ $tempkey->setType($type);
+ $tempkey->setFields($fieldsarr);
+ if ($type == XMLDB_KEY_FOREIGN ||
+ $type == XMLDB_KEY_FOREIGN_UNIQUE) {
+ $tempkey->setRefTable($reftable);
+ $tempkey->setRefFields($reffieldsarr);
+ }
+ /// Prepare the output
+ $site = get_site();
+ print_header("$site->shortname: XMLDB",
+ "$site->fullname",
+ "" . $this->str['administration'] . " -> XMLDB ");
+ notice ('' .implode(', ', $errors) . '
+ ' . $tempkey->readableInfo(),
+ 'index.php?action=edit_key&key=' .$key->getName() . '&table=' . $table->getName() . '&dir=' . urlencode($dirpath));
+ die; /// re-die :-P
+ }
+
+ /// Continue if we aren't under errors
+ if (empty($errors)) {
+ /// If there is one name change, do it, changing the prev and next
+ /// atributes of the adjacent fields
+ if ($keyparam != $name) {
+ $key->setName($name);
+ if ($key->getPrevious()) {
+ $prev =& $table->getKey($key->getPrevious());
+ $prev->setNext($name);
+ $prev->setChanged(true);
+ }
+ if ($key->getNext()) {
+ $next =& $table->getKey($key->getNext());
+ $next->setPrevious($name);
+ $next->setChanged(true);
+ }
+ }
+
+ /// Set comment
+ $key->setComment($comment);
+
+ /// Set the rest of fields
+ $key->setType($type);
+ $key->setFields($fieldsarr);
+ if ($type == XMLDB_KEY_FOREIGN ||
+ $type == XMLDB_KEY_FOREIGN_UNIQUE) {
+ $key->setRefTable($reftable);
+ $key->setRefFields($reffieldsarr);
+ }
+
+ /// If the hash has changed from the old one, change the version
+ /// and mark the structure as changed
+ $key->calculateHash(true);
+ if ($oldhash != $key->getHash()) {
+ $key->setChanged(true);
+ $table->setChanged(true);
+ /// Recalculate the structure hash
+ $structure->calculateHash(true);
+ $structure->setVersion(userdate(time(), '%Y%m%d', 99, false));
+ /// Mark as changed
+ $structure->setChanged(true);
+ }
+
+ /// Launch postaction if exists (leave this here!)
+ if ($this->getPostAction() && $result) {
+ return $this->launch($this->getPostAction());
+ }
+ }
+
+ /// Return ok if arrived here
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/edit_sentence/edit_sentence.class.php b/admin/xmldb/actions/edit_sentence/edit_sentence.class.php
new file mode 100644
index 00000000000..b3e04c9987c
--- /dev/null
+++ b/admin/xmldb/actions/edit_sentence/edit_sentence.class.php
@@ -0,0 +1,153 @@
+loadStrings(array(
+ 'change' => 'xmldb',
+ 'vieworiginal' => 'xmldb',
+ 'viewedited' => 'xmldb',
+ 'back' => 'xmldb'
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_GENERATE_HTML;
+
+ /// These are always here
+ global $CFG, $XMLDB;
+
+ /// Do the job, setting result as needed
+ /// Get the dir containing the file
+ $dirpath = required_param('dir', PARAM_CLEAN);
+ $dirpath = stripslashes_safe($dirpath);
+
+ /// Get the correct dirs
+ if (!empty($XMLDB->dbdirs)) {
+ $dbdir =& $XMLDB->dbdirs[$dirpath];
+ } else {
+ return false;
+ }
+ if (!empty($XMLDB->editeddirs)) {
+ $editeddir =& $XMLDB->editeddirs[$dirpath];
+ $structure =& $editeddir->xml_file->getStructure();
+ }
+
+ /// ADD YOUR CODE HERE
+
+ /// Fetch request data
+ $statementparam = required_param('statement', PARAM_CLEAN);
+ $sentenceparam = optional_param('sentence', NULL, PARAM_CLEAN);
+
+ if (!$statement =& $structure->getStatement($statementparam)) {
+ $this->errormsg = 'Wrong statement specified: ' . $statementparam;
+ return false;
+ }
+ $sentences =& $statement->getSentences();
+
+ /// If no sentence has been specified, edit the last one
+ if ($sentenceparam === NULL) {
+ end($sentences);
+ $sentenceparam = key($sentences);
+ }
+
+ if (!$sentence =& $sentences[$sentenceparam]) {
+ $this->errormsg = 'Wrong Sentence: ' . $sentenceparam;
+ return false;
+ }
+
+ $dbdir =& $XMLDB->dbdirs[$dirpath];
+ $origstructure =& $dbdir->xml_file->getStructure();
+
+ /// Based in the type of statement, print different forms
+ if ($statement->getType() != XMLDB_STATEMENT_INSERT) {
+ /// Only INSERT is allowed!!
+ $this->errormsg = 'Wrong Statement Type. Only INSERT allowed';
+ return false;
+ } else {
+ /// Prepare INSERT sentence
+ $fields = $statement->getFieldsFromInsertSentence($sentence);
+ $values = $statement->getValuesFromInsertSentence($sentence);
+
+ /// Add the main form
+ $o = '
';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= ' ';
+ /// Calculate the buttons
+ $b = ' ';
+ /// The back to edit statement button
+ $b .= ' [' . $this->str['back'] . '] ';
+ $b .= '
';
+ $o .= $b;
+
+ $this->output = $o;
+ }
+
+ /// Launch postaction if exists (leave this here!)
+ if ($this->getPostAction() && $result) {
+ return $this->launch($this->getPostAction());
+ }
+
+ /// Return ok if arrived here
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/edit_sentence_save/edit_sentence_save.class.php b/admin/xmldb/actions/edit_sentence_save/edit_sentence_save.class.php
new file mode 100644
index 00000000000..83d9f254398
--- /dev/null
+++ b/admin/xmldb/actions/edit_sentence_save/edit_sentence_save.class.php
@@ -0,0 +1,155 @@
+loadStrings(array(
+ 'cannotuseidfield' => 'xmldb',
+ 'missingfieldsinsentence' => 'xmldb',
+ 'missingvaluesinsentence' => 'xmldb',
+ 'wrongnumberoffieldsorvalues' => 'xmldb',
+ 'administration' => ''
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_NONE;
+ //$this->does_generate = ACTION_GENERATE_HTML;
+
+ /// These are always here
+ global $CFG, $XMLDB;
+
+ /// Do the job, setting result as needed
+
+ /// Get parameters
+ $dirpath = required_param('dir', PARAM_CLEAN);
+ $dirpath = stripslashes_safe($dirpath);
+
+ $statementparam = strtolower(required_param('statement', PARAM_CLEAN));
+ $sentenceparam = strtolower(required_param('sentence', PARAM_CLEAN));
+
+ $fields = required_param('fields', PARAM_CLEAN);
+ $fields = trim(stripslashes_safe($fields));
+ $values = required_param('values', PARAM_CLEAN);
+ $values = trim(stripslashes_safe($values));
+
+ $editeddir =& $XMLDB->editeddirs[$dirpath];
+ $structure =& $editeddir->xml_file->getStructure();
+ $statement =& $structure->getStatement($statementparam);
+ $sentences =& $statement->getSentences();
+
+ $oldsentence = $sentences[$sentenceparam];
+
+ if (!$statement) {
+ $this->errormsg = 'Wrong statement specified: ' . $statementparam;
+ return false;
+ }
+
+ /// For now, only insert sentences are allowed
+ if ($statement->getType() != XMLDB_STATEMENT_INSERT) {
+ $this->errormsg = 'Wrong Statement Type. Only INSERT allowed';
+ return false;
+ }
+
+ $errors = array(); /// To store all the errors found
+
+ /// Build the whole sentence
+ $sentence = '(' . $fields . ') VALUES (' . $values . ')';
+
+ /// Perform some checks
+ $fields = $statement->getFieldsFromInsertSentence($sentence);
+ $values = $statement->getValuesFromInsertSentence($sentence);
+
+ if (in_array('id', $fields)) {
+ $errors[] = $this->str['cannotuseidfield'];
+ }
+ if ($result && count($fields) == 0) {
+ $errors[] = $this->str['missingfieldsinsentence'];
+ }
+ if ($result && count($values) == 0) {
+ $errors[] = $this->str['missingvaluesinsentence'];
+ }
+ if ($result && count($fields) != count($values)) {
+ $errors[] = $this->str['wrongnumberoffieldsorvalues'];
+ }
+
+ if (!empty($errors)) {
+ /// Prepare the output
+ $site = get_site();
+ print_header("$site->shortname: XMLDB",
+ "$site->fullname",
+ "" . $this->str['administration'] . " -> XMLDB ");
+ notice ('' .implode(', ', $errors) . '
+ ' . s($sentence),
+ 'index.php?action=edit_sentence&sentence=' .$sentenceparam . '&statement=' . urlencode($statementparam) . '&dir=' . urlencode($dirpath));
+ die; /// re-die :-P
+ }
+
+ /// Continue if we aren't under errors
+ if (empty($errors)) {
+ $sentences[$sentenceparam] = $sentence;
+
+ /// If the sentence has changed from the old one, change the version
+ /// and mark the statement and structure as changed
+ if ($oldsentence != $sentence) {
+ $statement->setChanged(true);
+ $structure->setVersion(userdate(time(), '%Y%m%d', 99, false));
+ /// Mark as changed
+ $structure->setChanged(true);
+ }
+
+ /// Launch postaction if exists (leave this here!)
+ if ($this->getPostAction() && $result) {
+ return $this->launch($this->getPostAction());
+ }
+ }
+
+ /// Return ok if arrived here
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/edit_statement/edit_statement.class.php b/admin/xmldb/actions/edit_statement/edit_statement.class.php
new file mode 100644
index 00000000000..03a601a8607
--- /dev/null
+++ b/admin/xmldb/actions/edit_statement/edit_statement.class.php
@@ -0,0 +1,182 @@
+loadStrings(array(
+ 'change' => 'xmldb',
+ 'vieworiginal' => 'xmldb',
+ 'viewedited' => 'xmldb',
+ 'newsentence' => 'xmldb',
+ 'sentences' => 'xmldb',
+ 'edit' => 'xmldb',
+ 'delete' => 'xmldb',
+ 'duplicate' => 'xmldb',
+ 'back' => 'xmldb'
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_GENERATE_HTML;
+
+ /// These are always here
+ global $CFG, $XMLDB;
+
+ /// Do the job, setting result as needed
+ /// Get the dir containing the file
+ $dirpath = required_param('dir', PARAM_CLEAN);
+ $dirpath = stripslashes_safe($dirpath);
+
+ /// Get the correct dirs
+ if (!empty($XMLDB->dbdirs)) {
+ $dbdir =& $XMLDB->dbdirs[$dirpath];
+ } else {
+ return false;
+ }
+ if (!empty($XMLDB->editeddirs)) {
+ $editeddir =& $XMLDB->editeddirs[$dirpath];
+ $structure =& $editeddir->xml_file->getStructure();
+ }
+
+ /// ADD YOUR CODE HERE
+ $statementparam = optional_param('statement', NULL, PARAM_CLEAN);
+ /// If no statement, then we are coming for a new one. Look for
+ /// type and table and build the correct statementparam
+ if (!$statementparam) {
+ $typeparam = optional_param('type', NULL, PARAM_CLEAN);
+ $tableparam = optional_param('table', NULL, PARAM_CLEAN);
+ $typename = XMLDBStatement::getXMLDBStatementName($typeparam);
+ $statementparam = trim(strtolower($typename . ' ' . $tableparam));
+ }
+ if (!$statement =& $structure->getStatement($statementparam)) {
+ /// Arriving here from a name change, looking for the new statement name
+ $statementname = required_param('name', PARAM_CLEAN);
+ $statement =& $structure->getStatement($statementparam);
+ }
+
+ $dbdir =& $XMLDB->dbdirs[$dirpath];
+ $origstructure =& $dbdir->xml_file->getStructure();
+
+ /// Add the main form
+ $o = '
';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= ' ';
+ /// Calculate the buttons
+ $b = ' ';
+ /// The view original XML button
+ if ($origstructure->getStatement($statementparam)) {
+ $b .= ' [' . $this->str['vieworiginal'] . '] ';
+ } else {
+ $b .= ' [' . $this->str['vieworiginal'] . ']';
+ }
+ /// The view edited XML button
+ if ($statement->hasChanged()) {
+ $b .= ' [' . $this->str['viewedited'] . '] ';
+ } else {
+ $b .= ' [' . $this->str['viewedited'] . ']';
+ }
+ /// The new sentence button
+ $b .= ' [' . $this->str['newsentence'] . '] ';
+ /// The back to edit xml file button
+ $b .= ' [' . $this->str['back'] . '] ';
+ $b .= '
';
+ $o .= $b;
+
+ /// Delete any 'changeme' sentence
+ ///$statement->deleteSentence('changeme');
+
+ /// Add the fields list
+ $sentences =& $statement->getSentences();
+ if (!empty($sentences)) {
+ $o .= '' . $this->str['sentences'] . ' ';
+ $o .= '';
+ $row = 0;
+ foreach ($sentences as $key => $sentence) {
+ /// Prepend some SQL
+ if ($statement->getType() == XMLDB_STATEMENT_INSERT) {
+ $p = 'INSERT INTO ' . $statement->getTable() . ' ';
+ } else {
+ $p = 'UNSUPPORTED SENTENCE TYPE ';
+ }
+ /// Calculate buttons
+ $b = '';
+ /// The edit button
+ $b .= '[' . $this->str['edit'] . '] ';
+ $b .= ' ';
+ /// The duplicate button
+ $b .= '[' . $this->str['duplicate'] . '] ';
+ $b .= ' ';
+ /// The delete button
+ $b .= '[' . $this->str['delete'] . '] ';
+ $b .= ' ';
+ /// Print table row
+ $o .= '' . $p . $sentence . $b . ' ';
+ $row = ($row + 1) % 2;
+ }
+ $o .= '
';
+ }
+
+ $this->output = $o;
+
+ /// Launch postaction if exists (leave this here!)
+ if ($this->getPostAction() && $result) {
+ return $this->launch($this->getPostAction());
+ }
+
+ /// Return ok if arrived here
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/edit_statement_save/edit_statement_save.class.php b/admin/xmldb/actions/edit_statement_save/edit_statement_save.class.php
new file mode 100644
index 00000000000..db4be9ee90b
--- /dev/null
+++ b/admin/xmldb/actions/edit_statement_save/edit_statement_save.class.php
@@ -0,0 +1,108 @@
+loadStrings(array(
+ 'administration' => ''
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_NONE;
+ //$this->does_generate = ACTION_GENERATE_HTML;
+
+ /// These are always here
+ global $CFG, $XMLDB;
+
+ /// Do the job, setting result as needed
+
+ /// Get parameters
+ $dirpath = required_param('dir', PARAM_CLEAN);
+ $dirpath = stripslashes_safe($dirpath);
+
+ $statementparam = strtolower(required_param('statement', PARAM_CLEAN));
+ $name = trim(strtolower(required_param('name', PARAM_CLEAN)));
+ $comment = required_param('comment', PARAM_CLEAN);
+ $comment = stripslashes_safe($comment);
+
+ $editeddir =& $XMLDB->editeddirs[$dirpath];
+ $structure =& $editeddir->xml_file->getStructure();
+ $statement =& $structure->getStatement($statementparam);
+
+ $errors = array(); /// To store all the errors found
+
+ /// If there is one name change, do it, changing the prev and next
+ /// atributes of the adjacent tables
+ if ($statementparam != $name) {
+ $statement->setName($name);
+ if ($statement->getPrevious()) {
+ $prev =& $structure->getStatement($statement->getPrevious());
+ $prev->setNext($name);
+ $prev->setChanged(true);
+ }
+ if ($statement->getNext()) {
+ $next =& $structure->getStatement($statement->getNext());
+ $next->setPrevious($name);
+ $next->setChanged(true);
+ }
+ }
+
+ /// Set comment
+ $statement->setComment($comment);
+
+ /// Launch postaction if exists (leave this here!)
+ if ($this->getPostAction() && $result) {
+ return $this->launch($this->getPostAction());
+ }
+
+ /// Return ok if arrived here
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/edit_table/edit_table.class.php b/admin/xmldb/actions/edit_table/edit_table.class.php
new file mode 100644
index 00000000000..168d8a47e9d
--- /dev/null
+++ b/admin/xmldb/actions/edit_table/edit_table.class.php
@@ -0,0 +1,310 @@
+loadStrings(array(
+ 'change' => 'xmldb',
+ 'vieworiginal' => 'xmldb',
+ 'viewedited' => 'xmldb',
+ 'viewsqlcode' => 'xmldb',
+ 'viewphpcode' => 'xmldb',
+ 'newfield' => 'xmldb',
+ 'newkey' => 'xmldb',
+ 'newindex' => 'xmldb',
+ 'fields' => 'xmldb',
+ 'keys' => 'xmldb',
+ 'indexes' => 'xmldb',
+ 'edit' => 'xmldb',
+ 'up' => 'xmldb',
+ 'down' => 'xmldb',
+ 'delete' => 'xmldb',
+ 'reserved' => 'xmldb',
+ 'back' => 'xmldb'
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_GENERATE_HTML;
+
+ /// These are always here
+ global $CFG, $XMLDB;
+
+ /// Do the job, setting result as needed
+ /// Get the dir containing the file
+ $dirpath = required_param('dir', PARAM_CLEAN);
+ $dirpath = stripslashes_safe($dirpath);
+
+ /// Get the correct dirs
+ if (!empty($XMLDB->dbdirs)) {
+ $dbdir =& $XMLDB->dbdirs[$dirpath];
+ } else {
+ return false;
+ }
+ if (!empty($XMLDB->editeddirs)) {
+ $editeddir =& $XMLDB->editeddirs[$dirpath];
+ $structure =& $editeddir->xml_file->getStructure();
+ }
+
+ /// ADD YOUR CODE HERE
+ $tableparam = required_param('table', PARAM_CLEAN);
+ if (!$table =& $structure->getTable($tableparam)) {
+ /// Arriving here from a name change, looking for the new table name
+ $tableparam = required_param('name', PARAM_CLEAN);
+ $table =& $structure->getTable($tableparam);
+ }
+
+ $dbdir =& $XMLDB->dbdirs[$dirpath];
+ $origstructure =& $dbdir->xml_file->getStructure();
+
+ /// Add the main form
+ $o = '';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= ' ';
+ /// Calculate the buttons
+ $b = ' ';
+ /// The view original XML button
+ if ($origstructure->getTable($tableparam)) {
+ $b .= ' [' . $this->str['vieworiginal'] . '] ';
+ } else {
+ $b .= ' [' . $this->str['vieworiginal'] . ']';
+ }
+ /// The view edited XML button
+ if ($table->hasChanged()) {
+ $b .= ' [' . $this->str['viewedited'] . '] ';
+ } else {
+ $b .= ' [' . $this->str['viewedited'] . ']';
+ }
+ /// The new field button
+ $b .= ' [' . $this->str['newfield'] . '] ';
+ /// The new key button
+ $b .= ' [' . $this->str['newkey'] . '] ';
+ /// The new index button
+ $b .= ' [' . $this->str['newindex'] . '] ';
+ /// The back to edit xml file button
+ $b .= ' [' . $this->str['back'] . '] ';
+ $b .= '
';
+ $b .= ' ';
+ /// The view sql code button
+ $b .= '[' .$this->str['viewsqlcode'] . '] ';
+ /// The view php code button
+ $b .= ' [' . $this->str['viewphpcode'] . '] ';
+ $b .= '
';
+ $o .= $b;
+
+ /// Join all the reserved words into one big array
+ /// Calculate list of available SQL generators
+ $plugins = get_list_of_plugins('lib/xmldb/classes/generators');
+ $reserved_words = array();
+ foreach($plugins as $plugin) {
+ $classname = 'XMLDB' . $plugin;
+ $generator = new $classname();
+ $reserved_words = array_merge($reserved_words, $generator->getReservedWords());
+ }
+ sort($reserved_words);
+ $reserved_words = array_unique($reserved_words);
+
+ /// Delete any 'changeme' field/key/index
+ $table->deleteField('changeme');
+ $table->deleteKey('changeme');
+ $table->deleteIndex('changeme');
+
+ /// Add the fields list
+ $fields =& $table->getFields();
+ if (!empty($fields)) {
+ $o .= '' . $this->str['fields'] . ' ';
+ $o .= '';
+ $row = 0;
+ foreach ($fields as $field) {
+ /// Calculate buttons
+ $b = '';
+ /// The edit button (if the field has no uses)
+ if (!$structure->getFieldUses($table->getName(), $field->getName())) {
+ $b .= '[' . $this->str['edit'] . '] ';
+ } else {
+ $b .= '[' . $this->str['edit'] . ']';
+ }
+ $b .= ' ';
+ /// The up button
+ if ($field->getPrevious()) {
+ $b .= '[' . $this->str['up'] . '] ';
+ } else {
+ $b .= '[' . $this->str['up'] . ']';
+ }
+ $b .= ' ';
+ /// The down button
+ if ($field->getNext()) {
+ $b .= '[' . $this->str['down'] . '] ';
+ } else {
+ $b .= '[' . $this->str['down'] . ']';
+ }
+ $b .= ' ';
+ /// The delete button (if we have more than one and it isn't used
+ if (count($fields) > 1 &&
+ !$structure->getFieldUses($table->getName(), $field->getName())) {
+ $b .= '[' . $this->str['delete'] . '] ';
+ } else {
+ $b .= '[' . $this->str['delete'] . ']';
+ }
+ /// Detect if the table name is a reserved word
+ if (in_array($field->getName(), $reserved_words)) {
+ $b .= ' ' . $this->str['reserved'] . ' ';
+ }
+ /// The readable info
+ $r = ' ' . $field->readableInfo() . ' ';
+ /// Print table row
+ $o .= '' . $field->getName() . ' ' . $b . $r . ' ';
+ $row = ($row + 1) % 2;
+ }
+ $o .= '
';
+ }
+ /// Add the keys list
+ $keys =& $table->getKeys();
+ if (!empty($keys)) {
+ $o .= '' . $this->str['keys'] . ' ';
+ $o .= '';
+ $row = 0;
+ foreach ($keys as $key) {
+ /// Calculate buttons
+ $b = '';
+ /// The edit button (if the key hasn't uses)
+ if (!$structure->getKeyUses($table->getName(), $key->getName())) {
+ $b .= '[' . $this->str['edit'] . '] ';
+ } else {
+ $b .= '[' . $this->str['edit'] . ']';
+ }
+ $b .= ' ';
+ /// The up button
+ if ($key->getPrevious()) {
+ $b .= '[' . $this->str['up'] . '] ';
+ } else {
+ $b .= '[' . $this->str['up'] . ']';
+ }
+ $b .= ' ';
+ /// The down button
+ if ($key->getNext()) {
+ $b .= '[' . $this->str['down'] . '] ';
+ } else {
+ $b .= '[' . $this->str['down'] . ']';
+ }
+ $b .= ' ';
+ /// The delete button (if the key hasn't uses)
+ if (!$structure->getKeyUses($table->getName(), $key->getName())) {
+ $b .= '[' . $this->str['delete'] . '] ';
+ } else {
+ $b .= '[' . $this->str['delete'] . ']';
+ }
+ /// The readable info
+ $r = ' ' . $key->readableInfo() . ' ';
+ /// Print table row
+ $o .= '' . $key->getName() . ' ' . $b . $r .' ';
+ $row = ($row + 1) % 2;
+ }
+ $o .= '
';
+ }
+ /// Add the indexes list
+ $indexes =& $table->getIndexes();
+ if (!empty($indexes)) {
+ $o .= '' . $this->str['indexes'] . ' ';
+ $o .= '';
+ $row = 0;
+ foreach ($indexes as $index) {
+ /// Calculate buttons
+ $b = '';
+ /// The edit button
+ $b .= '[' . $this->str['edit'] . '] ';
+ $b .= ' ';
+ /// The up button
+ if ($index->getPrevious()) {
+ $b .= '[' . $this->str['up'] . '] ';
+ } else {
+ $b .= '[' . $this->str['up'] . ']';
+ }
+ $b .= ' ';
+ /// The down button
+ if ($index->getNext()) {
+ $b .= '[' . $this->str['down'] . '] ';
+ } else {
+ $b .= '[' . $this->str['down'] . ']';
+ }
+ $b .= ' ';
+ /// The delete button
+ $b .= '[' . $this->str['delete'] . '] ';
+ /// The readable info
+ $r = ' ' . $index->readableInfo() . ' ';
+ /// Print table row
+ $o .= '' . $index->getName() . ' ' . $b . $r .' ';
+ $row = ($row + 1) % 2;
+ }
+ $o .= '
';
+ }
+
+ $this->output = $o;
+
+ /// Launch postaction if exists (leave this here!)
+ if ($this->getPostAction() && $result) {
+ return $this->launch($this->getPostAction());
+ }
+
+ /// Return ok if arrived here
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/edit_table_save/edit_table_save.class.php b/admin/xmldb/actions/edit_table_save/edit_table_save.class.php
new file mode 100644
index 00000000000..10cfac515d8
--- /dev/null
+++ b/admin/xmldb/actions/edit_table_save/edit_table_save.class.php
@@ -0,0 +1,138 @@
+loadStrings(array(
+ 'tablenameempty' => 'xmldb',
+ 'incorrecttablename' => 'xmldb',
+ 'duplicatetablename' => 'xmldb',
+ 'administration' => ''
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_NONE;
+ //$this->does_generate = ACTION_GENERATE_HTML;
+
+ /// These are always here
+ global $CFG, $XMLDB;
+
+ /// Do the job, setting result as needed
+
+ /// Get parameters
+ $dirpath = required_param('dir', PARAM_CLEAN);
+ $dirpath = stripslashes_safe($dirpath);
+
+ $tableparam = strtolower(required_param('table', PARAM_CLEAN));
+ $name = substr(trim(strtolower(required_param('name', PARAM_CLEAN))),0,28);
+ $comment = required_param('comment', PARAM_CLEAN);
+ $comment = stripslashes_safe($comment);
+
+ $editeddir =& $XMLDB->editeddirs[$dirpath];
+ $structure =& $editeddir->xml_file->getStructure();
+ $table =& $structure->getTable($tableparam);
+
+ $errors = array(); /// To store all the errors found
+
+ /// Perform some checks
+ /// Check empty name
+ if (empty($name)) {
+ $errors[] = $this->str['tablenameempty'];
+ }
+ /// Check incorrect name
+ if ($name == 'changeme') {
+ $errors[] = $this->str['incorrecttablename'];
+ }
+ /// Check duplicatename
+ if ($tableparam != $name && $structure->getTable($name)) {
+ $errors[] = $this->str['duplicatetablename'];
+ }
+
+ if (!empty($errors)) {
+ $temptable = new XMLDBTable($name);
+ /// Prepare the output
+ $site = get_site();
+ print_header("$site->shortname: XMLDB",
+ "$site->fullname",
+ "" . $this->str['administration'] . " -> XMLDB ");
+ notice ('' .implode(', ', $errors) . '
+ ' . $temptable->readableInfo(),
+ 'index.php?action=edit_table&table=' . $tableparam . '&dir=' . urlencode($dirpath));
+ die; /// re-die :-P
+ }
+
+ /// If there is one name change, do it, changing the prev and next
+ /// atributes of the adjacent tables
+ if ($tableparam != $name) {
+ $table->setName($name);
+ if ($table->getPrevious()) {
+ $prev =& $structure->getTable($table->getPrevious());
+ $prev->setNext($name);
+ $prev->setChanged(true);
+ }
+ if ($table->getNext()) {
+ $next =& $structure->getTable($table->getNext());
+ $next->setPrevious($name);
+ $next->setChanged(true);
+ }
+ }
+
+ /// Set comment
+ $table->setComment($comment);
+
+ /// Launch postaction if exists (leave this here!)
+ if ($this->getPostAction() && $result) {
+ return $this->launch($this->getPostAction());
+ }
+
+ /// Return ok if arrived here
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/edit_xml_file/edit_xml_file.class.php b/admin/xmldb/actions/edit_xml_file/edit_xml_file.class.php
new file mode 100644
index 00000000000..bf45dc99804
--- /dev/null
+++ b/admin/xmldb/actions/edit_xml_file/edit_xml_file.class.php
@@ -0,0 +1,252 @@
+loadStrings(array(
+ 'change' => 'xmldb',
+ 'edit' => 'xmldb',
+ 'up' => 'xmldb',
+ 'down' => 'xmldb',
+ 'delete' => 'xmldb',
+ 'vieworiginal' => 'xmldb',
+ 'viewedited' => 'xmldb',
+ 'tables' => 'xmldb',
+ 'statements' => 'xmldb',
+ 'newtable' => 'xmldb',
+ 'newtablefrommysql' => 'xmldb',
+ 'newstatement' => 'xmldb',
+ 'viewsqlcode' => 'xmldb',
+ 'viewphpcode' => 'xmldb',
+ 'reserved' => 'xmldb',
+ 'backtomainview' => 'xmldb'
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ //$this->does_generate = ACTION_NONE;
+ $this->does_generate = ACTION_GENERATE_HTML;
+
+ /// These are always here
+ global $CFG, $XMLDB;
+
+ /// Do the job, setting $result as needed
+
+ /// Get the dir containing the file
+ $dirpath = required_param('dir', PARAM_CLEAN);
+ $dirpath = stripslashes_safe($dirpath);
+
+ /// Get the correct dir
+ if (!empty($XMLDB->dbdirs)) {
+ $dbdir =& $XMLDB->dbdirs[$dirpath];
+ if ($dbdir) {
+ /// Only if the directory exists and it has been loaded
+ if (!$dbdir->path_exists || !$dbdir->xml_loaded) {
+ return false;
+ }
+ /// Check if the in-memory object exists and create it
+ if (empty($XMLDB->editeddirs)) {
+ $XMLDB->editeddirs = array();
+ }
+ /// Check if the dir exists and copy it from dbdirs
+ if (!isset($XMLDB->editeddirs[$dirpath])) {
+ $XMLDB->editeddirs[$dirpath] = unserialize(serialize($dbdir));
+ }
+ /// Get it
+ $editeddir =& $XMLDB->editeddirs[$dirpath];
+ $structure =& $editeddir->xml_file->getStructure();
+ /// Add the main form
+ $o = '
';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= ' ';
+ /// Calculate the buttons
+ $b = ' ';
+ /// The view original XML button
+ $b .= ' [' . $this->str['vieworiginal'] . '] ';
+ /// The view edited XML button
+ if ($structure->hasChanged()) {
+ $b .= ' [' . $this->str['viewedited'] . '] ';
+ } else {
+ $b .= ' [' . $this->str['viewedited'] . ']';
+ }
+ /// The new table button
+ $b .= ' [' . $this->str['newtable'] . '] ';
+ /// The new from MySQL button
+ if ($CFG->dbtype == 'mysql') {
+ $b .= ' [' . $this->str['newtablefrommysql'] . '] ';
+ } else {
+ $b .= ' [' . $this->str['newtablefrommysql'] . ']';
+ }
+ /// The new statement button
+ $b .= ' [' . $this->str['newstatement'] . '] ';
+ /// The back to main menu button
+ $b .= ' [' . $this->str['backtomainview'] . '] ';
+ $b .= '
';
+ $b .= ' ';
+ /// The view sql code button
+ $b .= '[' .$this->str['viewsqlcode'] . '] ';
+ /// The view php code button
+ $b .= ' [' . $this->str['viewphpcode'] . '] ';
+ $b .= '
';
+ $o .= $b;
+ /// Join all the reserved words into one big array
+ /// Calculate list of available SQL generators
+ $plugins = get_list_of_plugins('lib/xmldb/classes/generators');
+ $reserved_words = array();
+ foreach($plugins as $plugin) {
+ $classname = 'XMLDB' . $plugin;
+ $generator = new $classname();
+ $reserved_words = array_merge($reserved_words, $generator->getReservedWords());
+ }
+ sort($reserved_words);
+ $reserved_words = array_unique($reserved_words);
+ /// Add the tables list
+ $tables =& $structure->getTables();
+ if ($tables) {
+ $o .= '' . $this->str['tables'] . ' ';
+ $o .= '';
+ $row = 0;
+ foreach ($tables as $table) {
+ /// Calculate buttons
+ $b = '';
+ /// The edit button
+ $b .= '[' . $this->str['edit'] . '] ';
+ $b .= ' ';
+ /// The up button
+ if ($table->getPrevious()) {
+ $b .= '[' . $this->str['up'] . '] ';
+ } else {
+ $b .= '[' . $this->str['up'] . ']';
+ }
+ $b .= ' ';
+ /// The down button
+ if ($table->getNext()) {
+ $b .= '[' . $this->str['down'] . '] ';
+ } else {
+ $b .= '[' . $this->str['down'] . ']';
+ }
+ $b .= ' ';
+ /// The delete button (if we have more than one and it isn't used)
+ if (count($tables) > 1 &&
+ !$structure->getTableUses($table->getName())) {
+ ///!$structure->getTableUses($table->getName())) {
+ $b .= '[' . $this->str['delete'] . '] ';
+ } else {
+ $b .= '[' . $this->str['delete'] . ']';
+ }
+ /// Detect if the table name is a reserved word
+ if (in_array($table->getName(), $reserved_words)) {
+ $b .= ' ' . $this->str['reserved'] . ' ';
+ }
+ $b .= ' ';
+ /// Print table row
+ $o .= '' . $table->getName() . ' ' . $b . ' ';
+ $row = ($row + 1) % 2;
+ }
+ $o .= '
';
+ }
+ ///Add the statements list
+ $statements =& $structure->getStatements();
+ if ($statements) {
+ $o .= '' . $this->str['statements'] . ' ';
+ $o .= '';
+ }
+ ///Add the back to main
+
+
+ $this->output = $o;
+ }
+ }
+
+ /// Launch postaction if exists (leave this unmodified)
+ if ($this->getPostAction() && $result) {
+ return $this->launch($this->getPostAction());
+ }
+
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/edit_xml_file_save/edit_xml_file_save.class.php b/admin/xmldb/actions/edit_xml_file_save/edit_xml_file_save.class.php
new file mode 100644
index 00000000000..5659c3c52da
--- /dev/null
+++ b/admin/xmldb/actions/edit_xml_file_save/edit_xml_file_save.class.php
@@ -0,0 +1,96 @@
+loadStrings(array(
+ /// 'key' => 'module',
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_NONE;
+ //$this->does_generate = ACTION_GENERATE_HTML;
+
+ /// These are always here
+ global $CFG, $XMLDB;
+
+ /// Do the job, setting result as needed
+
+ /// Get parameters
+ $dirpath = required_param('dir', PARAM_CLEAN);
+ $dirpath = stripslashes_safe($dirpath);
+
+ $comment = required_param('comment', PARAM_CLEAN);
+ $comment = stripslashes_safe($comment);
+
+ /// Set comment and recalculate hash
+ $editeddir =& $XMLDB->editeddirs[$dirpath];
+ $structure =& $editeddir->xml_file->getStructure();
+ $structure->setComment($comment);
+ $structure->calculateHash(true);
+
+
+ /// If the hash has changed from the original one, change the version
+ /// and mark the structure as changed
+ $origdir =& $XMLDB->dbdirs[$dirpath];
+ $origstructure =& $origdir->xml_file->getStructure();
+ if ($structure->getHash() != $origstructure->getHash()) {
+ $structure->setVersion(userdate(time(), '%Y%m%d', 99, false));
+ $structure->setChanged(true);
+ }
+
+ /// Launch postaction if exists (leave this here!)
+ if ($this->getPostAction() && $result) {
+ return $this->launch($this->getPostAction());
+ }
+
+ /// Return ok if arrived here
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/get_db_directories/get_db_directories.class.php b/admin/xmldb/actions/get_db_directories/get_db_directories.class.php
new file mode 100644
index 00000000000..55bf428bffb
--- /dev/null
+++ b/admin/xmldb/actions/get_db_directories/get_db_directories.class.php
@@ -0,0 +1,151 @@
+dbdirs array
+
+class get_db_directories extends XMLDBAction {
+
+ /**
+ * Init method, every subclass will have its own
+ */
+ function init() {
+ parent::init();
+ /// Set own core attributes
+ $this->can_subaction = ACTION_NONE;
+ //$this->can_subaction = ACTION_HAVE_SUBACTIONS;
+
+ /// Set own custom attributes
+
+ /// Get needed strings
+ $this->loadStrings(array(
+ /// 'key' => 'module',
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_NONE;
+ //$this->does_generate = ACTION_GENERATE_HTML;
+
+ /// These are always here
+ global $CFG, $XMLDB;
+
+ /// Do the job, setting $result as needed
+
+ /// Lets go to add all the db directories available inside Moodle
+ /// Create the array if it doesn't exists
+ if (!isset($XMLDB->dbdirs)) {
+ $XMLDB->dbdirs = array();
+ }
+ /// First, the main one (lib/db)
+ $dbdir = new stdClass;
+ $dbdir->path = $CFG->libdir . '/db';
+ $dbdir->path_exists = file_exists($dbdir->path);
+ if (!isset($XMLDB->dbdirs[$dbdir->path])) {
+ $XMLDB->dbdirs[$dbdir->path] = $dbdir;
+ }
+
+ /// Now, activity modules (mod/xxx/db)
+ if ($plugins = get_list_of_plugins('mod')) {
+ foreach ($plugins as $plugin) {
+ $dbdir = new stdClass;
+ $dbdir->path = $CFG->dirroot . '/mod/' . $plugin . '/db';
+ $dbdir->path_exists = file_exists($dbdir->path);
+ if (!isset($XMLDB->dbdirs[$dbdir->path])) {
+ $XMLDB->dbdirs[$dbdir->path] = $dbdir;
+ }
+ }
+ }
+
+ /// Now, question types (question/type/xxx/db)
+ if ($plugins = get_list_of_plugins('question/type')) {
+ foreach ($plugins as $plugin) {
+ $dbdir = new stdClass;
+ $dbdir->path = $CFG->dirroot . '/question/type/' . $plugin . '/db';
+ $dbdir->path_exists = file_exists($dbdir->path);
+ if (!isset($XMLDB->dbdirs[$dbdir->path])) {
+ $XMLDB->dbdirs[$dbdir->path] = $dbdir;
+ }
+ }
+ }
+
+ /// Now, backup/restore stuff (backup/db)
+ $dbdir = new stdClass;
+ $dbdir->path = $CFG->dirroot . '/backup/db';
+ $dbdir->path_exists = file_exists($dbdir->path);
+ if (!isset($XMLDB->dbdirs[$dbdir->path])) {
+ $XMLDB->dbdirs[$dbdir->path] = $dbdir;
+ }
+
+ /// Now, block system stuff (blocks/db)
+ $dbdir = new stdClass;
+ $dbdir->path = $CFG->dirroot . '/blocks/db';
+ $dbdir->path_exists = file_exists($dbdir->path);
+ if (!isset($XMLDB->dbdirs[$dbdir->path])) {
+ $XMLDB->dbdirs[$dbdir->path] = $dbdir;
+ }
+
+ /// Now, blocks (blocks/xxx/db)
+ if ($plugins = get_list_of_plugins('blocks', 'db')) {
+ foreach ($plugins as $plugin) {
+ $dbdir = new stdClass;
+ $dbdir->path = $CFG->dirroot . '/blocks/' . $plugin . '/db';
+ $dbdir->path_exists = file_exists($dbdir->path);
+ if (!isset($XMLDB->dbdirs[$dbdir->path])) {
+ $XMLDB->dbdirs[$dbdir->path] = $dbdir;
+ }
+ }
+ }
+
+ /// Now, enrolment plugins (enrol/xxx/db)
+ if ($plugins = get_list_of_plugins('enrol', 'db')) {
+ foreach ($plugins as $plugin) {
+ $dbdir = new stdClass;
+ $dbdir->path = $CFG->dirroot . '/enrol/' . $plugin . '/db';
+ $dbdir->path_exists = file_exists($dbdir->path);
+ if (!isset($XMLDB->dbdirs[$dbdir->path])) {
+ $XMLDB->dbdirs[$dbdir->path] = $dbdir;
+ }
+ }
+ }
+ /// Sort by key
+ ksort($XMLDB->dbdirs);
+
+ /// Return ok if arrived here
+ return true;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/load_xml_file/load_xml_file.class.php b/admin/xmldb/actions/load_xml_file/load_xml_file.class.php
new file mode 100644
index 00000000000..6c782dc69f1
--- /dev/null
+++ b/admin/xmldb/actions/load_xml_file/load_xml_file.class.php
@@ -0,0 +1,113 @@
+can_subaction = ACTION_NONE;
+ //$this->can_subaction = ACTION_HAVE_SUBACTIONS;
+
+ /// Set own custom attributes
+
+ /// Get needed strings
+ $this->loadStrings(array(
+ /// 'key' => 'module',
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_NONE;
+ //$this->does_generate = ACTION_GENERATE_HTML;
+
+ /// These are always here
+ global $CFG, $XMLDB;
+
+ /// Do the job, setting $result as needed
+
+ /// Get the dir containing the file
+ $dirpath = required_param('dir', PARAM_CLEAN);
+ $dirpath = stripslashes_safe($dirpath);
+
+ /// Get the correct dir
+ if (!empty($XMLDB->dbdirs)) {
+ $dbdir =& $XMLDB->dbdirs[$dirpath];
+ if ($dbdir) {
+ /// Set some defaults
+ $dbdir->xml_exists = false;
+ $dbdir->xml_writeable = false;
+ $dbdir->xml_loaded = false;
+ ///Only if the directory exists
+ if (!$dbdir->path_exists) {
+ return false;
+ }
+ $xmldb_file = new XMLDBFile($dbdir->path . '/install.xml');
+ /// Set dbdir as necessary
+ if ($xmldb_file->fileExists()) {
+ $dbdir->xml_exists = true;
+ }
+ if ($xmldb_file->fileWriteable()) {
+ $dbdir->xml_writeable = true;
+ }
+ /// Load the XML contents to structure
+ $loaded = $xmldb_file->loadXMLStructure();
+ if ($loaded && $xmldb_file->isLoaded()) {
+ $dbdir->xml_loaded = true;
+ }
+ $dbdir->xml_file = $xmldb_file;
+ } else {
+ $this->errormsg = 'Wrong directory (' . $dirpath . ')';
+ $result = false;
+ }
+ } else {
+ $this->errormsg = 'XMLDB structure not found';
+ $result = false;
+ }
+ /// Launch postaction if exists
+ if ($this->getPostAction() && $result) {
+ return $this->launch($this->getPostAction());
+ }
+
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/load_xml_files/load_xml_files.class.php b/admin/xmldb/actions/load_xml_files/load_xml_files.class.php
new file mode 100644
index 00000000000..008bd9afd86
--- /dev/null
+++ b/admin/xmldb/actions/load_xml_files/load_xml_files.class.php
@@ -0,0 +1,98 @@
+can_subaction = ACTION_NONE;
+ //$this->can_subaction = ACTION_HAVE_SUBACTIONS;
+
+ /// Set own custom attributes
+
+ /// Get needed strings
+ $this->loadStrings(array(
+ /// 'key' => 'module',
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_NONE;
+ //$this->does_generate = ACTION_GENERATE_HTML;
+
+ /// These are always here
+ global $CFG, $XMLDB;
+
+ /// Do the job, setting $result as needed
+
+ /// Iterate over $XMLDB->dbdirs, loading their XML data to memory
+ if ($XMLDB->dbdirs) {
+ $dbdirs =& $XMLDB->dbdirs;
+ foreach ($dbdirs as $dbdir) {
+ /// Set some defaults
+ $dbdir->xml_exists = false;
+ $dbdir->xml_writeable = false;
+ $dbdir->xml_loaded = false;
+ ///Only if the directory exists
+ if (!$dbdir->path_exists) {
+ continue;
+ }
+ $xmldb_file = new XMLDBFile($dbdir->path . '/install.xml');
+ /// Set dbdir as necessary
+ if ($xmldb_file->fileExists()) {
+ $dbdir->xml_exists = true;
+ }
+ if ($xmldb_file->fileWriteable()) {
+ $dbdir->xml_writeable = true;
+ }
+ /// Load the XML contents to structure
+ $loaded = $xmldb_file->loadXMLStructure();
+ if ($loaded && $xmldb_file->isLoaded()) {
+ $dbdir->xml_loaded = true;
+ }
+ $dbdir->xml_file = $xmldb_file;
+ }
+ }
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/main_view/main_view.class.php b/admin/xmldb/actions/main_view/main_view.class.php
new file mode 100644
index 00000000000..8811ab12e86
--- /dev/null
+++ b/admin/xmldb/actions/main_view/main_view.class.php
@@ -0,0 +1,233 @@
+loadStrings(array(
+ 'load' => 'xmldb',
+ 'create' => 'xmldb',
+ 'edit' => 'xmldb',
+ 'save' => 'xmldb',
+ 'revert' => 'xmldb',
+ 'unload' => 'xmldb',
+ 'delete' => 'xmldb',
+ 'reservedwords' => 'xmldb',
+ 'gotolastused' => 'xmldb'
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_GENERATE_HTML;
+
+ /// These are always here
+ global $CFG, $XMLDB, $SESSION;
+
+ /// Get lastused
+ $o = '';
+ if (isset($SESSION->lastused)) {
+ if ($lastused = $SESSION->lastused) {
+ /// Print link
+ $o .= '' . $this->str['gotolastused'] . '
';
+ }
+ } else {
+ $lastused = NULL;
+ }
+
+ /// Calculate the buttons
+ $b = '';
+ /// The reserved_words button
+ $b .= ' [' . $this->str['reservedwords'] . '] ';
+ $b .= '
';
+ /// Send buttons to output
+ $o .= $b;
+
+ /// Do the job
+
+ /// Get the list of DB directories
+ $result = $this->launch('get_db_directories');
+ /// Display list of DB directories if everything is ok
+ if ($result && !empty($XMLDB->dbdirs)) {
+ $o .= '';
+ $row = 0;
+ foreach ($XMLDB->dbdirs as $key => $dbdir) {
+ /// Detect if this is the lastused dir
+ $hithis = false;
+ if ($key == $lastused) {
+ $hithis = true;
+ }
+ $elementtext = str_replace($CFG->dirroot . '/', '', $key);
+ /// Calculate the dbdir has_changed field if needed
+ if (!isset($dbdir->has_changed) && isset($dbdir->xml_loaded)) {
+ $dbdir->xml_changed = false;
+ if (isset($XMLDB->editeddirs[$key])) {
+ $editeddir =& $XMLDB->editeddirs[$key];
+ if (isset($editeddir->xml_file)) {
+ $structure =& $editeddir->xml_file->getStructure();
+ if ($structure->hasChanged()) {
+ $dbdir->xml_changed = true;
+ $editeddir->xml_changed = true;
+ }
+ }
+ }
+ }
+ /// Calculate the buttons
+ $b = ' ';
+ /// The create button
+ if ($dbdir->path_exists &&
+ !file_exists($key . '/install.xml') &&
+ is_writeable($key)) {
+ $b .= '[' . $this->str['create'] . '] ';
+ } else {
+ $b .= '[' . $this->str['create'] . ']';
+ }
+ $b .= ' ';
+ /// The load button
+ if ($dbdir->path_exists &&
+ file_exists($key . '/install.xml') &&
+ is_readable($key . '/install.xml') &&
+ empty($dbdir->xml_loaded)) {
+ $b .= '[' . $this->str['load'] . '] ';
+ } else {
+ $b .= '[' . $this->str['load'] . ']';
+ }
+ $b .= ' ';
+ /// The edit button
+ if ($dbdir->path_exists &&
+ file_exists($key . '/install.xml') &&
+ is_readable($key . '/install.xml') &&
+ is_readable($key) &&
+ !empty($dbdir->xml_loaded)) {
+ $b .= '[' . $this->str['edit'] . '] ';
+ } else {
+ $b .= '[' . $this->str['edit'] . ']';
+ }
+ $b .= ' ';
+ /// The save button
+ if ($dbdir->path_exists &&
+ file_exists($key . '/install.xml') &&
+ is_readable($key . '/install.xml') &&
+ is_writeable($key) &&
+ !empty($dbdir->xml_loaded) &&
+ !empty($dbdir->xml_changed)) {
+ $b .= '[' . $this->str['save'] . '] ';
+ } else {
+ $b .= '[' . $this->str['save'] . ']';
+ }
+ $b .= ' ';
+ /// The revert button
+ if ($dbdir->path_exists &&
+ file_exists($key . '/install.xml') &&
+ is_readable($key . '/install.xml') &&
+ is_writeable($key) &&
+ !empty($dbdir->xml_loaded) &&
+ !empty($dbdir->xml_changed)) {
+ $b .= '[' . $this->str['revert'] . '] ';
+ } else {
+ $b .= '[' . $this->str['revert'] . ']';
+ }
+ $b .= ' ';
+ /// The unload button
+ if ($dbdir->path_exists &&
+ file_exists($key . '/install.xml') &&
+ is_readable($key . '/install.xml') &&
+ !empty($dbdir->xml_loaded) &&
+ empty($dbdir->xml_changed)) {
+ $b .= '[' . $this->str['unload'] . '] ';
+ } else {
+ $b .= '[' . $this->str['unload'] . ']';
+ }
+ $b .= ' ';
+ /// The delete button
+ if ($dbdir->path_exists &&
+ file_exists($key . '/install.xml') &&
+ is_readable($key . '/install.xml') &&
+ is_writeable($key) &&
+ empty($dbdir->xml_loaded)) {
+ $b .= '[' . $this->str['delete'] . '] ';
+ } else {
+ $b .= '[' . $this->str['delete'] . ']';
+ }
+ $b .= ' ';
+ /// if the file, exist, XML is viewable
+ if ($dbdir->path_exists &&
+ file_exists($key . '/install.xml') &&
+ is_readable($key . '/install.xml')) {
+ $elementtext = '' . $elementtext . ' ';
+ } else {
+ $elementtext = $elementtext . '';
+ }
+ /// include the higlight
+ if ($hithis) {
+ $o .= ' ' . $elementtext . $b . ' ';
+ } else {
+ $o .= '' . $elementtext . $b . ' ';
+ }
+ $row = ($row + 1) % 2;
+ /// show errors if they exist
+ if (isset($dbdir->xml_file)) {
+ if ($structure =& $dbdir->xml_file->getStructure()) {
+ if ($errors = $structure->getAllErrors()) {
+ if ($hithis) {
+ $o .= '' . implode (', ', $errors) . ' ';
+ } else {
+ $o .= '' . implode (', ', $errors) . ' ';
+ }
+ }
+ }
+ }
+ }
+ $o .= '
';
+
+ /// Set the output
+ $this->output = $o;
+ }
+
+ /// Finally, return result
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/move_updown_field/move_updown_field.class.php b/admin/xmldb/actions/move_updown_field/move_updown_field.class.php
new file mode 100644
index 00000000000..1355109e4e5
--- /dev/null
+++ b/admin/xmldb/actions/move_updown_field/move_updown_field.class.php
@@ -0,0 +1,146 @@
+loadStrings(array(
+ /// 'key' => 'module',
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_NONE;
+ //$this->does_generate = ACTION_GENERATE_HTML;
+
+ /// These are always here
+ global $CFG, $XMLDB;
+
+ /// Do the job, setting result as needed
+ /// Get the dir containing the file
+ $dirpath = required_param('dir', PARAM_CLEAN);
+ $dirpath = stripslashes_safe($dirpath);
+
+ /// Get the correct dirs
+ if (!empty($XMLDB->dbdirs)) {
+ $dbdir =& $XMLDB->dbdirs[$dirpath];
+ } else {
+ return false;
+ }
+ if (!empty($XMLDB->editeddirs)) {
+ $editeddir =& $XMLDB->editeddirs[$dirpath];
+ $structure =& $editeddir->xml_file->getStructure();
+ }
+ /// ADD YOUR CODE HERE
+ $prev = NULL;
+ $next = NULL;
+ $tableparam = required_param('table', PARAM_CLEAN);
+ $fieldparam = required_param('field', PARAM_CLEAN);
+ $direction = required_param('direction', PARAM_ALPHA);
+ $tables =& $structure->getTables();
+ $table =& $structure->getTable($tableparam);
+ $fields =& $table->getFields();
+ if ($direction == 'down') {
+ $field =& $table->getField($fieldparam);
+ $swap =& $table->getField($field->getNext());
+ } else {
+ $swap =& $table->getField($fieldparam);
+ $field =& $table->getField($swap->getPrevious());
+ }
+
+ /// Change the field before the pair
+ if ($field->getPrevious()) {
+ $prev =& $table->getField($field->getPrevious());
+ $prev->setNext($swap->getName());
+ $swap->setPrevious($prev->getName());
+ $prev->setChanged(true);
+ } else {
+ $swap->setPrevious(NULL);
+ }
+ /// Change the field after the pair
+ if ($swap->getNext()) {
+ $next =& $table->getField($swap->getNext());
+ $next->setPrevious($field->getName());
+ $field->setNext($next->getName());
+ $next->setChanged(true);
+ } else {
+ $field->setNext(NULL);
+ }
+ /// Swap the fields
+ $field->setPrevious($swap->getName());
+ $swap->setNext($field->getName());
+
+ /// Mark fields as changed
+ $field->setChanged(true);
+ $swap->setChanged(true);
+
+ /// Table has changed
+ $table->setChanged(true);
+
+ /// Reorder the fields
+ $table->orderFields($fields);
+
+ /// Recalculate the hash
+ $structure->calculateHash(true);
+
+ /// If the hash has changed from the original one, change the version
+ /// and mark the structure as changed
+ $origstructure =& $dbdir->xml_file->getStructure();
+ if ($structure->getHash() != $origstructure->getHash()) {
+ $structure->setVersion(userdate(time(), '%Y%m%d', 99, false));
+ $structure->setChanged(true);
+ }
+
+ /// Launch postaction if exists (leave this here!)
+ if ($this->getPostAction() && $result) {
+ return $this->launch($this->getPostAction());
+ }
+
+ /// Return ok if arrived here
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/move_updown_index/move_updown_index.class.php b/admin/xmldb/actions/move_updown_index/move_updown_index.class.php
new file mode 100644
index 00000000000..01d46d19318
--- /dev/null
+++ b/admin/xmldb/actions/move_updown_index/move_updown_index.class.php
@@ -0,0 +1,146 @@
+loadStrings(array(
+ /// 'key' => 'module',
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_NONE;
+ //$this->does_generate = ACTION_GENERATE_HTML;
+
+ /// These are always here
+ global $CFG, $XMLDB;
+
+ /// Do the job, setting result as needed
+ /// Get the dir containing the file
+ $dirpath = required_param('dir', PARAM_CLEAN);
+ $dirpath = stripslashes_safe($dirpath);
+
+ /// Get the correct dirs
+ if (!empty($XMLDB->dbdirs)) {
+ $dbdir =& $XMLDB->dbdirs[$dirpath];
+ } else {
+ return false;
+ }
+ if (!empty($XMLDB->editeddirs)) {
+ $editeddir =& $XMLDB->editeddirs[$dirpath];
+ $structure =& $editeddir->xml_file->getStructure();
+ }
+ /// ADD YOUR CODE HERE
+ $prev = NULL;
+ $next = NULL;
+ $tableparam = required_param('table', PARAM_CLEAN);
+ $indexparam = required_param('index', PARAM_CLEAN);
+ $direction = required_param('direction', PARAM_ALPHA);
+ $tables =& $structure->getTables();
+ $table =& $structure->getTable($tableparam);
+ $indexes =& $table->getIndexes();
+ if ($direction == 'down') {
+ $index =& $table->getIndex($indexparam);
+ $swap =& $table->getIndex($index->getNext());
+ } else {
+ $swap =& $table->getIndex($indexparam);
+ $index =& $table->getIndex($swap->getPrevious());
+ }
+
+ /// Change the index before the pair
+ if ($index->getPrevious()) {
+ $prev =& $table->getIndex($index->getPrevious());
+ $prev->setNext($swap->getName());
+ $swap->setPrevious($prev->getName());
+ $prev->setChanged(true);
+ } else {
+ $swap->setPrevious(NULL);
+ }
+ /// Change the field after the pair
+ if ($swap->getNext()) {
+ $next =& $table->getIndex($swap->getNext());
+ $next->setPrevious($index->getName());
+ $index->setNext($next->getName());
+ $next->setChanged(true);
+ } else {
+ $index->setNext(NULL);
+ }
+ /// Swap the indexes
+ $index->setPrevious($swap->getName());
+ $swap->setNext($index->getName());
+
+ /// Mark indexes as changed
+ $index->setChanged(true);
+ $swap->setChanged(true);
+
+ /// Table has changed
+ $table->setChanged(true);
+
+ /// Reorder the indexes
+ $table->orderIndexes($indexes);
+
+ /// Recalculate the hash
+ $structure->calculateHash(true);
+
+ /// If the hash has changed from the original one, change the version
+ /// and mark the structure as changed
+ $origstructure =& $dbdir->xml_file->getStructure();
+ if ($structure->getHash() != $origstructure->getHash()) {
+ $structure->setVersion(userdate(time(), '%Y%m%d', 99, false));
+ $structure->setChanged(true);
+ }
+
+ /// Launch postaction if exists (leave this here!)
+ if ($this->getPostAction() && $result) {
+ return $this->launch($this->getPostAction());
+ }
+
+ /// Return ok if arrived here
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/move_updown_key/move_updown_key.class.php b/admin/xmldb/actions/move_updown_key/move_updown_key.class.php
new file mode 100644
index 00000000000..5a0b0c2c2fb
--- /dev/null
+++ b/admin/xmldb/actions/move_updown_key/move_updown_key.class.php
@@ -0,0 +1,146 @@
+loadStrings(array(
+ /// 'key' => 'module',
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_NONE;
+ //$this->does_generate = ACTION_GENERATE_HTML;
+
+ /// These are always here
+ global $CFG, $XMLDB;
+
+ /// Do the job, setting result as needed
+ /// Get the dir containing the file
+ $dirpath = required_param('dir', PARAM_CLEAN);
+ $dirpath = stripslashes_safe($dirpath);
+
+ /// Get the correct dirs
+ if (!empty($XMLDB->dbdirs)) {
+ $dbdir =& $XMLDB->dbdirs[$dirpath];
+ } else {
+ return false;
+ }
+ if (!empty($XMLDB->editeddirs)) {
+ $editeddir =& $XMLDB->editeddirs[$dirpath];
+ $structure =& $editeddir->xml_file->getStructure();
+ }
+ /// ADD YOUR CODE HERE
+ $prev = NULL;
+ $next = NULL;
+ $tableparam = required_param('table', PARAM_CLEAN);
+ $keyparam = required_param('key', PARAM_CLEAN);
+ $direction = required_param('direction', PARAM_ALPHA);
+ $tables =& $structure->getTables();
+ $table =& $structure->getTable($tableparam);
+ $keys =& $table->getKeys();
+ if ($direction == 'down') {
+ $key =& $table->getKey($keyparam);
+ $swap =& $table->getKey($key->getNext());
+ } else {
+ $swap =& $table->getKey($keyparam);
+ $key =& $table->getKey($swap->getPrevious());
+ }
+
+ /// Change the key before the pair
+ if ($key->getPrevious()) {
+ $prev =& $table->getKey($key->getPrevious());
+ $prev->setNext($swap->getName());
+ $swap->setPrevious($prev->getName());
+ $prev->setChanged(true);
+ } else {
+ $swap->setPrevious(NULL);
+ }
+ /// Change the key after the pair
+ if ($swap->getNext()) {
+ $next =& $table->getKey($swap->getNext());
+ $next->setPrevious($key->getName());
+ $key->setNext($next->getName());
+ $next->setChanged(true);
+ } else {
+ $key->setNext(NULL);
+ }
+ /// Swap the keys
+ $key->setPrevious($swap->getName());
+ $swap->setNext($key->getName());
+
+ /// Mark keys as changed
+ $key->setChanged(true);
+ $swap->setChanged(true);
+
+ /// Table has changed
+ $table->setChanged(true);
+
+ /// Reorder the keys
+ $table->orderKeys($keys);
+
+ /// Recalculate the hash
+ $structure->calculateHash(true);
+
+ /// If the hash has changed from the original one, change the version
+ /// and mark the structure as changed
+ $origstructure =& $dbdir->xml_file->getStructure();
+ if ($structure->getHash() != $origstructure->getHash()) {
+ $structure->setVersion(userdate(time(), '%Y%m%d', 99, false));
+ $structure->setChanged(true);
+ }
+
+ /// Launch postaction if exists (leave this here!)
+ if ($this->getPostAction() && $result) {
+ return $this->launch($this->getPostAction());
+ }
+
+ /// Return ok if arrived here
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/move_updown_statement/move_updown_statement.class.php b/admin/xmldb/actions/move_updown_statement/move_updown_statement.class.php
new file mode 100644
index 00000000000..9b9cdf9cb5d
--- /dev/null
+++ b/admin/xmldb/actions/move_updown_statement/move_updown_statement.class.php
@@ -0,0 +1,140 @@
+loadStrings(array(
+ /// 'key' => 'module',
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_NONE;
+ //$this->does_generate = ACTION_GENERATE_HTML;
+
+ /// These are always here
+ global $CFG, $XMLDB;
+
+ /// Do the job, setting result as needed
+ /// Get the dir containing the file
+ $dirpath = required_param('dir', PARAM_CLEAN);
+ $dirpath = stripslashes_safe($dirpath);
+
+ /// Get the correct dirs
+ if (!empty($XMLDB->dbdirs)) {
+ $dbdir =& $XMLDB->dbdirs[$dirpath];
+ } else {
+ return false;
+ }
+ if (!empty($XMLDB->editeddirs)) {
+ $editeddir =& $XMLDB->editeddirs[$dirpath];
+ $structure =& $editeddir->xml_file->getStructure();
+ }
+ /// ADD YOUR CODE HERE
+ $prev = NULL;
+ $next = NULL;
+ $statementparam = required_param('statement', PARAM_CLEAN);
+ $direction = required_param('direction', PARAM_ALPHA);
+ $statements =& $structure->getStatements();
+ if ($direction == 'down') {
+ $statement =& $structure->getStatement($statementparam);
+ $swap =& $structure->getStatement($statement->getNext());
+ } else {
+ $swap =& $structure->getStatement($statementparam);
+ $statement =& $structure->getStatement($swap->getPrevious());
+ }
+
+ /// Change the statement before the pair
+ if ($statement->getPrevious()) {
+ $prev =& $structure->getStatement($statement->getPrevious());
+ $prev->setNext($swap->getName());
+ $swap->setPrevious($prev->getName());
+ $prev->setChanged(true);
+ } else {
+ $swap->setPrevious(NULL);
+ }
+ /// Change the statement after the pair
+ if ($swap->getNext()) {
+ $next =& $structure->getStatement($swap->getNext());
+ $next->setPrevious($statement->getName());
+ $statement->setNext($next->getName());
+ $next->setChanged(true);
+ } else {
+ $statement->setNext(NULL);
+ }
+ /// Swap the statements
+ $statement->setPrevious($swap->getName());
+ $swap->setNext($statement->getName());
+
+ /// Statement has changed
+ $statement->setChanged(true);
+
+ /// Reorder the structure
+ $structure->orderStatements($statements);
+ /// Send statements back to structure (the order above break refs)
+ $structure->setStatements($statements);
+ /// Recalculate the hash
+ $structure->calculateHash(true);
+
+ /// If the hash has changed from the original one, change the version
+ /// and mark the structure as changed
+ $origstructure =& $dbdir->xml_file->getStructure();
+ if ($structure->getHash() != $origstructure->getHash()) {
+ $structure->setVersion(userdate(time(), '%Y%m%d', 99, false));
+ $structure->setChanged(true);
+ }
+
+ /// Launch postaction if exists (leave this here!)
+ if ($this->getPostAction() && $result) {
+ return $this->launch($this->getPostAction());
+ }
+
+ /// Return ok if arrived here
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/move_updown_table/move_updown_table.class.php b/admin/xmldb/actions/move_updown_table/move_updown_table.class.php
new file mode 100644
index 00000000000..58e2660140f
--- /dev/null
+++ b/admin/xmldb/actions/move_updown_table/move_updown_table.class.php
@@ -0,0 +1,140 @@
+loadStrings(array(
+ /// 'key' => 'module',
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_NONE;
+ //$this->does_generate = ACTION_GENERATE_HTML;
+
+ /// These are always here
+ global $CFG, $XMLDB;
+
+ /// Do the job, setting result as needed
+ /// Get the dir containing the file
+ $dirpath = required_param('dir', PARAM_CLEAN);
+ $dirpath = stripslashes_safe($dirpath);
+
+ /// Get the correct dirs
+ if (!empty($XMLDB->dbdirs)) {
+ $dbdir =& $XMLDB->dbdirs[$dirpath];
+ } else {
+ return false;
+ }
+ if (!empty($XMLDB->editeddirs)) {
+ $editeddir =& $XMLDB->editeddirs[$dirpath];
+ $structure =& $editeddir->xml_file->getStructure();
+ }
+ /// ADD YOUR CODE HERE
+ $prev = NULL;
+ $next = NULL;
+ $tableparam = required_param('table', PARAM_CLEAN);
+ $direction = required_param('direction', PARAM_ALPHA);
+ $tables =& $structure->getTables();
+ if ($direction == 'down') {
+ $table =& $structure->getTable($tableparam);
+ $swap =& $structure->getTable($table->getNext());
+ } else {
+ $swap =& $structure->getTable($tableparam);
+ $table =& $structure->getTable($swap->getPrevious());
+ }
+
+ /// Change the table before the pair
+ if ($table->getPrevious()) {
+ $prev =& $structure->getTable($table->getPrevious());
+ $prev->setNext($swap->getName());
+ $swap->setPrevious($prev->getName());
+ $prev->setChanged(true);
+ } else {
+ $swap->setPrevious(NULL);
+ }
+ /// Change the table after the pair
+ if ($swap->getNext()) {
+ $next =& $structure->getTable($swap->getNext());
+ $next->setPrevious($table->getName());
+ $table->setNext($next->getName());
+ $next->setChanged(true);
+ } else {
+ $table->setNext(NULL);
+ }
+ /// Swap the tables
+ $table->setPrevious($swap->getName());
+ $swap->setNext($table->getName());
+
+ /// Table has changed
+ $table->setChanged(true);
+
+ /// Reorder the structure
+ $structure->orderTables($tables);
+ /// Send tables back to structure (the order above break refs)
+ $structure->setTables($tables);
+ /// Recalculate the hash
+ $structure->calculateHash(true);
+
+ /// If the hash has changed from the original one, change the version
+ /// and mark the structure as changed
+ $origstructure =& $dbdir->xml_file->getStructure();
+ if ($structure->getHash() != $origstructure->getHash()) {
+ $structure->setVersion(userdate(time(), '%Y%m%d', 99, false));
+ $structure->setChanged(true);
+ }
+
+ /// Launch postaction if exists (leave this here!)
+ if ($this->getPostAction() && $result) {
+ return $this->launch($this->getPostAction());
+ }
+
+ /// Return ok if arrived here
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/new_field/new_field.class.php b/admin/xmldb/actions/new_field/new_field.class.php
new file mode 100644
index 00000000000..32376799afb
--- /dev/null
+++ b/admin/xmldb/actions/new_field/new_field.class.php
@@ -0,0 +1,109 @@
+loadStrings(array(
+ /// 'key' => 'module',
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_NONE;
+ //$this->does_generate = ACTION_GENERATE_HTML;
+
+ /// These are always here
+ global $CFG, $XMLDB;
+
+ /// Do the job, setting result as needed
+ /// Get the dir containing the file
+ $dirpath = required_param('dir', PARAM_CLEAN);
+ $dirpath = stripslashes_safe($dirpath);
+
+ /// Get the correct dirs
+ if (!empty($XMLDB->dbdirs)) {
+ $dbdir =& $XMLDB->dbdirs[$dirpath];
+ } else {
+ return false;
+ }
+ if (!empty($XMLDB->editeddirs)) {
+ $editeddir =& $XMLDB->editeddirs[$dirpath];
+ $structure =& $editeddir->xml_file->getStructure();
+ }
+ /// ADD YOUR CODE HERE
+
+ $tableparam = required_param('table', PARAM_CLEAN);
+
+ $table =& $structure->getTable($tableparam);
+
+ /// If the changeme field exists, just get it and continue
+ $changeme_exists = false;
+ if ($fields =& $table->getFields()) {
+ if ($field =& $table->getField('changeme')) {
+ $changeme_exists = true;
+ }
+ }
+ if (!$changeme_exists) { /// Lets create the field
+ $field = new XMLDBField('changeme');
+ $field->setComment('Default comment for the field, please edit me');
+ $table->addField($field);
+
+ /// We have one new field, so the structure has changed
+ $structure->setVersion(userdate(time(), '%Y%m%d', 99, false));
+ $structure->setChanged(true);
+ }
+
+ /// Launch postaction if exists (leave this here!)
+ if ($this->getPostAction() && $result) {
+ return $this->launch($this->getPostAction());
+ }
+
+ /// Return ok if arrived here
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/new_index/new_index.class.php b/admin/xmldb/actions/new_index/new_index.class.php
new file mode 100644
index 00000000000..7c029cbfa25
--- /dev/null
+++ b/admin/xmldb/actions/new_index/new_index.class.php
@@ -0,0 +1,108 @@
+loadStrings(array(
+ /// 'key' => 'module',
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_NONE;
+ //$this->does_generate = ACTION_GENERATE_HTML;
+
+ /// These are always here
+ global $CFG, $XMLDB;
+
+ /// Do the job, setting result as needed
+ /// Get the dir containing the file
+ $dirpath = required_param('dir', PARAM_CLEAN);
+ $dirpath = stripslashes_safe($dirpath);
+
+ /// Get the correct dirs
+ if (!empty($XMLDB->dbdirs)) {
+ $dbdir =& $XMLDB->dbdirs[$dirpath];
+ } else {
+ return false;
+ }
+ if (!empty($XMLDB->editeddirs)) {
+ $editeddir =& $XMLDB->editeddirs[$dirpath];
+ $structure =& $editeddir->xml_file->getStructure();
+ }
+ /// ADD YOUR CODE HERE
+
+ $tableparam = required_param('table', PARAM_CLEAN);
+
+ $table =& $structure->getTable($tableparam);
+
+ /// If the changeme index exists, just get it and continue
+ $changeme_exists = false;
+ if ($indexes =& $table->getIndexes()) {
+ if ($index =& $table->getIndex('changeme')) {
+ $changeme_exists = true;
+ }
+ }
+ if (!$changeme_exists) { /// Lets create the Index
+ $index = new XMLDBIndex('changeme');
+ $index->setComment('Default comment for the index, please edit me');
+ $table->addIndex($index);
+
+ /// We have one new key, so the structure has changed
+ $structure->setVersion(userdate(time(), '%Y%m%d', 99, false));
+ $structure->setChanged(true);
+ }
+ /// Launch postaction if exists (leave this here!)
+ if ($this->getPostAction() && $result) {
+ return $this->launch($this->getPostAction());
+ }
+
+ /// Return ok if arrived here
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/new_key/new_key.class.php b/admin/xmldb/actions/new_key/new_key.class.php
new file mode 100644
index 00000000000..8e452b9fa75
--- /dev/null
+++ b/admin/xmldb/actions/new_key/new_key.class.php
@@ -0,0 +1,108 @@
+loadStrings(array(
+ /// 'key' => 'module',
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_NONE;
+ //$this->does_generate = ACTION_GENERATE_HTML;
+
+ /// These are always here
+ global $CFG, $XMLDB;
+
+ /// Do the job, setting result as needed
+ /// Get the dir containing the file
+ $dirpath = required_param('dir', PARAM_CLEAN);
+ $dirpath = stripslashes_safe($dirpath);
+
+ /// Get the correct dirs
+ if (!empty($XMLDB->dbdirs)) {
+ $dbdir =& $XMLDB->dbdirs[$dirpath];
+ } else {
+ return false;
+ }
+ if (!empty($XMLDB->editeddirs)) {
+ $editeddir =& $XMLDB->editeddirs[$dirpath];
+ $structure =& $editeddir->xml_file->getStructure();
+ }
+ /// ADD YOUR CODE HERE
+
+ $tableparam = required_param('table', PARAM_CLEAN);
+
+ $table =& $structure->getTable($tableparam);
+
+ /// If the changeme key exists, just get it and continue
+ $changeme_exists = false;
+ if ($keys =& $table->getKeys()) {
+ if ($key =& $table->getKey('changeme')) {
+ $changeme_exists = true;
+ }
+ }
+ if (!$changeme_exists) { /// Lets create the Key
+ $key = new XMLDBKey('changeme');
+ $key->setComment('Default comment for the key, please edit me');
+ $table->addKey($key);
+
+ /// We have one new key, so the structure has changed
+ $structure->setVersion(userdate(time(), '%Y%m%d', 99, false));
+ $structure->setChanged(true);
+ }
+ /// Launch postaction if exists (leave this here!)
+ if ($this->getPostAction() && $result) {
+ return $this->launch($this->getPostAction());
+ }
+
+ /// Return ok if arrived here
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/new_sentence/new_sentence.class.php b/admin/xmldb/actions/new_sentence/new_sentence.class.php
new file mode 100644
index 00000000000..739cf437781
--- /dev/null
+++ b/admin/xmldb/actions/new_sentence/new_sentence.class.php
@@ -0,0 +1,120 @@
+loadStrings(array(
+ /// 'key' => 'module',
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_NONE;
+ //$this->does_generate = ACTION_GENERATE_HTML;
+
+ /// These are always here
+ global $CFG, $XMLDB;
+
+ /// Do the job, setting result as needed
+ /// Get the dir containing the file
+ $dirpath = required_param('dir', PARAM_CLEAN);
+ $dirpath = stripslashes_safe($dirpath);
+
+ /// Get the correct dirs
+ if (!empty($XMLDB->dbdirs)) {
+ $dbdir =& $XMLDB->dbdirs[$dirpath];
+ } else {
+ return false;
+ }
+ if (!empty($XMLDB->editeddirs)) {
+ $editeddir =& $XMLDB->editeddirs[$dirpath];
+ $structure =& $editeddir->xml_file->getStructure();
+ }
+ /// ADD YOUR CODE HERE
+
+ $statementparam = required_param('statement', PARAM_CLEAN);
+ $basesentenceparam = optional_param('basesentence', NULL, PARAM_CLEAN);
+
+ $statement =& $structure->getStatement($statementparam);
+ $sentences =& $statement->getSentences();
+
+ $sentence = NULL;
+
+ /// If some sentence has been specified, create the new one
+ /// based on it
+ if (!empty($basesentenceparam)) {
+ $sentence = $sentences[$basesentenceparam];
+ }
+ /// Else, try to create the new one based in the last
+ if (empty($sentence) && !empty($sentences)) {
+ $sentence = end($sentences);
+ }
+ /// Else, create one sentence by hand
+ if (empty($sentence)) {
+ $sentence = "(list, of, fields) VALUES ('list', 'of', 'values')";
+ }
+
+ /// Add the sentence to the statement
+ $statement->addSentence($sentence);
+
+ /// We have one new sentence, so the statement and the structure has changed
+ $statement->setChanged(true);
+ $structure->setVersion(userdate(time(), '%Y%m%d', 99, false));
+ $structure->setChanged(true);
+
+ /// Launch postaction if exists (leave this here!)
+ if ($this->getPostAction() && $result) {
+ return $this->launch($this->getPostAction());
+ }
+
+ /// Return ok if arrived here
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/new_statement/new_statement.class.php b/admin/xmldb/actions/new_statement/new_statement.class.php
new file mode 100644
index 00000000000..8dfc3137dbe
--- /dev/null
+++ b/admin/xmldb/actions/new_statement/new_statement.class.php
@@ -0,0 +1,161 @@
+loadStrings(array(
+ 'statementtype' => 'xmldb',
+ 'statementtable' => 'xmldb',
+ 'create' => 'xmldb',
+ 'back' => 'xmldb'
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_GENERATE_HTML;
+
+ /// These are always here
+ global $CFG, $XMLDB, $db;
+
+ /// Do the job, setting result as needed
+ /// Get the dir containing the file
+ $dirpath = required_param('dir', PARAM_CLEAN);
+ $dirpath = stripslashes_safe($dirpath);
+
+ /// Get the correct dirs
+ if (!empty($XMLDB->dbdirs)) {
+ $dbdir =& $XMLDB->dbdirs[$dirpath];
+ } else {
+ return false;
+ }
+ if (!empty($XMLDB->editeddirs)) {
+ $editeddir =& $XMLDB->editeddirs[$dirpath];
+ $structure =& $editeddir->xml_file->getStructure();
+ }
+ /// ADD YOUR CODE HERE
+ $tableparam = optional_param('table', NULL, PARAM_CLEAN);
+ $typeparam = optional_param('type', NULL, PARAM_CLEAN);
+
+ /// If no table or type, show form
+ if (!$tableparam || !$typeparam) {
+ /// No postaction here
+ $this->postaction = NULL;
+ /// Get list of tables
+ $dbtables = $db->MetaTables('TABLES');
+ $selecttables = array();
+ foreach ($dbtables as $dbtable) {
+ $dbtable = str_replace($CFG->prefix, '', $dbtable);
+ $selecttables[$dbtable] = $dbtable;
+ }
+ /// Get list of statement types
+ $typeoptions = array (XMLDB_STATEMENT_INSERT => XMLDBStatement::getXMLDBStatementName(XMLDB_STATEMENT_INSERT),
+ XMLDB_STATEMENT_UPDATE => XMLDBStatement::getXMLDBStatementName(XMLDB_STATEMENT_UPDATE),
+ XMLDB_STATEMENT_DELETE => XMLDBStatement::getXMLDBStatementName(XMLDB_STATEMENT_DELETE),
+ XMLDB_STATEMENT_CUSTOM => XMLDBStatement::getXMLDBStatementName(XMLDB_STATEMENT_CUSTOM));
+ if (!$selecttables) {
+ $this->errormsg = 'No tables available to create statements';
+ return false;
+ }
+ /// Now build the form
+ $o = '';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= ' ';
+
+ $this->output = $o;
+
+
+ /// If table, retrofit information and, if everything works,
+ /// go to the table edit action
+ } else {
+ /// Get some params (table is mandatory here)
+ $tableparam = required_param('table', PARAM_CLEAN);
+ $typeparam = required_param('type', PARAM_CLEAN);
+
+ /// Only insert is allowed :-/
+ if ($typeparam != XMLDB_STATEMENT_INSERT) {
+ $this->errormsg = 'Only insert of records is supported';
+ return false;
+ }
+
+ /// Calculate the name of the statement
+ $typename = XMLDBStatement::getXMLDBStatementName($typeparam);
+ $name = trim(strtolower($typename . ' ' . $tableparam));
+
+ /// Check that this Statement hasn't been created before
+ if ($structure->getStatement($name)) {
+ $this->errormsg = 'The statement "' . $name . '" already exists, please use it to add more sentences';
+ return false;
+ }
+
+ /// Create one new XMLDBStatement
+ $statement = new XMLDBStatement($name);
+ $statement->setType($typeparam);
+ $statement->setTable($tableparam);
+ $statement->setComment('Initial ' . $typename . ' of records on table ' . $tableparam);
+ /// Finally, add the whole retroffited table to the structure
+ /// in the place specified
+ $structure->addStatement($statement);
+ }
+
+ /// Launch postaction if exists (leave this here!)
+ if ($this->getPostAction() && $result) {
+ return $this->launch($this->getPostAction());
+ }
+
+ /// Return ok if arrived here
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/new_table/new_table.class.php b/admin/xmldb/actions/new_table/new_table.class.php
new file mode 100644
index 00000000000..98cabf87080
--- /dev/null
+++ b/admin/xmldb/actions/new_table/new_table.class.php
@@ -0,0 +1,121 @@
+loadStrings(array(
+ /// 'key' => 'module',
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_NONE;
+ //$this->does_generate = ACTION_GENERATE_HTML;
+
+ /// These are always here
+ global $CFG, $XMLDB;
+
+ /// Do the job, setting result as needed
+ /// Get the dir containing the file
+ $dirpath = required_param('dir', PARAM_CLEAN);
+ $dirpath = stripslashes_safe($dirpath);
+
+ /// Get the correct dirs
+ if (!empty($XMLDB->dbdirs)) {
+ $dbdir =& $XMLDB->dbdirs[$dirpath];
+ } else {
+ return false;
+ }
+ if (!empty($XMLDB->editeddirs)) {
+ $editeddir =& $XMLDB->editeddirs[$dirpath];
+ $structure =& $editeddir->xml_file->getStructure();
+ }
+ /// ADD YOUR CODE HERE
+
+ /// If the changeme table exists, just get it and continue
+ $changeme_exists = false;
+ if ($tables =& $structure->getTables()) {
+ if ($table =& $structure->getTable('changeme')) {
+ $changeme_exists = true;
+ }
+ }
+ if (!$changeme_exists) { /// Lets create the table
+ $field = new XMLDBField('id');
+ $field->setType(XMLDB_TYPE_INTEGER);
+ $field->setLength(10);
+ $field->setNotNull(true);
+ $field->setSequence(true);
+ $field->setComment('id of the table, please edit me');
+ $field->setLoaded(true);
+ $field->setChanged(true);
+
+ $key = new XMLDBKey('primary');
+ $key->setType(XMLDB_KEY_PRIMARY);
+ $key->setFields(array('id'));
+ $key->setComment('primary key of the table, please edit me');
+ $key->setLoaded(true);
+ $key->setChanged(true);
+
+ $table = new XMLDBTable('changeme');
+ $table->setComment('Default comment for the table, please edit me');
+ $table->addField($field);
+ $table->addKey($key);
+
+ /// Finally, add the whole retroffited table to the structure
+ /// in the place specified
+ $structure->addTable($table);
+ }
+ /// Launch postaction if exists (leave this here!)
+ if ($this->getPostAction() && $result) {
+ return $this->launch($this->getPostAction());
+ }
+
+ /// Return ok if arrived here
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/new_table_from_mysql/new_table_from_mysql.class.php b/admin/xmldb/actions/new_table_from_mysql/new_table_from_mysql.class.php
new file mode 100644
index 00000000000..549a920c6ea
--- /dev/null
+++ b/admin/xmldb/actions/new_table_from_mysql/new_table_from_mysql.class.php
@@ -0,0 +1,188 @@
+loadStrings(array(
+ 'createtable' => 'xmldb',
+ 'aftertable' => 'xmldb',
+ 'create' => 'xmldb',
+ 'back' => 'xmldb'
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_GENERATE_HTML;
+
+ /// These are always here
+ global $CFG, $XMLDB, $db;
+
+ /// Do the job, setting result as needed
+ /// Get the dir containing the file
+ $dirpath = required_param('dir', PARAM_CLEAN);
+ $dirpath = stripslashes_safe($dirpath);
+
+ /// Get the correct dirs
+ if (!empty($XMLDB->dbdirs)) {
+ $dbdir =& $XMLDB->dbdirs[$dirpath];
+ } else {
+ return false;
+ }
+ if (!empty($XMLDB->editeddirs)) {
+ $editeddir =& $XMLDB->editeddirs[$dirpath];
+ $structure =& $editeddir->xml_file->getStructure();
+ }
+ /// ADD YOUR CODE HERE
+ $tableparam = optional_param('table', NULL, PARAM_CLEAN);
+
+ /// If no table, show form
+ if (!$tableparam) {
+ /// No postaction here
+ $this->postaction = NULL;
+ /// Get list of tables
+ $dbtables = $db->MetaTables('TABLES');
+ $selecttables = array();
+ foreach ($dbtables as $dbtable) {
+ $dbtable = str_replace($CFG->prefix, '', $dbtable);
+ $i = $structure->findTableInArray($dbtable);
+ if ($i === NULL) {
+ $selecttables[$dbtable] = $dbtable;
+ }
+ }
+ /// Get list of after tables
+ $aftertables = array();
+ if ($tables =& $structure->getTables()) {
+ foreach ($tables as $aftertable) {
+ $aftertables[$aftertable->getName()] = $aftertable->getName();
+ }
+ }
+ if (!$selecttables) {
+ $this->errormsg = 'No tables available to be retrofitted';
+ return false;
+ }
+ /// Now build the form
+ $o = '';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= ' ';
+
+ $this->output = $o;
+
+
+ /// If table, retrofit information and, if everything works,
+ /// go to the table edit action
+ } else {
+ /// Get some params (table is mandatory here)
+ $tableparam = required_param('table', PARAM_CLEAN);
+ $afterparam = required_param('after', PARAM_CLEAN);
+
+ /// Create one new XMLDBTable
+ $table = new XMLDBTable(strtolower(trim($tableparam)));
+ $table->setComment($table->getName() . ' table retrofitted from MySQL');
+ /// Get fields info from ADODb
+ $dbfields = $db->MetaColumns($CFG->prefix . $tableparam);
+ if ($dbfields) {
+ foreach ($dbfields as $dbfield) {
+ /// Create new XMLDB field
+ $field = new XMLDBField(strtolower($dbfield->name));
+ /// Set field with info retrofitted
+ $field->setFromADOField($dbfield);
+ /// Add field to the table
+ $table->addField($field);
+ }
+ }
+ /// Get PK, UK and indexes info from ADODb
+ $dbindexes = $db->MetaIndexes($CFG->prefix . $tableparam, true);
+ if ($dbindexes) {
+ $lastkey = NULL; //To temp store the last key processed
+ foreach ($dbindexes as $indexname => $dbindex) {
+ /// Add the indexname to the array
+ $dbindex['name'] = $indexname;
+ /// We are handling one XMLDBKey (primaries + uniques)
+ if ($dbindex['unique']) {
+ $key = new XMLDBKey(strtolower($dbindex['name']));
+ /// Set key with info retrofitted
+ $key->setFromADOKey($dbindex);
+ /// Set default comment to PKs
+ if ($key->getType() == XMLDB_KEY_PRIMARY) {
+ $key->setComment('Primary key for ' . $table->getName());
+ }
+ /// Add key to the table
+ $table->addKey($key);
+
+ /// We are handling one XMLDBIndex (non-uniques)
+ } else {
+ $index = new XMLDBIndex(strtolower($dbindex['name']));
+ /// Set index with info retrofitted
+ $index->setFromADOIndex($dbindex);
+ /// Add index to the table
+ $table->addIndex($index);
+ }
+ }
+ }
+ /// Finally, add the whole retroffited table to the structure
+ /// in the place specified
+ $structure->addTable($table, $afterparam);
+ }
+
+ /// Launch postaction if exists (leave this here!)
+ if ($this->getPostAction() && $result) {
+ return $this->launch($this->getPostAction());
+ }
+
+ /// Return ok if arrived here
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/revert_changes/revert_changes.class.php b/admin/xmldb/actions/revert_changes/revert_changes.class.php
new file mode 100644
index 00000000000..246ac0089ab
--- /dev/null
+++ b/admin/xmldb/actions/revert_changes/revert_changes.class.php
@@ -0,0 +1,117 @@
+loadStrings(array(
+ 'confirmrevertchanges' => 'xmldb',
+ 'yes' => '',
+ 'no' => ''
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_GENERATE_HTML;
+
+ /// These are always here
+ global $CFG, $XMLDB;
+
+ /// Do the job, setting result as needed
+
+ /// Get the dir containing the file
+ $dirpath = required_param('dir', PARAM_CLEAN);
+ $dirpath = stripslashes_safe($dirpath);
+
+ $confirmed = optional_param('confirmed', false, PARAM_BOOL);
+
+ /// If not confirmed, show confirmation box
+ if (!$confirmed) {
+ $o = '';
+ $o.= ' ';
+ $o.= ' ' . $this->str['confirmrevertchanges'] . ' ' . $dirpath . '
';
+ $o.= ' ';
+ $o.= ' ';
+ $o.= '
';
+
+ $this->output = $o;
+ } else {
+ /// Get the original dir and delete some elements
+ if (!empty($XMLDB->dbdirs)) {
+ if (isset($XMLDB->dbdirs[$dirpath])) {
+ $dbdir =& $XMLDB->dbdirs[$dirpath];
+ if ($dbdir) {
+ unset($dbdir->xml_changed);
+ }
+ }
+ }
+ /// Get the edited dir and delete it completely
+ if (!empty($XMLDB->editeddirs)) {
+ if (isset($XMLDB->editeddirs[$dirpath])) {
+ unset($XMLDB->editeddirs[$dirpath]);
+ }
+ }
+ }
+
+ /// Launch postaction if exists (leave this here!)
+ if ($this->getPostAction() && $result) {
+ return $this->launch($this->getPostAction());
+ }
+
+ /// Return ok if arrived here
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/save_xml_file/save_xml_file.class.php b/admin/xmldb/actions/save_xml_file/save_xml_file.class.php
new file mode 100644
index 00000000000..7e365d0ae86
--- /dev/null
+++ b/admin/xmldb/actions/save_xml_file/save_xml_file.class.php
@@ -0,0 +1,106 @@
+loadStrings(array(
+ /// 'key' => 'module'
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_NONE;
+
+ /// These are always here
+ global $CFG, $XMLDB;
+
+ /// Do the job, setting result as needed
+
+ /// Get the dir containing the file
+ $dirpath = required_param('dir', PARAM_CLEAN);
+ $dirpath = stripslashes_safe($dirpath);
+
+ /// Get the edited dir
+ if (!empty($XMLDB->editeddirs)) {
+ if (isset($XMLDB->editeddirs[$dirpath])) {
+ $editeddir =& $XMLDB->editeddirs[$dirpath];
+ }
+ }
+ /// Copy the edited dir over the original one
+ if (!empty($XMLDB->dbdirs)) {
+ if (isset($XMLDB->dbdirs[$dirpath])) {
+ $XMLDB->dbdirs[$dirpath] = unserialize(serialize($editeddir));
+ $dbdir =& $XMLDB->dbdirs[$dirpath];
+ }
+ }
+
+ /// Save the original dir
+ $result = $dbdir->xml_file->saveXMLFile();
+
+ if ($result) {
+ /// Delete the edited dir
+ unset ($XMLDB->editeddirs[$dirpath]);
+ /// Unload de originaldir
+ unset($XMLDB->dbdirs[$dirpath]->xml_file);
+ unset($XMLDB->dbdirs[$dirpath]->xml_loaded);
+ unset($XMLDB->dbdirs[$dirpath]->xml_changed);
+ unset($XMLDB->dbdirs[$dirpath]->xml_exists);
+ unset($XMLDB->dbdirs[$dirpath]->xml_writeable);
+ } else {
+ $errormsg = 'Error saving XML file (' . $dirpath . ')';
+ }
+
+ /// Launch postaction if exists (leave this here!)
+ if ($this->getPostAction() && $result) {
+ return $this->launch($this->getPostAction());
+ }
+
+ /// Return ok if arrived here
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/template/template.class.php b/admin/xmldb/actions/template/template.class.php
new file mode 100644
index 00000000000..f54f3827392
--- /dev/null
+++ b/admin/xmldb/actions/template/template.class.php
@@ -0,0 +1,91 @@
+loadStrings(array(
+ /// 'key' => 'module',
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_NONE;
+ //$this->does_generate = ACTION_GENERATE_HTML;
+
+ /// These are always here
+ global $CFG, $XMLDB;
+
+ /// Do the job, setting result as needed
+ /// Get the dir containing the file
+ $dirpath = required_param('dir', PARAM_CLEAN);
+ $dirpath = stripslashes_safe($dirpath);
+
+ /// Get the correct dirs
+ if (!empty($XMLDB->dbdirs)) {
+ $dbdir =& $XMLDB->dbdirs[$dirpath];
+ } else {
+ return false;
+ }
+ if (!empty($XMLDB->editeddirs)) {
+ $editeddir =& $XMLDB->editeddirs[$dirpath];
+ $structure =& $editeddir->xml_file->getStructure();
+ }
+ /// ADD YOUR CODE HERE
+
+
+
+
+ /// Launch postaction if exists (leave this here!)
+ if ($this->getPostAction() && $result) {
+ return $this->launch($this->getPostAction());
+ }
+
+ /// Return ok if arrived here
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/unload_xml_file/unload_xml_file.class.php b/admin/xmldb/actions/unload_xml_file/unload_xml_file.class.php
new file mode 100644
index 00000000000..65568802fbd
--- /dev/null
+++ b/admin/xmldb/actions/unload_xml_file/unload_xml_file.class.php
@@ -0,0 +1,97 @@
+loadStrings(array(
+ /// 'key' => 'module',
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_NONE;
+ //$this->does_generate = ACTION_GENERATE_HTML;
+
+ /// These are always here
+ global $CFG, $XMLDB;
+
+ /// Do the job, setting result as needed
+
+ /// Get the dir containing the file
+ $dirpath = required_param('dir', PARAM_CLEAN);
+ $dirpath = stripslashes_safe($dirpath);
+
+ /// Get the original dir and delete some elements
+ if (!empty($XMLDB->dbdirs)) {
+ if (isset($XMLDB->dbdirs[$dirpath])) {
+ $dbdir =& $XMLDB->dbdirs[$dirpath];
+ if ($dbdir) {
+ unset($dbdir->xml_file);
+ unset($dbdir->xml_loaded);
+ unset($dbdir->xml_changed);
+ unset($dbdir->xml_exists);
+ unset($dbdir->xml_writeable);
+ }
+ }
+ }
+ /// Get the edited dir and delete it completely
+ if (!empty($XMLDB->editeddirs)) {
+ if (isset($XMLDB->editeddirs[$dirpath])) {
+ unset($XMLDB->editeddirs[$dirpath]);
+ }
+ }
+
+ /// Launch postaction if exists (leave this here!)
+ if ($this->getPostAction() && $result) {
+ return $this->launch($this->getPostAction());
+ }
+
+ /// Return ok if arrived here
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/view_field_xml/view_field_xml.class.php b/admin/xmldb/actions/view_field_xml/view_field_xml.class.php
new file mode 100644
index 00000000000..34e0f136288
--- /dev/null
+++ b/admin/xmldb/actions/view_field_xml/view_field_xml.class.php
@@ -0,0 +1,139 @@
+loadStrings(array(
+ /// 'key' => 'module',
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_GENERATE_XML;
+
+ /// These are always here
+ global $CFG, $XMLDB;
+
+ /// Do the job, setting result as needed
+
+ /// Get the file parameter
+ $field = required_param('field', PARAM_CLEAN);
+ $table = required_param('table', PARAM_CLEAN);
+ $select = required_param('select', PARAM_ALPHA); //original/edited
+ /// Get the dir containing the file
+ $dirpath = required_param('dir', PARAM_CLEAN);
+ $dirpath = stripslashes_safe($dirpath);
+
+ /// Get the correct dir
+ if ($select == 'original') {
+ if (!empty($XMLDB->dbdirs)) {
+ $base =& $XMLDB->dbdirs[$dirpath];
+ }
+ } else if ($select == 'edited') {
+ if (!empty($XMLDB->editeddirs)) {
+ $base =& $XMLDB->editeddirs[$dirpath];
+ }
+ } else {
+ $this->errormsg = 'Cannot access to ' . $select . ' info';
+ $result = false;
+ }
+ if ($base) {
+ /// Only if the directory exists and it has been loaded
+ if (!$base->path_exists || !$base->xml_loaded) {
+ $this->errormsg = 'Directory ' . $dirpath . ' not loaded';
+ return false;
+ }
+ } else {
+ $this->errormsg = 'Problem handling ' . $select . ' files';
+ return false;
+ }
+
+ /// Get the structure
+ if ($result) {
+ if (!$structure =& $base->xml_file->getStructure()) {
+ $this->errormsg = 'Error retrieving ' . $select . ' structure';
+ $result = false;
+ }
+ }
+ /// Get the tables
+ if ($result) {
+ if (!$tables =& $structure->getTables()) {
+ $this->errormsg = 'Error retrieving ' . $select . ' tables';
+ $result = false;
+ }
+ }
+ /// Get the table
+ if ($result && !$t = $structure->getTable($table)) {
+ $this->errormsg = 'Error retrieving ' . $table . ' table';
+ $result = false;
+ }
+ /// Get the fields
+ if ($result) {
+ if (!$fields =& $t->getFields()) {
+ $this->errormsg = 'Error retrieving ' . $select . ' fields';
+ $result = false;
+ }
+ }
+ /// Get the field
+ if ($result && !$f = $t->getField($field)) {
+ $this->errormsg = 'Error retrieving ' . $field . ' field';
+ $result = false;
+ }
+
+ if ($result) {
+ /// Everything is ok. Generate the XML output
+ $this->output = $f->xmlOutput();
+ } else {
+ /// Switch to HTML and error
+ $this->does_generate = ACTION_GENERATE_HTML;
+ }
+
+ /// Return ok if arrived here
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/view_index_xml/view_index_xml.class.php b/admin/xmldb/actions/view_index_xml/view_index_xml.class.php
new file mode 100644
index 00000000000..14e43eb68c4
--- /dev/null
+++ b/admin/xmldb/actions/view_index_xml/view_index_xml.class.php
@@ -0,0 +1,139 @@
+loadStrings(array(
+ /// 'key' => 'module',
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_GENERATE_XML;
+
+ /// These are always here
+ global $CFG, $XMLDB;
+
+ /// Do the job, setting result as needed
+
+ /// Get the file parameter
+ $index = required_param('index', PARAM_CLEAN);
+ $table = required_param('table', PARAM_CLEAN);
+ $select = required_param('select', PARAM_ALPHA); //original/edited
+ /// Get the dir containing the file
+ $dirpath = required_param('dir', PARAM_CLEAN);
+ $dirpath = stripslashes_safe($dirpath);
+
+ /// Get the correct dir
+ if ($select == 'original') {
+ if (!empty($XMLDB->dbdirs)) {
+ $base =& $XMLDB->dbdirs[$dirpath];
+ }
+ } else if ($select == 'edited') {
+ if (!empty($XMLDB->editeddirs)) {
+ $base =& $XMLDB->editeddirs[$dirpath];
+ }
+ } else {
+ $this->errormsg = 'Cannot access to ' . $select . ' info';
+ $result = false;
+ }
+ if ($base) {
+ /// Only if the directory exists and it has been loaded
+ if (!$base->path_exists || !$base->xml_loaded) {
+ $this->errormsg = 'Directory ' . $dirpath . ' not loaded';
+ return false;
+ }
+ } else {
+ $this->errormsg = 'Problem handling ' . $select . ' files';
+ return false;
+ }
+
+ /// Get the structure
+ if ($result) {
+ if (!$structure =& $base->xml_file->getStructure()) {
+ $this->errormsg = 'Error retrieving ' . $select . ' structure';
+ $result = false;
+ }
+ }
+ /// Get the tables
+ if ($result) {
+ if (!$tables =& $structure->getTables()) {
+ $this->errormsg = 'Error retrieving ' . $select . ' tables';
+ $result = false;
+ }
+ }
+ /// Get the table
+ if ($result && !$t =& $structure->getTable($table)) {
+ $this->errormsg = 'Error retrieving ' . $table . ' table';
+ $result = false;
+ }
+ /// Get the indexes
+ if ($result) {
+ if (!$indexes =& $t->getIndexes()) {
+ $this->errormsg = 'Error retrieving ' . $select . ' indexes';
+ $result = false;
+ }
+ }
+ /// Get the index
+ if ($result && !$i = $t->getIndex($index)) {
+ $this->errormsg = 'Error retrieving ' . $index . ' index';
+ $result = false;
+ }
+
+ if ($result) {
+ /// Everything is ok. Generate the XML output
+ $this->output = $i->xmlOutput();
+ } else {
+ /// Switch to HTML and error
+ $this->does_generate = ACTION_GENERATE_HTML;
+ }
+
+ /// Return ok if arrived here
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/view_key_xml/view_key_xml.class.php b/admin/xmldb/actions/view_key_xml/view_key_xml.class.php
new file mode 100644
index 00000000000..9e76a754fcd
--- /dev/null
+++ b/admin/xmldb/actions/view_key_xml/view_key_xml.class.php
@@ -0,0 +1,139 @@
+loadStrings(array(
+ /// 'key' => 'module',
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_GENERATE_XML;
+
+ /// These are always here
+ global $CFG, $XMLDB;
+
+ /// Do the job, setting result as needed
+
+ /// Get the file parameter
+ $key = required_param('key', PARAM_CLEAN);
+ $table = required_param('table', PARAM_CLEAN);
+ $select = required_param('select', PARAM_ALPHA); //original/edited
+ /// Get the dir containing the file
+ $dirpath = required_param('dir', PARAM_CLEAN);
+ $dirpath = stripslashes_safe($dirpath);
+
+ /// Get the correct dir
+ if ($select == 'original') {
+ if (!empty($XMLDB->dbdirs)) {
+ $base =& $XMLDB->dbdirs[$dirpath];
+ }
+ } else if ($select == 'edited') {
+ if (!empty($XMLDB->editeddirs)) {
+ $base =& $XMLDB->editeddirs[$dirpath];
+ }
+ } else {
+ $this->errormsg = 'Cannot access to ' . $select . ' info';
+ $result = false;
+ }
+ if ($base) {
+ /// Only if the directory exists and it has been loaded
+ if (!$base->path_exists || !$base->xml_loaded) {
+ $this->errormsg = 'Directory ' . $dirpath . ' not loaded';
+ return false;
+ }
+ } else {
+ $this->errormsg = 'Problem handling ' . $select . ' files';
+ return false;
+ }
+
+ /// Get the structure
+ if ($result) {
+ if (!$structure =& $base->xml_file->getStructure()) {
+ $this->errormsg = 'Error retrieving ' . $select . ' structure';
+ $result = false;
+ }
+ }
+ /// Get the tables
+ if ($result) {
+ if (!$tables =& $structure->getTables()) {
+ $this->errormsg = 'Error retrieving ' . $select . ' tables';
+ $result = false;
+ }
+ }
+ /// Get the table
+ if ($result && !$t =& $structure->getTable($table)) {
+ $this->errormsg = 'Error retrieving ' . $table . ' table';
+ $result = false;
+ }
+ /// Get the keys
+ if ($result) {
+ if (!$keys =& $t->getKeys()) {
+ $this->errormsg = 'Error retrieving ' . $select . ' keys';
+ $result = false;
+ }
+ }
+ /// Get the key
+ if ($result && !$k = $t->getKey($key)) {
+ $this->errormsg = 'Error retrieving ' . $key . ' key';
+ $result = false;
+ }
+
+ if ($result) {
+ /// Everything is ok. Generate the XML output
+ $this->output = $k->xmlOutput();
+ } else {
+ /// Switch to HTML and error
+ $this->does_generate = ACTION_GENERATE_HTML;
+ }
+
+ /// Return ok if arrived here
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/view_reserved_words/view_reserved_words.class.php b/admin/xmldb/actions/view_reserved_words/view_reserved_words.class.php
new file mode 100644
index 00000000000..d7e4356d01c
--- /dev/null
+++ b/admin/xmldb/actions/view_reserved_words/view_reserved_words.class.php
@@ -0,0 +1,153 @@
+loadStrings(array(
+ 'listreservedwords' => 'xmldb',
+ 'wrongreservedwords' => 'xmldb',
+ 'table' => 'xmldb',
+ 'field' => 'xmldb',
+ 'back' => 'xmldb'
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_GENERATE_HTML;
+
+ /// These are always here
+ global $CFG, $XMLDB, $db;
+
+ /// Calculate list of available SQL generators
+ $plugins = get_list_of_plugins('lib/xmldb/classes/generators');
+ $reserved_words = array();
+ $reserved_words_bydb = array();
+ foreach($plugins as $plugin) {
+ $classname = 'XMLDB' . $plugin;
+ $generator = new $classname();
+ $reserved_words = array_merge($reserved_words, $generator->getReservedWords());
+ $reserved_words_bydb[$plugin] = $generator->getReservedWords();
+ }
+ sort($reserved_words);
+ $reserved_words = array_unique($reserved_words);
+
+ /// Now, calculate, looking into current DB (with AdoDB Metadata), which fields are
+ /// in the list of reserved words
+ $wronguses = array();
+ $dbtables = $db->MetaTables('TABLES');
+ if ($dbtables) {
+ foreach ($dbtables as $dbtable) {
+ $table = str_replace($CFG->prefix, '', $dbtable);
+ if (in_array($table, $reserved_words)) {
+ $list_of_db = array();
+ foreach ($reserved_words_bydb as $key=>$words) {
+ if (in_array($table, $words)) {
+ $list_of_db[] = $key;
+ }
+ }
+ $wronguses[] = $this->str['table'] . ' - ' . $table . ' (' . implode(', ',$list_of_db) . ')';
+
+ }
+ $dbfields = $db->MetaColumns($dbtable);
+ if ($dbfields) {
+ foreach ($dbfields as $dbfield) {
+ if (in_array($dbfield->name, $reserved_words)) {
+ $list_of_db = array();
+ foreach ($reserved_words_bydb as $key=>$words) {
+ if (in_array($dbfield->name, $words)) {
+ $list_of_db[] = $key;
+ }
+ }
+ $wronguses[] = $this->str['field'] . ' - ' . $table . '->' . $dbfield->name . ' (' . implode(', ',$list_of_db) . ')';
+ }
+ }
+ }
+ }
+ }
+
+ /// Sort the wrong uses
+ sort($wronguses);
+
+ /// The back to edit table button
+ $b = ' ';
+ $b .= '[' . $this->str['back'] . '] ';
+ $b .= '
';
+ $o = $b;
+
+ /// The list of currently wrong field names
+ if ($wronguses) {
+ $o.= ' ';
+ }
+
+ /// The textarea showing all the reserved words
+ $o.= ' ';
+
+ $this->output = $o;
+
+ /// Launch postaction if exists (leave this here!)
+ if ($this->getPostAction() && $result) {
+ return $this->launch($this->getPostAction());
+ }
+
+ /// Return ok if arrived here
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/view_statement_xml/view_statement_xml.class.php b/admin/xmldb/actions/view_statement_xml/view_statement_xml.class.php
new file mode 100644
index 00000000000..6a50faeddff
--- /dev/null
+++ b/admin/xmldb/actions/view_statement_xml/view_statement_xml.class.php
@@ -0,0 +1,126 @@
+loadStrings(array(
+ /// 'key' => 'module',
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_GENERATE_XML;
+
+ /// These are always here
+ global $CFG, $XMLDB;
+
+ /// Do the job, setting result as needed
+
+ /// Get the file parameter
+ $statement = required_param('statement', PARAM_CLEAN);
+ $select = required_param('select', PARAM_ALPHA); //original/edited
+ /// Get the dir containing the file
+ $dirpath = required_param('dir', PARAM_CLEAN);
+ $dirpath = stripslashes_safe($dirpath);
+
+ /// Get the correct dir
+ if ($select == 'original') {
+ if (!empty($XMLDB->dbdirs)) {
+ $base =& $XMLDB->dbdirs[$dirpath];
+ }
+ } else if ($select == 'edited') {
+ if (!empty($XMLDB->editeddirs)) {
+ $base =& $XMLDB->editeddirs[$dirpath];
+ }
+ } else {
+ $this->errormsg = 'Cannot access to ' . $select . ' info';
+ $result = false;
+ }
+ if ($base) {
+ /// Only if the directory exists and it has been loaded
+ if (!$base->path_exists || !$base->xml_loaded) {
+ $this->errormsg = 'Directory ' . $dirpath . ' not loaded';
+ return false;
+ }
+ } else {
+ $this->errormsg = 'Problem handling ' . $select . ' files';
+ return false;
+ }
+
+ /// Get the structure
+ if ($result) {
+ if (!$structure =& $base->xml_file->getStructure()) {
+ $this->errormsg = 'Error retrieving ' . $select . ' structure';
+ $result = false;
+ }
+ }
+ /// Get the statements
+ if ($result) {
+ if (!$statements =& $structure->getStatements()) {
+ $this->errormsg = 'Error retrieving ' . $select . ' statements';
+ $result = false;
+ }
+ }
+ /// Get the statement
+ if ($result && !$t =& $structure->getStatement($statement)) {
+ $this->errormsg = 'Error retrieving ' . $statement . ' statement';
+ $result = false;
+ }
+
+ if ($result) {
+ /// Everything is ok. Generate the XML output
+ $this->output = $t->xmlOutput();
+ } else {
+ /// Switch to HTML and error
+ $this->does_generate = ACTION_GENERATE_HTML;
+ }
+
+ /// Return ok if arrived here
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/view_structure_sql/view_structure_sql.class.php b/admin/xmldb/actions/view_structure_sql/view_structure_sql.class.php
new file mode 100644
index 00000000000..81ad972b1cc
--- /dev/null
+++ b/admin/xmldb/actions/view_structure_sql/view_structure_sql.class.php
@@ -0,0 +1,134 @@
+loadStrings(array(
+ 'selectdb' => 'xmldb',
+ 'back' => 'xmldb'
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_GENERATE_HTML;
+
+ /// These are always here
+ global $CFG, $XMLDB;
+
+ /// Do the job, setting result as needed
+ /// Get the dir containing the file
+ $dirpath = required_param('dir', PARAM_CLEAN);
+ $dirpath = stripslashes_safe($dirpath);
+
+ /// Get the correct dirs
+ if (!empty($XMLDB->dbdirs)) {
+ $dbdir =& $XMLDB->dbdirs[$dirpath];
+ } else {
+ return false;
+ }
+ if (!empty($XMLDB->editeddirs)) {
+ $editeddir =& $XMLDB->editeddirs[$dirpath];
+ $structure =& $editeddir->xml_file->getStructure();
+ }
+ /// ADD YOUR CODE HERE
+
+ /// Get parameters
+ $generatorparam = optional_param('generator', null, PARAM_CLEAN);
+ if (empty($generatorparam)) {
+ $generatorparam = $CFG->dbtype;
+ }
+
+ /// Calculate list of available SQL generators
+ $plugins = get_list_of_plugins('lib/xmldb/classes/generators');
+ $generators = array();
+ foreach($plugins as $plugin) {
+ $generators[$plugin] = $plugin;
+ }
+ /// Check we have the selected generator
+ if (!in_array($generatorparam, $generators)) {
+ $generatorparam = reset($generators);
+ }
+
+ /// The back to edit table button
+ $b = ' ';
+ $b .= '[' . $this->str['back'] . '] ';
+ $b .= '
';
+ $o = $b;
+
+ $o.= ' ';
+
+ $this->output = $o;
+
+ /// Launch postaction if exists (leave this here!)
+ if ($this->getPostAction() && $result) {
+ return $this->launch($this->getPostAction());
+ }
+
+ /// Return ok if arrived here
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/view_structure_xml/view_structure_xml.class.php b/admin/xmldb/actions/view_structure_xml/view_structure_xml.class.php
new file mode 100644
index 00000000000..d35e059b05c
--- /dev/null
+++ b/admin/xmldb/actions/view_structure_xml/view_structure_xml.class.php
@@ -0,0 +1,113 @@
+loadStrings(array(
+ /// 'key' => 'module',
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_GENERATE_XML;
+
+ /// These are always here
+ global $CFG, $XMLDB;
+
+ /// Do the job, setting result as needed
+
+ /// Get the file parameter
+ $select = required_param('select', PARAM_ALPHAEXT); //original/edited
+ /// Get the dir containing the file
+ $dirpath = required_param('dir', PARAM_CLEAN);
+ $dirpath = stripslashes_safe($dirpath);
+
+ /// Get the correct dir
+ if ($select == 'original') {
+ if (!empty($XMLDB->dbdirs)) {
+ $base =& $XMLDB->dbdirs[$dirpath];
+ }
+ } else if ($select == 'edited') {
+ if (!empty($XMLDB->editeddirs)) {
+ $base =& $XMLDB->editeddirs[$dirpath];
+ }
+ } else {
+ $this->errormsg = 'Cannot access to ' . $select . ' info';
+ $result = false;
+ }
+ if ($base) {
+ /// Only if the directory exists and it has been loaded
+ if (!$base->path_exists || !$base->xml_loaded) {
+ $this->errormsg = 'Directory ' . $dirpath . ' not loaded';
+ return false;
+ }
+ } else {
+ $this->errormsg = 'Problem handling ' . $select . ' files';
+ return false;
+ }
+
+ /// Get the structure
+ if ($result) {
+ if (!$structure =& $base->xml_file->getStructure()) {
+ $this->errormsg = 'Error retrieving ' . $select . ' structure';
+ $result = false;
+ }
+ }
+
+ if ($result) {
+ /// Everything is ok. Generate the XML output
+ $this->output = $structure->xmlOutput();
+ } else {
+ /// Switch to HTML and error
+ $this->does_generate = ACTION_GENERATE_HTML;
+ }
+
+ /// Return ok if arrived here
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/view_table_sql/view_table_sql.class.php b/admin/xmldb/actions/view_table_sql/view_table_sql.class.php
new file mode 100644
index 00000000000..f6c8896f6d1
--- /dev/null
+++ b/admin/xmldb/actions/view_table_sql/view_table_sql.class.php
@@ -0,0 +1,139 @@
+loadStrings(array(
+ 'selectdb' => 'xmldb',
+ 'back' => 'xmldb'
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_GENERATE_HTML;
+
+ /// These are always here
+ global $CFG, $XMLDB;
+
+ /// Do the job, setting result as needed
+ /// Get the dir containing the file
+ $dirpath = required_param('dir', PARAM_CLEAN);
+ $dirpath = stripslashes_safe($dirpath);
+
+ /// Get the correct dirs
+ if (!empty($XMLDB->dbdirs)) {
+ $dbdir =& $XMLDB->dbdirs[$dirpath];
+ } else {
+ return false;
+ }
+ if (!empty($XMLDB->editeddirs)) {
+ $editeddir =& $XMLDB->editeddirs[$dirpath];
+ $structure =& $editeddir->xml_file->getStructure();
+ }
+ /// ADD YOUR CODE HERE
+
+ /// Get parameters
+ $tableparam = required_param('table', PARAM_CLEAN);
+ if (!$table =& $structure->getTable($tableparam)) {
+ $this->errormsg = 'Wrong table specified: ' . $tableparm;
+ return false;
+ }
+ $generatorparam = optional_param('generator', null, PARAM_CLEAN);
+ if (empty($generatorparam)) {
+ $generatorparam = $CFG->dbtype;
+ }
+
+ /// Calculate list of available SQL generators
+ $plugins = get_list_of_plugins('lib/xmldb/classes/generators');
+ $generators = array();
+ foreach($plugins as $plugin) {
+ $generators[$plugin] = $plugin;
+ }
+ /// Check we have the selected generator
+ if (!in_array($generatorparam, $generators)) {
+ $generatorparam = reset($generators);
+ }
+
+ /// The back to edit table button
+ $b = ' ';
+ $b .= '[' . $this->str['back'] . '] ';
+ $b .= '
';
+ $o = $b;
+
+ $o.= ' ';
+
+ $this->output = $o;
+
+ /// Launch postaction if exists (leave this here!)
+ if ($this->getPostAction() && $result) {
+ return $this->launch($this->getPostAction());
+ }
+
+ /// Return ok if arrived here
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/view_table_xml/view_table_xml.class.php b/admin/xmldb/actions/view_table_xml/view_table_xml.class.php
new file mode 100644
index 00000000000..2722f304c5a
--- /dev/null
+++ b/admin/xmldb/actions/view_table_xml/view_table_xml.class.php
@@ -0,0 +1,126 @@
+loadStrings(array(
+ /// 'key' => 'module',
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_GENERATE_XML;
+
+ /// These are always here
+ global $CFG, $XMLDB;
+
+ /// Do the job, setting result as needed
+
+ /// Get the file parameter
+ $table = required_param('table', PARAM_CLEAN);
+ $select = required_param('select', PARAM_ALPHA); //original/edited
+ /// Get the dir containing the file
+ $dirpath = required_param('dir', PARAM_CLEAN);
+ $dirpath = stripslashes_safe($dirpath);
+
+ /// Get the correct dir
+ if ($select == 'original') {
+ if (!empty($XMLDB->dbdirs)) {
+ $base =& $XMLDB->dbdirs[$dirpath];
+ }
+ } else if ($select == 'edited') {
+ if (!empty($XMLDB->editeddirs)) {
+ $base =& $XMLDB->editeddirs[$dirpath];
+ }
+ } else {
+ $this->errormsg = 'Cannot access to ' . $select . ' info';
+ $result = false;
+ }
+ if ($base) {
+ /// Only if the directory exists and it has been loaded
+ if (!$base->path_exists || !$base->xml_loaded) {
+ $this->errormsg = 'Directory ' . $dirpath . ' not loaded';
+ return false;
+ }
+ } else {
+ $this->errormsg = 'Problem handling ' . $select . ' files';
+ return false;
+ }
+
+ /// Get the structure
+ if ($result) {
+ if (!$structure =& $base->xml_file->getStructure()) {
+ $this->errormsg = 'Error retrieving ' . $select . ' structure';
+ $result = false;
+ }
+ }
+ /// Get the tables
+ if ($result) {
+ if (!$tables =& $structure->getTables()) {
+ $this->errormsg = 'Error retrieving ' . $select . ' tables';
+ $result = false;
+ }
+ }
+ /// Get the table
+ if ($result && !$t =& $structure->getTable($table)) {
+ $this->errormsg = 'Error retrieving ' . $table . ' table';
+ $result = false;
+ }
+
+ if ($result) {
+ /// Everything is ok. Generate the XML output
+ $this->output = $t->xmlOutput();
+ } else {
+ /// Switch to HTML and error
+ $this->does_generate = ACTION_GENERATE_HTML;
+ }
+
+ /// Return ok if arrived here
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/actions/view_xml/view_xml.class.php b/admin/xmldb/actions/view_xml/view_xml.class.php
new file mode 100644
index 00000000000..ea41484d8b2
--- /dev/null
+++ b/admin/xmldb/actions/view_xml/view_xml.class.php
@@ -0,0 +1,86 @@
+can_subaction = ACTION_NONE;
+ //$this->can_subaction = ACTION_HAVE_SUBACTIONS;
+
+ /// Set own custom attributes
+
+ /// Get needed strings
+ $this->loadStrings(array(
+ /// 'key' => 'module',
+ ));
+ }
+
+ /**
+ * Invoke method, every class will have its own
+ * returns true/false on completion, setting both
+ * errormsg and output as necessary
+ */
+ function invoke() {
+ parent::invoke();
+
+ $result = true;
+
+ /// Set own core attributes
+ $this->does_generate = ACTION_GENERATE_XML;
+
+ /// These are always here
+ global $CFG, $XMLDB;
+
+ /// Do the job, setting result as needed
+
+ /// Get the file parameter
+ $file = required_param('file', PARAM_CLEAN);
+ $file = stripslashes_safe($file);
+ /// File must be under $CFG->wwwroot and
+ /// under one db directory (simple protection)
+ if (substr($file, 0, strlen($CFG->dirroot)) == $CFG->dirroot &&
+ substr(dirname($file), -2, 2) == 'db') {
+ /// Everything is ok. Load the file to memory
+ $this->output = file_get_contents($file);
+ } else {
+ /// Switch to HTML and error
+ $this->does_generate = ACTION_GENERATE_HTML;
+ $this->errormsg = 'File not viewable (' . $file .')';
+ $result = false;
+ }
+
+ /// Return ok if arrived here
+ return $result;
+ }
+}
+?>
diff --git a/admin/xmldb/index.php b/admin/xmldb/index.php
new file mode 100644
index 00000000000..5cbde18cbac
--- /dev/null
+++ b/admin/xmldb/index.php
@@ -0,0 +1,138 @@
+libdir . '/xmlize.php');
+
+/// Add all the available SQL generators
+ $generators = get_list_of_plugins('lib/xmldb/classes/generators');
+ foreach($generators as $generator) {
+ require_once ('../../lib/xmldb/classes/generators/' . $generator . '/' . $generator . '.class.php');
+ }
+
+/// Handle session data
+ global $XMLDB;
+/// The global SESSION object where everything will happen
+ if (!isset($SESSION->xmldb)) {
+ $SESSION->xmldb = new stdClass;
+ }
+ $XMLDB =& $SESSION->xmldb;
+
+/// Some previous checks
+ if (! $site = get_site()) {
+ redirect("$CFG->wwwroot/$CFG->admin/index.php");
+ }
+
+ require_login();
+
+ if (!isadmin()) {
+ error('You must be an administrator to use this page.');
+ }
+
+/// Fetch all the needed strings
+ $stradministration = get_string('administration');
+
+/// Body of the script, based on action, we delegate the work
+ $action = optional_param ('action', 'main_view', PARAM_ALPHAEXT);
+
+/// Get the action path and invoke it
+ $actionsroot = "$CFG->dirroot/$CFG->admin/xmldb/actions";
+ $actionclass = $action . '.class.php';
+ $actionpath = "$actionsroot/$action/$actionclass";
+
+/// Load and invoke the proper action
+ if (file_exists($actionpath) && is_readable($actionpath)) {
+ require_once($actionpath);
+ if ($xmldb_action = new $action) {
+ //Invoke it
+ $result = $xmldb_action->invoke();
+ if ($result) {
+ /// Based on getDoesGenerate()
+ switch ($xmldb_action->getDoesGenerate()) {
+ case ACTION_GENERATE_HTML:
+ /// Define $CFG->javascript to use our custom javascripts.
+ /// Save the original one to add it from ours. Global too! :-(
+ global $standard_javascript;
+ $standard_javascript = $CFG->javascript; // Save original javascript file
+ $CFG->javascript = $CFG->dirroot.'/admin/xmldb/javascript.php'; //Use our custom javascript code
+ /// Go with standard header
+ print_header("$site->shortname: XMLDB",
+ "$site->fullname",
+ "$stradministration -> XMLDB ");
+ print_heading($xmldb_action->getTitle());
+ echo $xmldb_action->getOutput();
+ print_footer();
+ break;
+ case ACTION_GENERATE_XML:
+ header('Content-type: application/xhtml+xml');
+ echo $xmldb_action->getOutput();
+ break;
+ }
+ } else {
+ error($xmldb_action->getError());
+ }
+ } else {
+ error ("Error: cannot instantiate class (actions/$action/$actionclass)");
+ }
+ } else {
+ error ("Error: wrong action specified ($action)");
+ }
+
+ if ($xmldb_action->getDoesGenerate() != ACTION_GENERATE_XML) {
+ if ($CFG->debug > 7) {
+ ///print_object($XMLDB);
+ }
+ }
+
+?>
diff --git a/admin/xmldb/javascript.php b/admin/xmldb/javascript.php
new file mode 100644
index 00000000000..ecafad4d438
--- /dev/null
+++ b/admin/xmldb/javascript.php
@@ -0,0 +1,60 @@
+dirroot . '/admin/xmldb/actions/' . $action . '/' . $action . '.js';
+ $wwwfile = $CFG->wwwroot . '/admin/xmldb/actions/' . $action . '/' . $action . '.js';
+ if (file_exists($file) && is_readable($file)) {
+ echo '' . "\n";
+ } else {
+ /// Try to load the postaction javascript if exists
+ if ($postaction) {
+ $file = $CFG->dirroot . '/admin/xmldb/actions/' . $postaction . '/' . $postaction . '.js';
+ $wwwfile = $CFG->wwwroot . '/admin/xmldb/actions/' . $postaction . '/' . $postaction . '.js';
+ if (file_exists($file) && is_readable($file)) {
+ echo '' . "\n";
+ }
+ }
+ }
+ }
+
+/// Load standard JavaScript
+ include($standard_javascript);
+?>
diff --git a/admin/xmldb/xmldb.dtd b/admin/xmldb/xmldb.dtd
new file mode 100644
index 00000000000..2a5907ebe8d
--- /dev/null
+++ b/admin/xmldb/xmldb.dtd
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/admin/xmldb/xmldb.xsd b/admin/xmldb/xmldb.xsd
new file mode 100644
index 00000000000..ace90535224
--- /dev/null
+++ b/admin/xmldb/xmldb.xsd
@@ -0,0 +1,197 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file