5ffc70e3f7f5fc4db56edee33bb3473fcae6ab22
[moodle.git] / admin / tool / xmldb / actions / XMLDBCheckAction.class.php
1 <?php
2 // This file is part of Moodle - http://moodle.org/
3 //
4 // Moodle is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // Moodle is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
17 /**
18  * @package    tool_xmldb
19  * @copyright  2008 onwards Tim Hunt
20  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
21  */
23 /**
24  * This is a base class for the various actions that interate over all the
25  * tables and check some aspect of their definition.
26  *
27  * @package    tool_xmldb
28  * @copyright  2008 onwards Tim Hunt
29  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
30  */
31 abstract class XMLDBCheckAction extends XMLDBAction {
32     /**
33      * @var string This string is displayed with a yes/no choice before the report is run.
34      * You must set this to the name of a lang string in xmldb.php before calling init.
35      */
36     protected $introstr = '';
38     /**
39      * Init method, every subclass will have its own
40      */
41     function init() {
42         parent::init();
44         // Set own core attributes
46         // Set own custom attributes
48         // Get needed strings
49         $this->loadStrings(array(
50             $this->introstr => 'tool_xmldb',
51             'ok' => '',
52             'wrong' => 'tool_xmldb',
53             'table' => 'tool_xmldb',
54             'field' => 'tool_xmldb',
55             'searchresults' => 'tool_xmldb',
56             'completelogbelow' => 'tool_xmldb',
57             'yes' => '',
58             'no' => '',
59             'error' => '',
60             'back' => 'tool_xmldb'
61         ));
62     }
64     /**
65      * Invoke method, every class will have its own
66      * returns true/false on completion, setting both
67      * errormsg and output as necessary
68      */
69     function invoke() {
70         parent::invoke();
72         $result = true;
74         // Set own core attributes
75         $this->does_generate = ACTION_GENERATE_HTML;
77         // These are always here
78         global $CFG, $XMLDB, $DB, $OUTPUT;
80         // And we nedd some ddl suff
81         $dbman = $DB->get_manager();
83         // Here we'll acummulate all the wrong fields found
84         $problemsfound = array();
86         // Do the job, setting $result as needed
88         // Get the confirmed to decide what to do
89         $confirmed = optional_param('confirmed', false, PARAM_BOOL);
91         // If  not confirmed, show confirmation box
92         if (!$confirmed) {
93             $o = '<table class="generaltable" border="0" cellpadding="5" cellspacing="0" id="notice">';
94             $o.= '  <tr><td class="generalboxcontent">';
95             $o.= '    <p class="centerpara">' . $this->str[$this->introstr] . '</p>';
96             $o.= '    <table class="boxaligncenter" cellpadding="20"><tr><td>';
97             $o.= '      <div class="singlebutton">';
98             $o.= '        <form action="index.php?action=' . $this->title . '&amp;confirmed=yes&amp;sesskey=' . sesskey() . '" method="post"><fieldset class="invisiblefieldset">';
99             $o.= '          <input type="submit" value="'. $this->str['yes'] .'" /></fieldset></form></div>';
100             $o.= '      </td><td>';
101             $o.= '      <div class="singlebutton">';
102             $o.= '        <form action="index.php?action=main_view" method="post"><fieldset class="invisiblefieldset">';
103             $o.= '          <input type="submit" value="'. $this->str['no'] .'" /></fieldset></form></div>';
104             $o.= '      </td></tr>';
105             $o.= '    </table>';
106             $o.= '  </td></tr>';
107             $o.= '</table>';
109             $this->output = $o;
110         } else {
111             // The back to edit table button
112             $b = ' <p class="centerpara buttons">';
113             $b .= '<a href="index.php">[' . $this->str['back'] . ']</a>';
114             $b .= '</p>';
116             // Iterate over $XMLDB->dbdirs, loading their XML data to memory
117             if ($XMLDB->dbdirs) {
118                 $dbdirs = $XMLDB->dbdirs;
119                 $o='<ul>';
120                 foreach ($dbdirs as $dbdir) {
121                     // Only if the directory exists
122                     if (!$dbdir->path_exists) {
123                         continue;
124                     }
125                     // Load the XML file
126                     $xmldb_file = new xmldb_file($dbdir->path . '/install.xml');
128                     // Only if the file exists
129                     if (!$xmldb_file->fileExists()) {
130                         continue;
131                     }
132                     // Load the XML contents to structure
133                     $loaded = $xmldb_file->loadXMLStructure();
134                     if (!$loaded || !$xmldb_file->isLoaded()) {
135                         echo $OUTPUT->notification('Errors found in XMLDB file: '. $dbdir->path . '/install.xml');
136                         continue;
137                     }
138                     // Arriving here, everything is ok, get the XMLDB structure
139                     $structure = $xmldb_file->getStructure();
141                     $o.='    <li>' . str_replace($CFG->dirroot . '/', '', $dbdir->path . '/install.xml');
142                     // Getting tables
143                     if ($xmldb_tables = $structure->getTables()) {
144                         $o.='        <ul>';
145                         // Foreach table, process its fields
146                         foreach ($xmldb_tables as $xmldb_table) {
147                             // Skip table if not exists
148                             if (!$dbman->table_exists($xmldb_table)) {
149                                 continue;
150                             }
151                             // Fetch metadata from physical DB. All the columns info.
152                             if (!$metacolumns = $DB->get_columns($xmldb_table->getName(), false)) {
153                                 // / Skip table if no metacolumns is available for it
154                                 continue;
155                             }
156                             // Table processing starts here
157                             $o.='            <li>' . $xmldb_table->getName();
158                             // Do the specific check.
159                             list($output, $newproblems) = $this->check_table($xmldb_table, $metacolumns);
160                             $o.=$output;
161                             $problemsfound = array_merge($problemsfound, $newproblems);
162                             $o.='    </li>';
163                             // Give the script some more time (resetting to current if exists)
164                             if ($currenttl = @ini_get('max_execution_time')) {
165                                 @ini_set('max_execution_time',$currenttl);
166                             }
167                         }
168                         $o.='        </ul>';
169                     }
170                     $o.='    </li>';
171                 }
172                 $o.='</ul>';
173             }
175             // Create a report of the problems found.
176             $r = $this->display_results($problemsfound);
178             // Combine the various bits of output.
179             $this->output = $b . $r . $o;
180         }
182         // Launch postaction if exists (leave this here!)
183         if ($this->getPostAction() && $result) {
184             return $this->launch($this->getPostAction());
185         }
187         // Return ok if arrived here
188         return $result;
189     }
191     /**
192      * Do the checks necessary on one particular table.
193      *
194      * @param xmldb_table $xmldb_table the table definition from the install.xml file.
195      * @param array $metacolumns the column information read from the database.
196      * @return array an array with two elements: First, some additional progress output,
197      *      for example a list (<ul>) of the things check each with an one work ok/not ok summary.
198      *      Second, an array giving the details of any problems found. These arrays
199      *      for all tables will be aggregated, and then passed to
200      */
201     abstract protected function check_table(xmldb_table $xmldb_table, array $metacolumns);
203     /**
204      * Display a list of the problems found.
205      *
206      * @param array $problems_found an aggregation of all the problems found by
207      *      all the check_table calls.
208      * @return string a display of all the problems found as HTML.
209      */
210     abstract protected function display_results(array $problems_found);