|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00002 // This file is part of Moodle - http://moodle.org/ 00003 // 00004 // Moodle is free software: you can redistribute it and/or modify 00005 // it under the terms of the GNU General Public License as published by 00006 // the Free Software Foundation, either version 3 of the License, or 00007 // (at your option) any later version. 00008 // 00009 // Moodle is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 // GNU General Public License for more details. 00013 // 00014 // You should have received a copy of the GNU General Public License 00015 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 00016 00038 class check_foreign_keys extends XMLDBCheckAction { 00039 00043 function init() { 00044 $this->introstr = 'confirmcheckforeignkeys'; 00045 parent::init(); 00046 00047 // Set own core attributes 00048 00049 // Set own custom attributes 00050 00051 // Get needed strings 00052 $this->loadStrings(array( 00053 'key' => 'tool_xmldb', 00054 'violatedforeignkeys' => 'tool_xmldb', 00055 'noviolatedforeignkeysfound' => 'tool_xmldb', 00056 'violatedforeignkeysfound' => 'tool_xmldb', 00057 'violations' => 'tool_xmldb', 00058 )); 00059 } 00060 00061 protected function check_table(xmldb_table $xmldb_table, array $metacolumns) { 00062 global $DB; 00063 $dbman = $DB->get_manager(); 00064 00065 $strictchecks = optional_param('strict', false, PARAM_BOOL); 00066 00067 $o = ''; 00068 $violatedkeys = array(); 00069 00070 // Keys 00071 if ($xmldb_keys = $xmldb_table->getKeys()) { 00072 $o.=' <ul>'; 00073 foreach ($xmldb_keys as $xmldb_key) { 00074 // We are only interested in foreign keys. 00075 if (!in_array($xmldb_key->getType(), array(XMLDB_KEY_FOREIGN, XMLDB_KEY_FOREIGN_UNIQUE))) { 00076 continue; 00077 } 00078 $o.=' <li>' . $this->str['key'] . ': ' . $xmldb_key->readableInfo() . ' '; 00079 00080 // Work out the SQL to find key violations. 00081 $keyfields = $xmldb_key->getFields(); 00082 $reffields = $xmldb_key->getRefFields(); 00083 $joinconditions = array(); 00084 $nullnessconditions = array(); 00085 $params = array(); 00086 foreach ($keyfields as $i => $field) { 00087 $joinconditions[] = 't1.' . $field . ' = t2.' . $reffields[$i]; 00088 $xmldb_field = $xmldb_table->getField($field); 00089 $default = $xmldb_field->getDefault(); 00090 if (!$xmldb_field->getNotNull()) { 00091 $nullnessconditions[] = 't1.' . $field . ' IS NOT NULL'; 00092 } else if (!$strictchecks && ($default == '0' || !$default)) { 00093 // We have a default of 0 or '' or something like that. 00094 // These generate a lot of false-positives, so ignore them 00095 // for now. 00096 $nullnessconditions[] = 't1.' . $field . ' <> ?'; 00097 $params[] = $xmldb_field->getDefault(); 00098 } 00099 } 00100 $nullnessconditions[] = 't2.id IS NULL'; 00101 $sql = 'SELECT count(1) FROM {' . $xmldb_table->getName() . 00102 '} t1 LEFT JOIN {' . $xmldb_key->getRefTable() . '} t2 ON ' . 00103 implode(' AND ', $joinconditions) . ' WHERE ' . 00104 implode(' AND ', $nullnessconditions); 00105 00106 // Check there are any problems in the database. 00107 $violations = $DB->count_records_sql($sql, $params); 00108 if ($violations == 0) { 00109 $o.='<font color="green">' . $this->str['ok'] . '</font>'; 00110 } else { 00111 $o.='<font color="red">' . $this->str['violations'] . '</font>'; 00112 // Add the missing index to the list 00113 $violation = new stdClass; 00114 $violation->table = $xmldb_table; 00115 $violation->key = $xmldb_key; 00116 $violation->numviolations = $violations; 00117 $violation->numrows = $DB->count_records($xmldb_table->getName()); 00118 $violation->sql = str_replace('count(1)', '*', $sql); 00119 if (!empty($params)) { 00120 $violation->sqlparams = '(' . implode(', ', $params) . ')'; 00121 } else { 00122 $violation->sqlparams = ''; 00123 } 00124 $violatedkeys[] = $violation; 00125 } 00126 $o.='</li>'; 00127 } 00128 $o.=' </ul>'; 00129 } 00130 00131 return array($o, $violatedkeys); 00132 } 00133 00134 protected function display_results(array $violatedkeys) { 00135 $r = '<table class="generalbox boxaligncenter boxwidthwide" border="0" cellpadding="5" cellspacing="0" id="results">'; 00136 $r.= ' <tr><td class="generalboxcontent">'; 00137 $r.= ' <h2 class="main">' . $this->str['searchresults'] . '</h2>'; 00138 $r.= ' <p class="centerpara">' . $this->str['violatedforeignkeys'] . ': ' . count($violatedkeys) . '</p>'; 00139 $r.= ' </td></tr>'; 00140 $r.= ' <tr><td class="generalboxcontent">'; 00141 00142 // If we have found wrong integers inform about them 00143 if (count($violatedkeys)) { 00144 $r.= ' <p class="centerpara">' . $this->str['violatedforeignkeysfound'] . '</p>'; 00145 $r.= ' <ul>'; 00146 foreach ($violatedkeys as $violation) { 00147 $violation->tablename = $violation->table->getName(); 00148 $violation->keyname = $violation->key->getName(); 00149 00150 $r.= ' <li>' .get_string('fkviolationdetails', 'tool_xmldb', $violation) . 00151 '<pre>' . s($violation->sql) . '; ' . s($violation->sqlparams) . '</pre></li>'; 00152 } 00153 $r.= ' </ul>'; 00154 } else { 00155 $r.= ' <p class="centerpara">' . $this->str['noviolatedforeignkeysfound'] . '</p>'; 00156 } 00157 $r.= ' </td></tr>'; 00158 $r.= ' <tr><td class="generalboxcontent">'; 00159 // Add the complete log message 00160 $r.= ' <p class="centerpara">' . $this->str['completelogbelow'] . '</p>'; 00161 $r.= ' </td></tr>'; 00162 $r.= '</table>'; 00163 00164 return $r; 00165 } 00166 }