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.= '
'; + $o.= '

' . $this->str['confirmdeletefield'] . '

' . $fieldparam . '

'; + $o.= ' '; + $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.= '
'; + $o.= '

' . $this->str['confirmdeleteindex'] . '

' . $indexparam . '

'; + $o.= ' '; + $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.= '
'; + $o.= '

' . $this->str['confirmdeletekey'] . '

' . $keyparam . '

'; + $o.= ' '; + $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.= '
'; + $o.= '

' . $this->str['confirmdeletesentence'] . '

'; + $o.= ' '; + $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.= '
'; + $o.= '

' . $this->str['confirmdeletestatement'] . '

' . $statementparam . '

'; + $o.= ' '; + $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.= '
'; + $o.= '

' . $this->str['confirmdeletetable'] . '

' . $tableparam . '

'; + $o.= ' '; + $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.= '
'; + $o.= '

' . $this->str['confirmdeletexmlfile'] . '

' . $dirpath . '

'; + $o.= ' '; + $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 = '
'; + $o.= ' '; + $o.= ' '; + $o.= ' '; + $o.= ' '; + $o.= ' '; + $o.= ' '; + /// XMLDB field name + /// If the field has dependencies, we cannot change its name + $disabled = ''; + if ($structure->getFieldUses($table->getName(), $field->getName())) { + $o.= ' '; + $o.= ' '; + } else { + $o.= ' '; + } + /// XMLDB field comment + $o.= ' '; + /// XMLDBField Type + $typeoptions = array (XMLDB_TYPE_INTEGER => $field->getXMLDBTypeName(XMLDB_TYPE_INTEGER), + XMLDB_TYPE_NUMBER => $field->getXMLDBTypeName(XMLDB_TYPE_NUMBER), + XMLDB_TYPE_FLOAT => $field->getXMLDBTypeName(XMLDB_TYPE_FLOAT), + XMLDB_TYPE_DATETIME=> $field->getXMLDBTypeName(XMLDB_TYPE_DATETIME), + XMLDB_TYPE_CHAR => $field->getXMLDBTypeName(XMLDB_TYPE_CHAR), + XMLDB_TYPE_TEXT => $field->getXMLDBTypeName(XMLDB_TYPE_TEXT), + XMLDB_TYPE_BINARY => $field->getXMLDBTypeName(XMLDB_TYPE_BINARY)); + /// If current field isnt float, delete such column type to avoid its creation from the interface + /// Note that float fields are supported completely but it's possible than in a next future + /// we delete them completely from Moodle DB, using, exlusively, number(x,y) types + if ($field->getType() != XMLDB_TYPE_FLOAT) { + unset ($typeoptions[XMLDB_TYPE_FLOAT]); + } + /// Also we hide datetimes. Only edition of them is allowed (and retrofit) but not new creation + if ($field->getType() != XMLDB_TYPE_DATETIME) { + unset ($typeoptions[XMLDB_TYPE_DATETIME]); + } + $o.= ' '; + $o.= ' '; + /// XMLDBField Length + $o.= ' '; + $o.= ' '; + /// XMLDBField Decimals + $o.= ' '; + $o.= ' '; + /// XMLDBField Unsigned + $unsignedoptions = array (0 => 'signed', 1 => 'unsigned'); + $o.= ' '; + $o.= ' '; + /// XMLDBField NotNull + $notnulloptions = array (0 => 'null', 'not null'); + $o.= ' '; + $o.= ' '; + /// XMLDBField Sequence + $sequenceoptions = array (0 => $this->str['no'], 1 => 'auto-numbered'); + $o.= ' '; + $o.= ' '; + /// XMLDBField Enum and enumvalues + $enumoptions = array (0 => $this->str['no'], 1 => $this->str['yes']); + $o.= ' '; + $o.= ' '; + if (is_array($field->getEnumValues())) { + $enumvalues = implode(', ', $field->getEnumValues()); + } else { + $enumvalues = ''; + } + $o.= ' '; + /// XMLDBField Default + $o.= ' '; + $o.= ' '; + /// Change button + $o.= ' '; + $o.= '
Name:' . s($field->getName()) . '
' . choose_from_menu($typeoptions, 'type', $field->getType(), '', '', '', true) . '
' . choose_from_menu($unsignedoptions, 'unsigned', $field->getUnsigned(), '', '', '', true) . '
' . choose_from_menu($notnulloptions, 'notnull', $field->getNotNull(), '', '', '', true) . '
' . choose_from_menu($sequenceoptions, 'sequence', $field->getSequence(), '', '', '', true) . '
' . choose_from_menu($enumoptions, 'enum', $field->getEnum(), '', '', '', true) . '
 
