|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00002 00004 // // 00005 // NOTICE OF COPYRIGHT // 00006 // // 00007 // Moodle - Modular Object-Oriented Dynamic Learning Environment // 00008 // http://moodle.com // 00009 // // 00010 // Copyright (C) 1999 onwards Martin Dougiamas http://dougiamas.com // 00011 // (C) 2001-3001 Eloy Lafuente (stronk7) http://contiento.com // 00012 // // 00013 // This program is free software; you can redistribute it and/or modify // 00014 // it under the terms of the GNU General Public License as published by // 00015 // the Free Software Foundation; either version 2 of the License, or // 00016 // (at your option) any later version. // 00017 // // 00018 // This program is distributed in the hope that it will be useful, // 00019 // but WITHOUT ANY WARRANTY; without even the implied warranty of // 00020 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // 00021 // GNU General Public License for more details: // 00022 // // 00023 // http://www.gnu.org/copyleft/gpl.html // 00024 // // 00026 00028 00029 class xmldb_table extends xmldb_object { 00030 00031 var $fields; 00032 var $keys; 00033 var $indexes; 00034 00038 function __construct($name) { 00039 parent::__construct($name); 00040 $this->fields = array(); 00041 $this->keys = array(); 00042 $this->indexes = array(); 00043 } 00044 00049 function addField(&$field, $after=NULL) { 00050 00052 if ($this->getField($field->getName())) { 00053 throw new coding_exception('Duplicate field '.$field->getName().' specified in table '.$this->getName()); 00054 } 00055 00057 $prevfield = NULL; 00058 $nextfield = NULL; 00059 00060 if (!$after) { 00061 $allfields =& $this->getFields(); 00062 if (!empty($allfields)) { 00063 end($allfields); 00064 $prevfield =& $allfields[key($allfields)]; 00065 } 00066 } else { 00067 $prevfield =& $this->getField($after); 00068 } 00069 if ($prevfield && $prevfield->getNext()) { 00070 $nextfield =& $this->getField($prevfield->getNext()); 00071 } 00072 00074 if ($prevfield) { 00075 $field->setPrevious($prevfield->getName()); 00076 $prevfield->setNext($field->getName()); 00077 } 00078 if ($nextfield) { 00079 $field->setNext($nextfield->getName()); 00080 $nextfield->setPrevious($field->getName()); 00081 } 00083 $field->setLoaded(true); 00084 $field->setChanged(true); 00086 $this->fields[] = $field; 00088 $this->orderFields($this->fields); 00090 $this->calculateHash(true); 00092 $this->setChanged(true); 00093 00094 return $field; 00095 } 00096 00101 function addKey(&$key, $after=NULL) { 00102 00104 if ($this->getKey($key->getName())) { 00105 throw new coding_exception('Duplicate key '.$key->getName().' specified in table '.$this->getName()); 00106 } 00107 00109 $prevkey = NULL; 00110 $nextkey = NULL; 00111 00112 if (!$after) { 00113 $allkeys =& $this->getKeys(); 00114 if (!empty($allkeys)) { 00115 end($allkeys); 00116 $prevkey =& $allkeys[key($allkeys)]; 00117 } 00118 } else { 00119 $prevkey =& $this->getKey($after); 00120 } 00121 if ($prevkey && $prevkey->getNext()) { 00122 $nextkey =& $this->getKey($prevkey->getNext()); 00123 } 00124 00126 if ($prevkey) { 00127 $key->setPrevious($prevkey->getName()); 00128 $prevkey->setNext($key->getName()); 00129 } 00130 if ($nextkey) { 00131 $key->setNext($nextkey->getName()); 00132 $nextkey->setPrevious($key->getName()); 00133 } 00135 $key->setLoaded(true); 00136 $key->setChanged(true); 00138 $this->keys[] = $key; 00140 $this->orderKeys($this->keys); 00142 $this->calculateHash(true); 00144 $this->setChanged(true); 00145 } 00146 00151 function addIndex(&$index, $after=NULL) { 00152 00154 if ($this->getIndex($index->getName())) { 00155 throw new coding_exception('Duplicate index '.$index->getName().' specified in table '.$this->getName()); 00156 } 00157 00159 $previndex = NULL; 00160 $nextindex = NULL; 00161 00162 if (!$after) { 00163 $allindexes =& $this->getIndexes(); 00164 if (!empty($allindexes)) { 00165 end($allindexes); 00166 $previndex =& $allindexes[key($allindexes)]; 00167 } 00168 } else { 00169 $previndex =& $this->getIndex($after); 00170 } 00171 if ($previndex && $previndex->getNext()) { 00172 $nextindex =& $this->getIndex($previndex->getNext()); 00173 } 00174 00176 if ($previndex) { 00177 $index->setPrevious($previndex->getName()); 00178 $previndex->setNext($index->getName()); 00179 } 00180 if ($nextindex) { 00181 $index->setNext($nextindex->getName()); 00182 $nextindex->setPrevious($index->getName()); 00183 } 00184 00186 $index->setLoaded(true); 00187 $index->setChanged(true); 00189 $this->indexes[] = $index; 00191 $this->orderIndexes($this->indexes); 00193 $this->calculateHash(true); 00195 $this->setChanged(true); 00196 } 00197 00201 function &getFields() { 00202 return $this->fields; 00203 } 00204 00208 function &getKeys() { 00209 return $this->keys; 00210 } 00211 00215 function &getIndexes() { 00216 return $this->indexes; 00217 } 00218 00222 function &getField($fieldname) { 00223 $i = $this->findFieldInArray($fieldname); 00224 if ($i !== NULL) { 00225 return $this->fields[$i]; 00226 } 00227 $null = NULL; 00228 return $null; 00229 } 00230 00234 function &findFieldInArray($fieldname) { 00235 foreach ($this->fields as $i => $field) { 00236 if ($fieldname == $field->getName()) { 00237 return $i; 00238 } 00239 } 00240 $null = NULL; 00241 return $null; 00242 } 00243 00247 function orderFields() { 00248 $result = $this->orderElements($this->fields); 00249 if ($result) { 00250 $this->setFields($result); 00251 return true; 00252 } else { 00253 return false; 00254 } 00255 } 00256 00260 function &getKey($keyname) { 00261 $i = $this->findKeyInArray($keyname); 00262 if ($i !== NULL) { 00263 return $this->keys[$i]; 00264 } 00265 $null = NULL; 00266 return $null; 00267 } 00268 00272 function &findKeyInArray($keyname) { 00273 foreach ($this->keys as $i => $key) { 00274 if ($keyname == $key->getName()) { 00275 return $i; 00276 } 00277 } 00278 $null = NULL; 00279 return $null; 00280 } 00281 00285 function orderKeys() { 00286 $result = $this->orderElements($this->keys); 00287 if ($result) { 00288 $this->setKeys($result); 00289 return true; 00290 } else { 00291 return false; 00292 } 00293 } 00294 00298 function &getIndex($indexname) { 00299 $i = $this->findIndexInArray($indexname); 00300 if ($i !== NULL) { 00301 return $this->indexes[$i]; 00302 } 00303 $null = NULL; 00304 return $null; 00305 } 00306 00310 function &findIndexInArray($indexname) { 00311 foreach ($this->indexes as $i => $index) { 00312 if ($indexname == $index->getName()) { 00313 return $i; 00314 } 00315 } 00316 $null = NULL; 00317 return $null; 00318 } 00319 00323 function orderIndexes() { 00324 $result = $this->orderElements($this->indexes); 00325 if ($result) { 00326 $this->setIndexes($result); 00327 return true; 00328 } else { 00329 return false; 00330 } 00331 } 00332 00336 function setFields($fields) { 00337 $this->fields = $fields; 00338 } 00339 00343 function setKeys($keys) { 00344 $this->keys = $keys; 00345 } 00346 00350 function setIndexes($indexes) { 00351 $this->indexes = $indexes; 00352 } 00353 00357 function deleteField($fieldname) { 00358 00359 $field =& $this->getField($fieldname); 00360 if ($field) { 00361 $i = $this->findFieldInArray($fieldname); 00363 $prevfield =& $this->getField($field->getPrevious()); 00364 $nextfield =& $this->getField($field->getNext()); 00366 if ($prevfield) { 00367 $prevfield->setNext($field->getNext()); 00368 } 00369 if ($nextfield) { 00370 $nextfield->setPrevious($field->getPrevious()); 00371 } 00373 unset($this->fields[$i]); 00375 $this->orderFields($this->fields); 00377 $this->calculateHash(true); 00379 $this->setChanged(true); 00380 } 00381 } 00382 00386 function deleteKey($keyname) { 00387 00388 $key =& $this->getKey($keyname); 00389 if ($key) { 00390 $i = $this->findKeyInArray($keyname); 00392 $prevkey =& $this->getKey($key->getPrevious()); 00393 $nextkey =& $this->getKey($key->getNext()); 00395 if ($prevkey) { 00396 $prevkey->setNext($key->getNext()); 00397 } 00398 if ($nextkey) { 00399 $nextkey->setPrevious($key->getPrevious()); 00400 } 00402 unset($this->keys[$i]); 00404 $this->orderKeys($this->keys); 00406 $this->calculateHash(true); 00408 $this->setChanged(true); 00409 } 00410 } 00411 00415 function deleteIndex($indexname) { 00416 00417 $index =& $this->getIndex($indexname); 00418 if ($index) { 00419 $i = $this->findIndexInArray($indexname); 00421 $previndex =& $this->getIndex($index->getPrevious()); 00422 $nextindex =& $this->getIndex($index->getNext()); 00424 if ($previndex) { 00425 $previndex->setNext($index->getNext()); 00426 } 00427 if ($nextindex) { 00428 $nextindex->setPrevious($index->getPrevious()); 00429 } 00431 unset($this->indexes[$i]); 00433 $this->orderIndexes($this->indexes); 00435 $this->calculateHash(true); 00437 $this->setChanged(true); 00438 } 00439 } 00440 00444 function arr2xmldb_table($xmlarr) { 00445 00446 global $CFG; 00447 00448 $result = true; 00449 00454 00456 if (isset($xmlarr['@']['NAME'])) { 00457 $this->name = trim($xmlarr['@']['NAME']); 00458 } else { 00459 $this->errormsg = 'Missing NAME attribute'; 00460 $this->debug($this->errormsg); 00461 $result = false; 00462 } 00463 if (isset($xmlarr['@']['COMMENT'])) { 00464 $this->comment = trim($xmlarr['@']['COMMENT']); 00465 } else if (!empty($CFG->xmldbdisablecommentchecking)) { 00466 $this->comment = ''; 00467 } else { 00468 $this->errormsg = 'Missing COMMENT attribute'; 00469 $this->debug($this->errormsg); 00470 $result = false; 00471 } 00472 if (isset($xmlarr['@']['PREVIOUS'])) { 00473 $this->previous = trim($xmlarr['@']['PREVIOUS']); 00474 } 00475 if (isset($xmlarr['@']['NEXT'])) { 00476 $this->next = trim($xmlarr['@']['NEXT']); 00477 } 00478 00480 if (isset($xmlarr['#']['FIELDS']['0']['#']['FIELD'])) { 00481 foreach ($xmlarr['#']['FIELDS']['0']['#']['FIELD'] as $xmlfield) { 00482 if (!$result) { //Skip on error 00483 continue; 00484 } 00485 $name = trim($xmlfield['@']['NAME']); 00486 $field = new xmldb_field($name); 00487 $field->arr2xmldb_field($xmlfield); 00488 $this->fields[] = $field; 00489 if (!$field->isLoaded()) { 00490 $this->errormsg = 'Problem loading field ' . $name; 00491 $this->debug($this->errormsg); 00492 $result = false; 00493 } 00494 } 00495 } else { 00496 $this->errormsg = 'Missing FIELDS section'; 00497 $this->debug($this->errormsg); 00498 $result = false; 00499 } 00500 00502 if ($result && $this->fields) { 00504 if (!$this->checkNameValues($this->fields)) { 00505 $this->errormsg = 'Some FIELDS name values are incorrect'; 00506 $this->debug($this->errormsg); 00507 $result = false; 00508 } 00510 $this->fixPrevNext($this->fields); 00511 if ($result && !$this->checkPreviousNextValues($this->fields)) { 00512 $this->errormsg = 'Some FIELDS previous/next values are incorrect'; 00513 $this->debug($this->errormsg); 00514 $result = false; 00515 } 00517 if ($result && !$this->orderFields($this->fields)) { 00518 $this->errormsg = 'Error ordering the fields'; 00519 $this->debug($this->errormsg); 00520 $result = false; 00521 } 00522 } 00523 00525 if (isset($xmlarr['#']['KEYS']['0']['#']['KEY'])) { 00526 foreach ($xmlarr['#']['KEYS']['0']['#']['KEY'] as $xmlkey) { 00527 if (!$result) { //Skip on error 00528 continue; 00529 } 00530 $name = trim($xmlkey['@']['NAME']); 00531 $key = new xmldb_key($name); 00532 $key->arr2xmldb_key($xmlkey); 00533 $this->keys[] = $key; 00534 if (!$key->isLoaded()) { 00535 $this->errormsg = 'Problem loading key ' . $name; 00536 $this->debug($this->errormsg); 00537 $result = false; 00538 } 00539 } 00540 } else { 00541 $this->errormsg = 'Missing KEYS section (at least one PK must exist)'; 00542 $this->debug($this->errormsg); 00543 $result = false; 00544 } 00545 00547 if ($result && $this->keys) { 00549 if (!$this->checkNameValues($this->keys)) { 00550 $this->errormsg = 'Some KEYS name values are incorrect'; 00551 $this->debug($this->errormsg); 00552 $result = false; 00553 } 00555 $this->fixPrevNext($this->keys); 00556 if ($result && !$this->checkPreviousNextValues($this->keys)) { 00557 $this->errormsg = 'Some KEYS previous/next values are incorrect'; 00558 $this->debug($this->errormsg); 00559 $result = false; 00560 } 00562 if ($result && !$this->orderKeys($this->keys)) { 00563 $this->errormsg = 'Error ordering the keys'; 00564 $this->debug($this->errormsg); 00565 $result = false; 00566 } 00570 } 00571 00573 if (isset($xmlarr['#']['INDEXES']['0']['#']['INDEX'])) { 00574 foreach ($xmlarr['#']['INDEXES']['0']['#']['INDEX'] as $xmlindex) { 00575 if (!$result) { //Skip on error 00576 continue; 00577 } 00578 $name = trim($xmlindex['@']['NAME']); 00579 $index = new xmldb_index($name); 00580 $index->arr2xmldb_index($xmlindex); 00581 $this->indexes[] = $index; 00582 if (!$index->isLoaded()) { 00583 $this->errormsg = 'Problem loading index ' . $name; 00584 $this->debug($this->errormsg); 00585 $result = false; 00586 } 00587 } 00588 } 00589 00591 if ($result && $this->indexes) { 00593 if (!$this->checkNameValues($this->indexes)) { 00594 $this->errormsg = 'Some INDEXES name values are incorrect'; 00595 $this->debug($this->errormsg); 00596 $result = false; 00597 } 00599 $this->fixPrevNext($this->indexes); 00600 if ($result && !$this->checkPreviousNextValues($this->indexes)) { 00601 $this->errormsg = 'Some INDEXES previous/next values are incorrect'; 00602 $this->debug($this->errormsg); 00603 $result = false; 00604 } 00606 if ($result && !$this->orderIndexes($this->indexes)) { 00607 $this->errormsg = 'Error ordering the indexes'; 00608 $this->debug($this->errormsg); 00609 $result = false; 00610 } 00613 } 00614 00616 if ($result) { 00617 $this->loaded = true; 00618 } 00619 $this->calculateHash(); 00620 return $result; 00621 } 00622 00626 function calculateHash($recursive = false) { 00627 if (!$this->loaded) { 00628 $this->hash = NULL; 00629 } else { 00630 $key = $this->name . $this->comment; 00631 if ($this->fields) { 00632 foreach ($this->fields as $fie) { 00633 $field =& $this->getField($fie->getName()); 00634 if ($recursive) { 00635 $field->calculateHash($recursive); 00636 } 00637 $key .= $field->getHash(); 00638 } 00639 } 00640 if ($this->keys) { 00641 foreach ($this->keys as $ke) { 00642 $k =& $this->getKey($ke->getName()); 00643 if ($recursive) { 00644 $k->calculateHash($recursive); 00645 } 00646 $key .= $k->getHash(); 00647 } 00648 } 00649 if ($this->indexes) { 00650 foreach ($this->indexes as $in) { 00651 $index =& $this->getIndex($in->getName()); 00652 if ($recursive) { 00653 $index->calculateHash($recursive); 00654 } 00655 $key .= $index->getHash(); 00656 } 00657 } 00658 $this->hash = md5($key); 00659 } 00660 } 00661 00665 function xmlOutput() { 00666 $o = ''; 00667 $o.= ' <TABLE NAME="' . $this->name . '"'; 00668 if ($this->comment) { 00669 $o.= ' COMMENT="' . htmlspecialchars($this->comment) . '"'; 00670 } 00671 if ($this->previous) { 00672 $o.= ' PREVIOUS="' . $this->previous . '"'; 00673 } 00674 if ($this->next) { 00675 $o.= ' NEXT="' . $this->next . '"'; 00676 } 00677 $o.= '>' . "\n"; 00679 if ($this->fields) { 00680 $o.= ' <FIELDS>' . "\n"; 00681 foreach ($this->fields as $field) { 00682 $o.= $field->xmlOutput(); 00683 } 00684 $o.= ' </FIELDS>' . "\n"; 00685 } 00687 if ($this->keys) { 00688 $o.= ' <KEYS>' . "\n"; 00689 foreach ($this->keys as $key) { 00690 $o.= $key->xmlOutput(); 00691 } 00692 $o.= ' </KEYS>' . "\n"; 00693 } 00695 if ($this->indexes) { 00696 $o.= ' <INDEXES>' . "\n"; 00697 foreach ($this->indexes as $index) { 00698 $o.= $index->xmlOutput(); 00699 } 00700 $o.= ' </INDEXES>' . "\n"; 00701 } 00702 $o.= ' </TABLE>' . "\n"; 00703 00704 return $o; 00705 } 00706 00709 function addFieldInfo($name, $type, $precision=null, $unsigned=null, $notnull=null, $sequence=null, $enum=null, $enumvalues=null, $default=null, $previous=null) { 00710 00711 debugging('XMLDBTable->addFieldInfo() has been deprecated in Moodle 2.0. Will be out in Moodle 2.1. Please use xmldb_table->add_field() instead', DEBUG_DEVELOPER); 00712 if ($enum) { 00713 debugging('Also, ENUMs support has been dropped in Moodle 2.0. Your fields specs are incorrect because you are trying to introduce one new ENUM. Created DB estructures will ignore that.'); 00714 } 00715 00716 return $this->add_field($name, $type, $precision, $unsigned, $notnull, $sequence, $default, $previous); 00717 00718 } 00720 00734 function add_field($name, $type, $precision=null, $unsigned=null, $notnull=null, $sequence=null, $default=null, $previous=null) { 00735 $field = new xmldb_field($name, $type, $precision, $unsigned, $notnull, $sequence, $default); 00736 $this->addField($field, $previous); 00737 00738 return $field; 00739 } 00740 00743 00744 function addKeyInfo($name, $type, $fields, $reftable=null, $reffields=null) { 00745 00746 debugging('XMLDBTable->addKeyInfo() has been deprecated in Moodle 2.0. Will be out in Moodle 2.1. Please use xmldb_table->add_key() instead', DEBUG_DEVELOPER); 00747 00748 return $this->add_key($name, $type, $fields, $reftable, $reffields); 00749 00750 } 00752 00763 function add_key($name, $type, $fields, $reftable=null, $reffields=null) { 00764 $key = new xmldb_key($name, $type, $fields, $reftable, $reffields); 00765 $this->addKey($key); 00766 } 00767 00770 function addIndexInfo($name, $type, $fields) { 00771 00772 debugging('XMLDBTable->addIndexInfo() has been deprecated in Moodle 2.0. Will be out in Moodle 2.1. Please use xmldb_table->add_index() instead', DEBUG_DEVELOPER); 00773 00774 return $this->add_index($name, $type, $fields); 00775 00776 } 00778 00787 function add_index($name, $type, $fields) { 00788 $index = new xmldb_index($name, $type, $fields); 00789 $this->addIndex($index); 00790 } 00791 00797 function getAllErrors() { 00798 00799 $errors = array(); 00801 if ($this->getError()) { 00802 $errors[] = $this->getError(); 00803 } 00805 if ($fields = $this->getFields()) { 00806 foreach ($fields as $field) { 00807 if ($field->getError()) { 00808 $errors[] = $field->getError(); 00809 } 00810 } 00811 } 00813 if ($keys = $this->getKeys()) { 00814 foreach ($keys as $key) { 00815 if ($key->getError()) { 00816 $errors[] = $key->getError(); 00817 } 00818 } 00819 } 00821 if ($indexes = $this->getIndexes()) { 00822 foreach ($indexes as $index) { 00823 if ($index->getError()) { 00824 $errors[] = $index->getError(); 00825 } 00826 } 00827 } 00829 if (count($errors)) { 00830 return $errors; 00831 } else { 00832 return false; 00833 } 00834 } 00835 } 00836 00839 class XMLDBTable extends xmldb_table { 00840 00841 function __construct($name) { 00842 parent::__construct($name); 00843 } 00844 00845 }