Differences Between: [Versions 311 and 401] [Versions 311 and 402] [Versions 311 and 403]
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/>. 16 17 /** 18 * @package tool_xmldb 19 * @copyright 2003 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} 20 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 21 */ 22 23 /** 24 * This class verifies all the data introduced when editing a key for correctness, 25 * performing changes / displaying errors depending of the results. 26 * 27 * @package tool_xmldb 28 * @copyright 2003 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} 29 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 30 */ 31 class edit_key_save extends XMLDBAction { 32 33 /** 34 * Init method, every subclass will have its own 35 */ 36 function init() { 37 parent::init(); 38 39 // Set own custom attributes 40 41 // Get needed strings 42 $this->loadStrings(array( 43 'keynameempty' => 'tool_xmldb', 44 'incorrectkeyname' => 'tool_xmldb', 45 'duplicatekeyname' => 'tool_xmldb', 46 'nofieldsspecified' => 'tool_xmldb', 47 'duplicatefieldsused' => 'tool_xmldb', 48 'fieldsnotintable' => 'tool_xmldb', 49 'fieldsusedinkey' => 'tool_xmldb', 50 'fieldsusedinindex' => 'tool_xmldb', 51 'noreftablespecified' => 'tool_xmldb', 52 'wrongnumberofreffields' => 'tool_xmldb', 53 'noreffieldsspecified' => 'tool_xmldb', 54 'nomasterprimaryuniquefound' => 'tool_xmldb', 55 'masterprimaryuniqueordernomatch' => 'tool_xmldb', 56 'primarykeyonlyallownotnullfields' => 'tool_xmldb', 57 'back' => 'tool_xmldb', 58 'administration' => '' 59 )); 60 } 61 62 /** 63 * Invoke method, every class will have its own 64 * returns true/false on completion, setting both 65 * errormsg and output as necessary 66 */ 67 function invoke() { 68 parent::invoke(); 69 70 $result = true; 71 72 // Set own core attributes 73 //$this->does_generate = ACTION_NONE; 74 $this->does_generate = ACTION_GENERATE_HTML; 75 76 // These are always here 77 global $CFG, $XMLDB; 78 79 // Do the job, setting result as needed 80 81 if (!data_submitted()) { // Basic prevention 82 print_error('wrongcall', 'error'); 83 } 84 85 // Get parameters 86 $dirpath = required_param('dir', PARAM_PATH); 87 $dirpath = $CFG->dirroot . $dirpath; 88 89 $tableparam = strtolower(required_param('table', PARAM_PATH)); 90 $keyparam = strtolower(required_param('key', PARAM_PATH)); 91 $name = trim(strtolower(optional_param('name', $keyparam, PARAM_PATH))); 92 93 $comment = required_param('comment', PARAM_CLEAN); 94 $comment = trim($comment); 95 96 $type = required_param('type', PARAM_INT); 97 $fields = required_param('fields', PARAM_CLEAN); 98 $fields = str_replace(' ', '', trim(strtolower($fields))); 99 100 if ($type == XMLDB_KEY_FOREIGN || 101 $type == XMLDB_KEY_FOREIGN_UNIQUE) { 102 $reftable = trim(strtolower(required_param('reftable', PARAM_PATH))); 103 $reffields= required_param('reffields', PARAM_CLEAN); 104 $reffields = str_replace(' ', '', trim(strtolower($reffields))); 105 } 106 107 $editeddir = $XMLDB->editeddirs[$dirpath]; 108 $structure = $editeddir->xml_file->getStructure(); 109 $table = $structure->getTable($tableparam); 110 $key = $table->getKey($keyparam); 111 $oldhash = $key->getHash(); 112 113 $errors = array(); // To store all the errors found 114 115 // Perform some checks 116 // Check empty name 117 if (empty($name)) { 118 $errors[] = $this->str['keynameempty']; 119 } 120 // Check incorrect name 121 if ($name == 'changeme') { 122 $errors[] = $this->str['incorrectkeyname']; 123 } 124 // Check duplicate name 125 if ($keyparam != $name && $table->getKey($name)) { 126 $errors[] = $this->str['duplicatekeyname']; 127 } 128 $fieldsarr = explode(',', $fields); 129 // Check the fields isn't empty 130 if (empty($fieldsarr[0])) { 131 $errors[] = $this->str['nofieldsspecified']; 132 } else { 133 // Check that there aren't duplicate column names 134 $uniquearr = array_unique($fieldsarr); 135 if (count($fieldsarr) != count($uniquearr)) { 136 $errors[] = $this->str['duplicatefieldsused']; 137 } 138 // Check that all the fields in belong to the table 139 foreach ($fieldsarr as $field) { 140 if (!$table->getField($field)) { 141 $errors[] = $this->str['fieldsnotintable']; 142 break; 143 } 144 } 145 // If primary, check that all the fields are not null 146 if ($type == XMLDB_KEY_PRIMARY) { 147 foreach ($fieldsarr as $field) { 148 if ($fi = $table->getField($field)) { 149 if (!$fi->getNotNull()) { 150 $errors[] = $this->str['primarykeyonlyallownotnullfields']; 151 break; 152 } 153 } 154 } 155 } 156 // Check that there isn't any key using exactly the same fields 157 $tablekeys = $table->getKeys(); 158 if ($tablekeys) { 159 foreach ($tablekeys as $tablekey) { 160 // Skip checking against itself 161 if ($keyparam == $tablekey->getName()) { 162 continue; 163 } 164 $keyfieldsarr = $tablekey->getFields(); 165 // Compare both arrays, looking for diferences 166 $diferences = array_merge(array_diff($fieldsarr, $keyfieldsarr), array_diff($keyfieldsarr, $fieldsarr)); 167 if (empty($diferences)) { 168 $errors[] = $this->str['fieldsusedinkey']; 169 break; 170 } 171 } 172 } 173 // Check that there isn't any index using exactlt the same fields 174 $tableindexes = $table->getIndexes(); 175 if ($tableindexes) { 176 foreach ($tableindexes as $tableindex) { 177 $indexfieldsarr = $tableindex->getFields(); 178 // Compare both arrays, looking for diferences 179 $diferences = array_merge(array_diff($fieldsarr, $indexfieldsarr), array_diff($indexfieldsarr, $fieldsarr)); 180 if (empty($diferences)) { 181 $errors[] = $this->str['fieldsusedinindex']; 182 break; 183 } 184 } 185 } 186 // If foreign key 187 if ($type == XMLDB_KEY_FOREIGN || 188 $type == XMLDB_KEY_FOREIGN_UNIQUE) { 189 $reffieldsarr = explode(',', $reffields); 190 // Check reftable is not empty 191 if (empty($reftable)) { 192 $errors[] = $this->str['noreftablespecified']; 193 } else 194 // Check reffields are not empty 195 if (empty($reffieldsarr[0])) { 196 $errors[] = $this->str['noreffieldsspecified']; 197 } else 198 // Check the number of fields is correct 199 if (count($fieldsarr) != count($reffieldsarr)) { 200 $errors[] = $this->str['wrongnumberofreffields']; 201 } else { 202 // Check, if pointing to one structure table, that there is one master key for this key 203 if ($rt = $structure->getTable($reftable)) { 204 $masterfound = false; 205 $reftablekeys = $rt->getKeys(); 206 if ($reftablekeys) { 207 foreach ($reftablekeys as $reftablekey) { 208 // Only compare with primary and unique keys 209 if ($reftablekey->getType() != XMLDB_KEY_PRIMARY && $reftablekey->getType() != XMLDB_KEY_UNIQUE) { 210 continue; 211 } 212 $keyfieldsarr = $reftablekey->getFields(); 213 // Compare both arrays, looking for diferences 214 $diferences = array_merge(array_diff($reffieldsarr, $keyfieldsarr), array_diff($keyfieldsarr, $reffieldsarr)); 215 if (empty($diferences)) { 216 $masterfound = true; 217 break; 218 } 219 } 220 if (!$masterfound) { 221 $errors[] = $this->str['nomasterprimaryuniquefound']; 222 } else { 223 // Quick test of the order 224 if (implode(',', $reffieldsarr) != implode(',', $keyfieldsarr)) { 225 $errors[] = $this->str['masterprimaryuniqueordernomatch']; 226 } 227 } 228 } 229 } 230 } 231 } 232 } 233 234 235 if (!empty($errors)) { 236 $tempkey = new xmldb_key($name); 237 $tempkey->setType($type); 238 $tempkey->setFields($fieldsarr); 239 if ($type == XMLDB_KEY_FOREIGN || 240 $type == XMLDB_KEY_FOREIGN_UNIQUE) { 241 $tempkey->setRefTable($reftable); 242 $tempkey->setRefFields($reffieldsarr); 243 } 244 // Prepare the output 245 $o = '<p>' .implode(', ', $errors) . '</p> 246 <p>' . $name . ': ' . $tempkey->readableInfo() . '</p>'; 247 $o.= '<a href="index.php?action=edit_key&key=' .$key->getName() . '&table=' . $table->getName() . 248 '&dir=' . urlencode(str_replace($CFG->dirroot, '', $dirpath)) . '">[' . $this->str['back'] . ']</a>'; 249 $this->output = $o; 250 } 251 252 // Continue if we aren't under errors 253 if (empty($errors)) { 254 // If there is one name change, do it, changing the prev and next 255 // attributes of the adjacent fields 256 if ($keyparam != $name) { 257 $key->setName($name); 258 if ($key->getPrevious()) { 259 $prev = $table->getKey($key->getPrevious()); 260 $prev->setNext($name); 261 $prev->setChanged(true); 262 } 263 if ($key->getNext()) { 264 $next = $table->getKey($key->getNext()); 265 $next->setPrevious($name); 266 $next->setChanged(true); 267 } 268 } 269 270 // Set comment 271 $key->setComment($comment); 272 273 // Set the rest of fields 274 $key->setType($type); 275 $key->setFields($fieldsarr); 276 if ($type == XMLDB_KEY_FOREIGN || 277 $type == XMLDB_KEY_FOREIGN_UNIQUE) { 278 $key->setRefTable($reftable); 279 $key->setRefFields($reffieldsarr); 280 } 281 282 // If the hash has changed from the old one, change the version 283 // and mark the structure as changed 284 $key->calculateHash(true); 285 if ($oldhash != $key->getHash()) { 286 $key->setChanged(true); 287 $table->setChanged(true); 288 // Recalculate the structure hash 289 $structure->calculateHash(true); 290 $structure->setVersion(userdate(time(), '%Y%m%d', 99, false)); 291 // Mark as changed 292 $structure->setChanged(true); 293 } 294 295 // Launch postaction if exists (leave this here!) 296 if ($this->getPostAction() && $result) { 297 return $this->launch($this->getPostAction()); 298 } 299 } 300 301 // Return ok if arrived here 302 return $result; 303 } 304 } 305
title
Description
Body
title
Description
Body
title
Description
Body
title
Body