'; + $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.= ' '; + /// XMLDB index name + /// If the index has dependencies, we cannot change its name + $disabled = ''; + if ($structure->getIndexUses($table->getName(), $index->getName())) { + $disabled = ' disabled="disabled " '; + } + $o.= ' '; + /// XMLDB key comment + $o.= ' '; + /// XMLDBIndex Type + $typeoptions = array (0 => 'not unique', + 1 => 'unique'); + $o.= ' '; + $o.= ' '; + /// XMLDBIndex Fields + $o.= ' '; + $o.= ' '; + /// Change button + $o.= ' '; + $o.= '
' . choose_from_menu($typeoptions, 'unique', $index->getUnique(), '', '', '', true) . '
 
'; + $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.= ' '; + /// XMLDB key name + /// If the key has dependencies, we cannot change its name + $disabled = ''; + if ($structure->getKeyUses($table->getName(), $key->getName())) { + $disabled = ' disabled="disabled " '; + } + $o.= ' '; + /// XMLDB key comment + $o.= ' '; + /// XMLDBKey Type + $typeoptions = array (XMLDB_KEY_PRIMARY => $key->getXMLDBKeyName(XMLDB_KEY_PRIMARY), + XMLDB_KEY_UNIQUE => $key->getXMLDBKeyName(XMLDB_KEY_UNIQUE), + XMLDB_KEY_FOREIGN => $key->getXMLDBKeyName(XMLDB_KEY_FOREIGN), + XMLDB_KEY_FOREIGN_UNIQUE => $key->getXMLDBKeyName(XMLDB_KEY_FOREIGN_UNIQUE)); + /// Only show the XMLDB_KEY_FOREIGN_UNIQUE if the Key has that type + /// if ($key->getType() != XMLDB_KEY_FOREIGN_UNIQUE) { + /// unset ($typeoptions[XMLDB_KEY_FOREIGN_UNIQUE); + /// } + $o.= ' '; + $o.= ' '; + /// XMLDBKey Fields + $o.= ' '; + $o.= ' '; + /// XMLDBKey Reftable + $o.= ' '; + $o.= ' '; + /// XMLDBKey Reffields + $o.= ' '; + $o.= ' '; + /// Change button + $o.= ' '; + $o.= '
' . choose_from_menu($typeoptions, 'type', $key->getType(), '', '', '', true) . '
 
'; + $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.= ' '; + /// The fields box + $o.= ' '; + $o.= ' '; + /// The values box + $o.= ' '; + $o.= ' '; + /// The submit button + $o.= ' '; + $o.= '
INSERT INTO ' . s($statement->getTable()) . '
VALUES
'; + $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.= ' '; + $o.= ' '; + $o.= ' '; + $o.= '
Name:' . s($statement->getName()) .'
 
'; + $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 = ''; + /// Print table row + $o .= ''; + $row = ($row + 1) % 2; + } + $o .= '
'; + /// The edit button + $b .= '[' . $this->str['edit'] . ']'; + $b .= ''; + /// The duplicate button + $b .= '[' . $this->str['duplicate'] . ']'; + $b .= ''; + /// The delete button + $b .= '[' . $this->str['delete'] . ']'; + $b .= '
' . $p . $sentence . $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_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.= ' '; + /// If the table is being used, we cannot rename it + if ($structure->getTableUses($table->getName())) { + $o.= ' '; + } else { + $o.= ' '; + } + $o.= ' '; + $o.= ' '; + $o.= '
Name:' . s($table->getName()) .'
 
'; + $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 = ''; + /// Print table row + $o .= ''; + $row = ($row + 1) % 2; + } + $o .= '
'; + /// 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() . '
' . $field->getName() . '' . $b . $r . '
'; + } + /// Add the keys list + $keys =& $table->getKeys(); + if (!empty($keys)) { + $o .= '

' . $this->str['keys'] . '

'; + $o .= ''; + $row = 0; + foreach ($keys as $key) { + /// Calculate buttons + $b = ''; + /// Print table row + $o .= ''; + $row = ($row + 1) % 2; + } + $o .= '
'; + /// 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() . '
' . $key->getName() . '' . $b . $r .'
'; + } + /// Add the indexes list + $indexes =& $table->getIndexes(); + if (!empty($indexes)) { + $o .= '

