Merge commit 'catalyst/MOODLE_19_STABLE' into mdl19-linuxchix
[moodle-linuxchix.git] / admin / xmldb / actions / edit_key_save / edit_key_save.class.php
blob3ca892a568d760292af82caddf0cd37803e1ada1
1 <?php // $Id$
3 ///////////////////////////////////////////////////////////////////////////
4 // //
5 // NOTICE OF COPYRIGHT //
6 // //
7 // Moodle - Modular Object-Oriented Dynamic Learning Environment //
8 // http://moodle.com //
9 // //
10 // Copyright (C) 1999 onwards Martin Dougiamas http://dougiamas.com //
11 // (C) 2001-3001 Eloy Lafuente (stronk7) http://contiento.com //
12 // //
13 // This program is free software; you can redistribute it and/or modify //
14 // it under the terms of the GNU General Public License as published by //
15 // the Free Software Foundation; either version 2 of the License, or //
16 // (at your option) any later version. //
17 // //
18 // This program is distributed in the hope that it will be useful, //
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of //
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
21 // GNU General Public License for more details: //
22 // //
23 // http://www.gnu.org/copyleft/gpl.html //
24 // //
25 ///////////////////////////////////////////////////////////////////////////
27 /// This class will save the changes performed to one key
29 class edit_key_save extends XMLDBAction {
31 /**
32 * Init method, every subclass will have its own
34 function init() {
35 parent::init();
37 /// Set own custom attributes
39 /// Get needed strings
40 $this->loadStrings(array(
41 'keynameempty' => 'xmldb',
42 'incorrectkeyname' => 'xmldb',
43 'duplicatekeyname' => 'xmldb',
44 'nofieldsspecified' => 'xmldb',
45 'duplicatefieldsused' => 'xmldb',
46 'fieldsnotintable' => 'xmldb',
47 'fieldsusedinkey' => 'xmldb',
48 'fieldsusedinindex' => 'xmldb',
49 'noreftablespecified' => 'xmldb',
50 'wrongnumberofreffields' => 'xmldb',
51 'noreffieldsspecified' => 'xmldb',
52 'nomasterprimaryuniquefound' => 'xmldb',
53 'masterprimaryuniqueordernomatch' => 'xmldb',
54 'primarykeyonlyallownotnullfields' => 'xmldb',
55 'administration' => ''
56 ));
59 /**
60 * Invoke method, every class will have its own
61 * returns true/false on completion, setting both
62 * errormsg and output as necessary
64 function invoke() {
65 parent::invoke();
67 $result = true;
69 /// Set own core attributes
70 $this->does_generate = ACTION_NONE;
71 //$this->does_generate = ACTION_GENERATE_HTML;
73 /// These are always here
74 global $CFG, $XMLDB;
76 /// Do the job, setting result as needed
78 if (!data_submitted('nomatch')) { ///Basic prevention
79 error('Wrong action call');
82 /// Get parameters
83 $dirpath = required_param('dir', PARAM_PATH);
84 $dirpath = $CFG->dirroot . stripslashes_safe($dirpath);
86 $tableparam = strtolower(required_param('table', PARAM_PATH));
87 $keyparam = strtolower(required_param('key', PARAM_PATH));
88 $name = trim(strtolower(optional_param('name', $keyparam, PARAM_PATH)));
90 $comment = required_param('comment', PARAM_CLEAN);
91 $comment = trim(stripslashes_safe($comment));
93 $type = required_param('type', PARAM_INT);
94 $fields = required_param('fields', PARAM_CLEAN);
95 $fields = str_replace(' ', '', trim(strtolower(stripslashes_safe($fields))));
97 if ($type == XMLDB_KEY_FOREIGN ||
98 $type == XMLDB_KEY_FOREIGN_UNIQUE) {
99 $reftable = trim(strtolower(required_param('reftable', PARAM_PATH)));
100 $reffields= required_param('reffields', PARAM_CLEAN);
101 $reffields = str_replace(' ', '', trim(strtolower(stripslashes_safe($reffields))));
104 $editeddir =& $XMLDB->editeddirs[$dirpath];
105 $structure =& $editeddir->xml_file->getStructure();
106 $table =& $structure->getTable($tableparam);
107 $key =& $table->getKey($keyparam);
108 $oldhash = $key->getHash();
110 $errors = array(); /// To store all the errors found
112 /// Perform some checks
113 /// Check empty name
114 if (empty($name)) {
115 $errors[] = $this->str['keynameempty'];
117 /// Check incorrect name
118 if ($name == 'changeme') {
119 $errors[] = $this->str['incorrectkeyname'];
121 /// Check duplicate name
122 if ($keyparam != $name && $table->getKey($name)) {
123 $errors[] = $this->str['duplicatekeyname'];
125 $fieldsarr = explode(',', $fields);
126 /// Check the fields isn't empty
127 if (empty($fieldsarr[0])) {
128 $errors[] = $this->str['nofieldsspecified'];
129 } else {
130 /// Check that there aren't duplicate column names
131 $uniquearr = array_unique($fieldsarr);
132 if (count($fieldsarr) != count($uniquearr)) {
133 $errors[] = $this->str['duplicatefieldsused'];
135 /// Check that all the fields in belong to the table
136 foreach ($fieldsarr as $field) {
137 if (!$table->getField($field)) {
138 $errors[] = $this->str['fieldsnotintable'];
139 break;
142 /// If primary, check that all the fields are not null
143 if ($type == XMLDB_KEY_PRIMARY) {
144 foreach ($fieldsarr as $field) {
145 if ($fi = $table->getField($field)) {
146 if (!$fi->getNotNull()) {
147 $errors[] = $this->str['primarykeyonlyallownotnullfields'];
148 break;
153 /// Check that there isn't any key using exactly the same fields
154 $tablekeys = $table->getKeys();
155 if ($tablekeys) {
156 foreach ($tablekeys as $tablekey) {
157 /// Skip checking against itself
158 if ($keyparam == $tablekey->getName()) {
159 continue;
161 $keyfieldsarr = $tablekey->getFields();
162 /// Compare both arrays, looking for diferences
163 $diferences = array_merge(array_diff($fieldsarr, $keyfieldsarr), array_diff($keyfieldsarr, $fieldsarr));
164 if (empty($diferences)) {
165 $errors[] = $this->str['fieldsusedinkey'];
166 break;
170 /// Check that there isn't any index using exactlt the same fields
171 $tableindexes = $table->getIndexes();
172 if ($tableindexes) {
173 foreach ($tableindexes as $tableindex) {
174 $indexfieldsarr = $tableindex->getFields();
175 /// Compare both arrays, looking for diferences
176 $diferences = array_merge(array_diff($fieldsarr, $indexfieldsarr), array_diff($indexfieldsarr, $fieldsarr));
177 if (empty($diferences)) {
178 $errors[] = $this->str['fieldsusedinindex'];
179 break;
183 /// If foreign key
184 if ($type == XMLDB_KEY_FOREIGN ||
185 $type == XMLDB_KEY_FOREIGN_UNIQUE) {
186 $reffieldsarr = explode(',', $reffields);
187 /// Check reftable is not empty
188 if (empty($reftable)) {
189 $errors[] = $this->str['noreftablespecified'];
190 } else
191 /// Check reffields are not empty
192 if (empty($reffieldsarr[0])) {
193 $errors[] = $this->str['noreffieldsspecified'];
194 } else
195 /// Check the number of fields is correct
196 if (count($fieldsarr) != count($reffieldsarr)) {
197 $errors[] = $this->str['wrongnumberofreffields'];
198 } else {
199 /// Check, if pointing to one structure table, that there is one master key for this key
200 if ($rt = $structure->getTable($reftable)) {
201 $masterfound = false;
202 $reftablekeys = $rt->getKeys();
203 if ($reftablekeys) {
204 foreach ($reftablekeys as $reftablekey) {
205 /// Only compare with primary and unique keys
206 if ($reftablekey->getType() != XMLDB_KEY_PRIMARY && $reftablekey->getType() != XMLDB_KEY_UNIQUE) {
207 continue;
209 $keyfieldsarr = $reftablekey->getFields();
210 /// Compare both arrays, looking for diferences
211 $diferences = array_merge(array_diff($reffieldsarr, $keyfieldsarr), array_diff($keyfieldsarr, $reffieldsarr));
212 if (empty($diferences)) {
213 $masterfound = true;
214 break;
217 if (!$masterfound) {
218 $errors[] = $this->str['nomasterprimaryuniquefound'];
219 } else {
220 /// Quick test of the order
221 if (implode(',', $reffieldsarr) != implode(',', $keyfieldsarr)) {
222 $errors[] = $this->str['masterprimaryuniqueordernomatch'];
232 if (!empty($errors)) {
233 $tempkey = new XMLDBKey($name);
234 $tempkey->setType($type);
235 $tempkey->setFields($fieldsarr);
236 if ($type == XMLDB_KEY_FOREIGN ||
237 $type == XMLDB_KEY_FOREIGN_UNIQUE) {
238 $tempkey->setRefTable($reftable);
239 $tempkey->setRefFields($reffieldsarr);
241 /// Prepare the output
242 $site = get_site();
243 $navlinks = array();
244 $navlinks[] = array('name' => $this->str['administration'], 'link' => '../index.php', 'type' => 'misc');
245 $navlinks[] = array('name' => 'XMLDB', 'link' => 'index.php', 'type' => 'misc');
246 $navigation = build_navigation($navlinks);
247 print_header("$site->shortname: XMLDB", "$site->fullname", $navigation);
249 notice ('<p>' .implode(', ', $errors) . '</p>
250 <p>' . $tempkey->readableInfo(),
251 'index.php?action=edit_key&amp;key=' .$key->getName() . '&amp;table=' . $table->getName() . '&amp;dir=' . urlencode(str_replace($CFG->dirroot, '', $dirpath)));
252 die; /// re-die :-P
255 /// Continue if we aren't under errors
256 if (empty($errors)) {
257 /// If there is one name change, do it, changing the prev and next
258 /// atributes of the adjacent fields
259 if ($keyparam != $name) {
260 $key->setName($name);
261 if ($key->getPrevious()) {
262 $prev =& $table->getKey($key->getPrevious());
263 $prev->setNext($name);
264 $prev->setChanged(true);
266 if ($key->getNext()) {
267 $next =& $table->getKey($key->getNext());
268 $next->setPrevious($name);
269 $next->setChanged(true);
273 /// Set comment
274 $key->setComment($comment);
276 /// Set the rest of fields
277 $key->setType($type);
278 $key->setFields($fieldsarr);
279 if ($type == XMLDB_KEY_FOREIGN ||
280 $type == XMLDB_KEY_FOREIGN_UNIQUE) {
281 $key->setRefTable($reftable);
282 $key->setRefFields($reffieldsarr);
285 /// If the hash has changed from the old one, change the version
286 /// and mark the structure as changed
287 $key->calculateHash(true);
288 if ($oldhash != $key->getHash()) {
289 $key->setChanged(true);
290 $table->setChanged(true);
291 /// Recalculate the structure hash
292 $structure->calculateHash(true);
293 $structure->setVersion(userdate(time(), '%Y%m%d', 99, false));
294 /// Mark as changed
295 $structure->setChanged(true);
298 /// Launch postaction if exists (leave this here!)
299 if ($this->getPostAction() && $result) {
300 return $this->launch($this->getPostAction());
304 /// Return ok if arrived here
305 return $result;