|
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 00033 class edit_key_save extends XMLDBAction { 00034 00038 function init() { 00039 parent::init(); 00040 00041 // Set own custom attributes 00042 00043 // Get needed strings 00044 $this->loadStrings(array( 00045 'keynameempty' => 'tool_xmldb', 00046 'incorrectkeyname' => 'tool_xmldb', 00047 'duplicatekeyname' => 'tool_xmldb', 00048 'nofieldsspecified' => 'tool_xmldb', 00049 'duplicatefieldsused' => 'tool_xmldb', 00050 'fieldsnotintable' => 'tool_xmldb', 00051 'fieldsusedinkey' => 'tool_xmldb', 00052 'fieldsusedinindex' => 'tool_xmldb', 00053 'noreftablespecified' => 'tool_xmldb', 00054 'wrongnumberofreffields' => 'tool_xmldb', 00055 'noreffieldsspecified' => 'tool_xmldb', 00056 'nomasterprimaryuniquefound' => 'tool_xmldb', 00057 'masterprimaryuniqueordernomatch' => 'tool_xmldb', 00058 'primarykeyonlyallownotnullfields' => 'tool_xmldb', 00059 'back' => 'tool_xmldb', 00060 'administration' => '' 00061 )); 00062 } 00063 00069 function invoke() { 00070 parent::invoke(); 00071 00072 $result = true; 00073 00074 // Set own core attributes 00075 //$this->does_generate = ACTION_NONE; 00076 $this->does_generate = ACTION_GENERATE_HTML; 00077 00078 // These are always here 00079 global $CFG, $XMLDB; 00080 00081 // Do the job, setting result as needed 00082 00083 if (!data_submitted()) { // Basic prevention 00084 print_error('wrongcall', 'error'); 00085 } 00086 00087 // Get parameters 00088 $dirpath = required_param('dir', PARAM_PATH); 00089 $dirpath = $CFG->dirroot . $dirpath; 00090 00091 $tableparam = strtolower(required_param('table', PARAM_PATH)); 00092 $keyparam = strtolower(required_param('key', PARAM_PATH)); 00093 $name = trim(strtolower(optional_param('name', $keyparam, PARAM_PATH))); 00094 00095 $comment = required_param('comment', PARAM_CLEAN); 00096 $comment = trim($comment); 00097 00098 $type = required_param('type', PARAM_INT); 00099 $fields = required_param('fields', PARAM_CLEAN); 00100 $fields = str_replace(' ', '', trim(strtolower($fields))); 00101 00102 if ($type == XMLDB_KEY_FOREIGN || 00103 $type == XMLDB_KEY_FOREIGN_UNIQUE) { 00104 $reftable = trim(strtolower(required_param('reftable', PARAM_PATH))); 00105 $reffields= required_param('reffields', PARAM_CLEAN); 00106 $reffields = str_replace(' ', '', trim(strtolower($reffields))); 00107 } 00108 00109 $editeddir =& $XMLDB->editeddirs[$dirpath]; 00110 $structure =& $editeddir->xml_file->getStructure(); 00111 $table =& $structure->getTable($tableparam); 00112 $key =& $table->getKey($keyparam); 00113 $oldhash = $key->getHash(); 00114 00115 $errors = array(); // To store all the errors found 00116 00117 // Perform some checks 00118 // Check empty name 00119 if (empty($name)) { 00120 $errors[] = $this->str['keynameempty']; 00121 } 00122 // Check incorrect name 00123 if ($name == 'changeme') { 00124 $errors[] = $this->str['incorrectkeyname']; 00125 } 00126 // Check duplicate name 00127 if ($keyparam != $name && $table->getKey($name)) { 00128 $errors[] = $this->str['duplicatekeyname']; 00129 } 00130 $fieldsarr = explode(',', $fields); 00131 // Check the fields isn't empty 00132 if (empty($fieldsarr[0])) { 00133 $errors[] = $this->str['nofieldsspecified']; 00134 } else { 00135 // Check that there aren't duplicate column names 00136 $uniquearr = array_unique($fieldsarr); 00137 if (count($fieldsarr) != count($uniquearr)) { 00138 $errors[] = $this->str['duplicatefieldsused']; 00139 } 00140 // Check that all the fields in belong to the table 00141 foreach ($fieldsarr as $field) { 00142 if (!$table->getField($field)) { 00143 $errors[] = $this->str['fieldsnotintable']; 00144 break; 00145 } 00146 } 00147 // If primary, check that all the fields are not null 00148 if ($type == XMLDB_KEY_PRIMARY) { 00149 foreach ($fieldsarr as $field) { 00150 if ($fi = $table->getField($field)) { 00151 if (!$fi->getNotNull()) { 00152 $errors[] = $this->str['primarykeyonlyallownotnullfields']; 00153 break; 00154 } 00155 } 00156 } 00157 } 00158 // Check that there isn't any key using exactly the same fields 00159 $tablekeys = $table->getKeys(); 00160 if ($tablekeys) { 00161 foreach ($tablekeys as $tablekey) { 00162 // Skip checking against itself 00163 if ($keyparam == $tablekey->getName()) { 00164 continue; 00165 } 00166 $keyfieldsarr = $tablekey->getFields(); 00167 // Compare both arrays, looking for diferences 00168 $diferences = array_merge(array_diff($fieldsarr, $keyfieldsarr), array_diff($keyfieldsarr, $fieldsarr)); 00169 if (empty($diferences)) { 00170 $errors[] = $this->str['fieldsusedinkey']; 00171 break; 00172 } 00173 } 00174 } 00175 // Check that there isn't any index using exactlt the same fields 00176 $tableindexes = $table->getIndexes(); 00177 if ($tableindexes) { 00178 foreach ($tableindexes as $tableindex) { 00179 $indexfieldsarr = $tableindex->getFields(); 00180 // Compare both arrays, looking for diferences 00181 $diferences = array_merge(array_diff($fieldsarr, $indexfieldsarr), array_diff($indexfieldsarr, $fieldsarr)); 00182 if (empty($diferences)) { 00183 $errors[] = $this->str['fieldsusedinindex']; 00184 break; 00185 } 00186 } 00187 } 00188 // If foreign key 00189 if ($type == XMLDB_KEY_FOREIGN || 00190 $type == XMLDB_KEY_FOREIGN_UNIQUE) { 00191 $reffieldsarr = explode(',', $reffields); 00192 // Check reftable is not empty 00193 if (empty($reftable)) { 00194 $errors[] = $this->str['noreftablespecified']; 00195 } else 00196 // Check reffields are not empty 00197 if (empty($reffieldsarr[0])) { 00198 $errors[] = $this->str['noreffieldsspecified']; 00199 } else 00200 // Check the number of fields is correct 00201 if (count($fieldsarr) != count($reffieldsarr)) { 00202 $errors[] = $this->str['wrongnumberofreffields']; 00203 } else { 00204 // Check, if pointing to one structure table, that there is one master key for this key 00205 if ($rt = $structure->getTable($reftable)) { 00206 $masterfound = false; 00207 $reftablekeys = $rt->getKeys(); 00208 if ($reftablekeys) { 00209 foreach ($reftablekeys as $reftablekey) { 00210 // Only compare with primary and unique keys 00211 if ($reftablekey->getType() != XMLDB_KEY_PRIMARY && $reftablekey->getType() != XMLDB_KEY_UNIQUE) { 00212 continue; 00213 } 00214 $keyfieldsarr = $reftablekey->getFields(); 00215 // Compare both arrays, looking for diferences 00216 $diferences = array_merge(array_diff($reffieldsarr, $keyfieldsarr), array_diff($keyfieldsarr, $reffieldsarr)); 00217 if (empty($diferences)) { 00218 $masterfound = true; 00219 break; 00220 } 00221 } 00222 if (!$masterfound) { 00223 $errors[] = $this->str['nomasterprimaryuniquefound']; 00224 } else { 00225 // Quick test of the order 00226 if (implode(',', $reffieldsarr) != implode(',', $keyfieldsarr)) { 00227 $errors[] = $this->str['masterprimaryuniqueordernomatch']; 00228 } 00229 } 00230 } 00231 } 00232 } 00233 } 00234 } 00235 00236 00237 if (!empty($errors)) { 00238 $tempkey = new xmldb_key($name); 00239 $tempkey->setType($type); 00240 $tempkey->setFields($fieldsarr); 00241 if ($type == XMLDB_KEY_FOREIGN || 00242 $type == XMLDB_KEY_FOREIGN_UNIQUE) { 00243 $tempkey->setRefTable($reftable); 00244 $tempkey->setRefFields($reffieldsarr); 00245 } 00246 // Prepare the output 00247 $o = '<p>' .implode(', ', $errors) . '</p> 00248 <p>' . $name . ': ' . $tempkey->readableInfo() . '</p>'; 00249 $o.= '<a href="index.php?action=edit_key&key=' .$key->getName() . '&table=' . $table->getName() . 00250 '&dir=' . urlencode(str_replace($CFG->dirroot, '', $dirpath)) . '">[' . $this->str['back'] . ']</a>'; 00251 $this->output = $o; 00252 } 00253 00254 // Continue if we aren't under errors 00255 if (empty($errors)) { 00256 // If there is one name change, do it, changing the prev and next 00257 // atributes of the adjacent fields 00258 if ($keyparam != $name) { 00259 $key->setName($name); 00260 if ($key->getPrevious()) { 00261 $prev =& $table->getKey($key->getPrevious()); 00262 $prev->setNext($name); 00263 $prev->setChanged(true); 00264 } 00265 if ($key->getNext()) { 00266 $next =& $table->getKey($key->getNext()); 00267 $next->setPrevious($name); 00268 $next->setChanged(true); 00269 } 00270 } 00271 00272 // Set comment 00273 $key->setComment($comment); 00274 00275 // Set the rest of fields 00276 $key->setType($type); 00277 $key->setFields($fieldsarr); 00278 if ($type == XMLDB_KEY_FOREIGN || 00279 $type == XMLDB_KEY_FOREIGN_UNIQUE) { 00280 $key->setRefTable($reftable); 00281 $key->setRefFields($reffieldsarr); 00282 } 00283 00284 // If the hash has changed from the old one, change the version 00285 // and mark the structure as changed 00286 $key->calculateHash(true); 00287 if ($oldhash != $key->getHash()) { 00288 $key->setChanged(true); 00289 $table->setChanged(true); 00290 // Recalculate the structure hash 00291 $structure->calculateHash(true); 00292 $structure->setVersion(userdate(time(), '%Y%m%d', 99, false)); 00293 // Mark as changed 00294 $structure->setChanged(true); 00295 } 00296 00297 // Launch postaction if exists (leave this here!) 00298 if ($this->getPostAction() && $result) { 00299 return $this->launch($this->getPostAction()); 00300 } 00301 } 00302 00303 // Return ok if arrived here 00304 return $result; 00305 } 00306 } 00307