diff --git a/admin/tool/xmldb/actions/main_view/main_view.class.php b/admin/tool/xmldb/actions/main_view/main_view.class.php index 7a37f8eb1ad..8071a71530b 100644 --- a/admin/tool/xmldb/actions/main_view/main_view.class.php +++ b/admin/tool/xmldb/actions/main_view/main_view.class.php @@ -57,6 +57,7 @@ class main_view extends XMLDBAction { 'checkforeignkeys' => 'tool_xmldb', 'checkbigints' => 'tool_xmldb', 'checkoraclesemantics' => 'tool_xmldb', + 'reconcilefiles' => 'tool_xmldb', 'doc' => 'tool_xmldb', 'filemodifiedoutfromeditor' => 'tool_xmldb', 'viewxml' => 'tool_xmldb', @@ -97,6 +98,8 @@ class main_view extends XMLDBAction { $b .= ' [' . $this->str['reservedwords'] . ']'; // The docs button $b .= ' [' . $this->str['doc'] . ']'; + // The reconcile XMLDB files button. + $b .= ' [' . $this->str['reconcilefiles'] . ']'; // The check indexes button $b .= ' [' . $this->str['checkindexes'] . ']'; // The check defaults button diff --git a/admin/tool/xmldb/actions/reconcile_files/reconcile_files.class.php b/admin/tool/xmldb/actions/reconcile_files/reconcile_files.class.php new file mode 100644 index 00000000000..7536ad2b6ce --- /dev/null +++ b/admin/tool/xmldb/actions/reconcile_files/reconcile_files.class.php @@ -0,0 +1,124 @@ +. + +/** + * List all the files needing reconcile because the definitions don't match the XML contents. + * + * @package tool_xmldb + * @copyright 2022 onwards Eloy Lafuente (stronk7) {@link https://stronk7.com} + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class reconcile_files extends XMLDBAction { + + /** + * Init method, every subclass will have its own + */ + public function init() { + parent::init(); + + // Set own custom attributes. + $this->sesskey_protected = false; // This action doesn't need sesskey protection. + + // Get needed strings. + $this->loadStrings([ + 'backtomainview' => 'tool_xmldb', + 'reconcile_files_intro' => 'tool_xmldb', + 'reconcile_files_no' => 'tool_xmldb', + 'reconcile_files_yes' => 'tool_xmldb', + 'searchresults' => 'tool_xmldb', + ]); + } + + /** + * Invoke method, every class will have its own + * returns true/false on completion, setting both + * errormsg and output as necessary + */ + public 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. + + // Add link back to home. + $b = '
'; + $b .= ' [' . $this->str['backtomainview'] . ']'; + $b .= '
'; + $this->output .= $b; + + $c = ''; + $c .= $this->str['reconcile_files_intro']; + $c .= '
'; + $this->output .= $c; + + // Get the list of DB directories. + $result = $this->launch('get_db_directories'); + if ($result && !empty($XMLDB->dbdirs)) { + $needfix = []; + foreach ($XMLDB->dbdirs as $key => $dbdir) { + // Verify it exists. + if (!file_exists($key . '/install.xml') && !is_readable($key . '/install.xml')) { + continue; + } + + // Read the raw contents of the file. + $rawcontents = file_get_contents($key . '/install.xml'); + + // Load the XMLDB file and its structure. + $xmldb = new xmldb_file($key . '/install.xml'); + $xmldb->loadXMLStructure(); + + // Generate the XML contents from the loaded structure. + $xmlcontents = $xmldb->getStructure()->xmlOutput(); + + if ($rawcontents != $xmlcontents) { + $relpath = str_replace($CFG->dirroot . '/', '', $key) . '/install.xml'; + $needfix[] = $relpath; + // Left here on purpose, as a quick way to fix problems. To be + // enabled and run by developers only, uncomment the next line: + // file_put_contents($key . '/install.xml', $xmlcontents); + // (this script won't ever do that officially). + } + } + } + + $r = '