' . $this->str['indexes'] . '

'; + $o .= ''; + $row = 0; + foreach ($indexes as $index) { + /// Calculate buttons + $b = ''; + /// Print table row + $o .= ''; + $row = ($row + 1) % 2; + } + $o .= '
'; + /// 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() . '
' . $index->getName() . '' . $b . $r .'
'; + } + + $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.= ' '; + $o.= ' '; + $o.= ' '; + $o.= ' '; + $o.= '
Path:' . s($structure->getPath()) . '
Version:' . s($structure->getVersion()) . '
 
'; + $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 = ''; + /// Print table row + $o .= ''; + $row = ($row + 1) % 2; + } + $o .= '
'; + /// 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 .= '
' . $table->getName() . '' . $b . '
'; + } + ///Add the statements list + $statements =& $structure->getStatements(); + if ($statements) { + $o .= '

' . $this->str['statements'] . '

'; + $o .= ''; + $row = 0; + foreach ($statements as $statement) { + /// Calculate buttons + $b = ''; + /// Print statement row + $o .= ''; + $row = ($row + 1) % 2; + } + $o .= '
'; + /// The edit button + $b .= '[' . $this->str['edit'] . ']'; + $b .= ''; + /// The up button + if ($statement->getPrevious()) { + $b .= '[' . $this->str['up'] . ']'; + } else { + $b .= '[' . $this->str['up'] . ']'; + } + $b .= ''; + /// The down button + if ($statement->getNext()) { + $b .= '[' . $this->str['down'] . ']'; + } else { + $b .= '[' . $this->str['down'] . ']'; + } + $b .= ''; + /// The delete button + $b .= '[' . $this->str['delete'] . ']'; + $b .= '
' . $statement->getName() . '' . $b . '
'; + } + ///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 = ' '; + /// 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 .= ''; + } else { + $o .= ''; + } + $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 .= ''; + } else { + $o .= ''; + } + } + } + } + } + $o .= '
'; + /// 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 .= '
' . $elementtext . $b . '
' . $elementtext . $b . '
' . implode (', ', $errors) . '
' . implode (', ', $errors) . '
'; + + /// 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.= ' '; + $o.= ' '; + $o.= ' '; + $o.= '
' . choose_from_menu($typeoptions, 'type', '', 'choose', '', 0, true) . '' .choose_from_menu($selecttables, 'table', '', 'choose', '', 0, true) . '
[' . $this->str['back'] . ']
'; + $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.= ' '; + $o.= ' '; + $o.= ' '; + $o.= '
' . choose_from_menu($selecttables, 'table', '', 'choose', '', 0, true) . '' .choose_from_menu($aftertables, 'after', '', 'choose', '', 0, true) . '
[' . $this->str['back'] . ']
'; + $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.= '
'; + $o.= '

' . $this->str['confirmrevertchanges'] . '

' . $dirpath . '

'; + $o.= ' '; + $o.= '
'; + $o.= '
'; + $o.= '
'; + $o.= '
'; + $o.= '
'; + $o.= '
'; + $o.= '
'; + $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.= ' '; + $o.= ' '; + $o.= ' '; + $o.= '
' . $this->str['wrongreservedwords'] . '
'; + $o.= '
  • ' . implode('
  • ', $wronguses) . '
'; + $o.= '
'; + } + + /// The textarea showing all the reserved words + $o.= ' '; + $o.= ' '; + $o.= '
' . $this->str['listreservedwords']; + $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.= ' '; + $o.= ' '; + $o.= ' '; + $o.= '
' . $this->str['selectdb']; + + /// Show the popup of generators + $url = 'index.php?action=view_structure_sql&dir=' . urlencode($dirpath) . '&generator='; + $o.= popup_form($url, $generators, 'selectgenerator', $generatorparam, '', '', '' , true); + $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.= ' '; + $o.= ' '; + $o.= ' '; + $o.= '
' . $this->str['selectdb']; + + /// Show the popup of generators + $url = 'index.php?action=view_table_sql&table=' . $tableparam . '&dir=' . urlencode($dirpath) . '&generator='; + $o.= popup_form($url, $generators, 'selectgenerator', $generatorparam, '', '', '' , true); + $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