Differences Between: [Versions 310 and 402] [Versions 311 and 402] [Versions 39 and 402] [Versions 400 and 402] [Versions 402 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 * This class represent one XMLDB table 19 * 20 * @package core_xmldb 21 * @copyright 1999 onwards Martin Dougiamas http://dougiamas.com 22 * 2001-3001 Eloy Lafuente (stronk7) http://contiento.com 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26 defined('MOODLE_INTERNAL') || die(); 27 28 29 class xmldb_table extends xmldb_object { 30 31 /** @var xmldb_field[] table columns */ 32 protected $fields; 33 34 /** @var xmldb_key[] keys */ 35 protected $keys; 36 37 /** @var xmldb_index[] indexes */ 38 protected $indexes; 39 40 /** 41 * Note: 42 * - Oracle has 30 chars limit for all names, 43 * 2 chars are reserved for prefix. 44 * 45 * @const maximum length of field names 46 */ 47 const NAME_MAX_LENGTH = 28; 48 49 /** 50 * Creates one new xmldb_table 51 * @param string $name 52 */ 53 public function __construct($name) { 54 parent::__construct($name); 55 $this->fields = array(); 56 $this->keys = array(); 57 $this->indexes = array(); 58 } 59 60 /** 61 * Add one field to the table, allowing to specify the desired order 62 * If it's not specified, then the field is added at the end 63 * @param xmldb_field $field 64 * @param xmldb_object $after 65 * @return xmldb_field 66 */ 67 public function addField($field, $after=null) { 68 69 // Detect duplicates first 70 if ($this->getField($field->getName())) { 71 throw new coding_exception('Duplicate field '.$field->getName().' specified in table '.$this->getName()); 72 } 73 74 // Calculate the previous and next fields 75 $prevfield = null; 76 $nextfield = null; 77 78 if (!$after) { 79 $allfields = $this->getFields(); 80 if (!empty($allfields)) { 81 end($allfields); 82 $prevfield = $allfields[key($allfields)]; 83 } 84 } else { 85 $prevfield = $this->getField($after); 86 } 87 if ($prevfield && $prevfield->getNext()) { 88 $nextfield = $this->getField($prevfield->getNext()); 89 } 90 91 // Set current field previous and next attributes 92 if ($prevfield) { 93 $field->setPrevious($prevfield->getName()); 94 $prevfield->setNext($field->getName()); 95 } 96 if ($nextfield) { 97 $field->setNext($nextfield->getName()); 98 $nextfield->setPrevious($field->getName()); 99 } 100 // Some more attributes 101 $field->setLoaded(true); 102 $field->setChanged(true); 103 // Add the new field 104 $this->fields[] = $field; 105 // Reorder the field 106 $this->orderFields($this->fields); 107 // Recalculate the hash 108 $this->calculateHash(true); 109 // We have one new field, so the table has changed 110 $this->setChanged(true); 111 112 return $field; 113 } 114 115 /** 116 * Add one key to the table, allowing to specify the desired order 117 * If it's not specified, then the key is added at the end 118 * @param xmldb_key $key 119 * @param xmldb_object $after 120 */ 121 public function addKey($key, $after=null) { 122 123 // Detect duplicates first 124 if ($this->getKey($key->getName())) { 125 throw new coding_exception('Duplicate key '.$key->getName().' specified in table '.$this->getName()); 126 } 127 128 // Make sure there are no indexes with the key column specs because they would collide. 129 $newfields = $key->getFields(); 130 $allindexes = $this->getIndexes(); 131 foreach ($allindexes as $index) { 132 $fields = $index->getFields(); 133 if ($fields === $newfields) { 134 throw new coding_exception('Index '.$index->getName().' collides with key'.$key->getName().' specified in table '.$this->getName()); 135 } 136 } 137 138 // Calculate the previous and next keys 139 $prevkey = null; 140 $nextkey = null; 141 142 if (!$after) { 143 $allkeys = $this->getKeys(); 144 if (!empty($allkeys)) { 145 end($allkeys); 146 $prevkey = $allkeys[key($allkeys)]; 147 } 148 } else { 149 $prevkey = $this->getKey($after); 150 } 151 if ($prevkey && $prevkey->getNext()) { 152 $nextkey = $this->getKey($prevkey->getNext()); 153 } 154 155 // Set current key previous and next attributes 156 if ($prevkey) { 157 $key->setPrevious($prevkey->getName()); 158 $prevkey->setNext($key->getName()); 159 } 160 if ($nextkey) { 161 $key->setNext($nextkey->getName()); 162 $nextkey->setPrevious($key->getName()); 163 } 164 // Some more attributes 165 $key->setLoaded(true); 166 $key->setChanged(true); 167 // Add the new key 168 $this->keys[] = $key; 169 // Reorder the keys 170 $this->orderKeys($this->keys); 171 // Recalculate the hash 172 $this->calculateHash(true); 173 // We have one new field, so the table has changed 174 $this->setChanged(true); 175 } 176 177 /** 178 * Add one index to the table, allowing to specify the desired order 179 * If it's not specified, then the index is added at the end 180 * @param xmldb_index $index 181 * @param xmldb_object $after 182 */ 183 public function addIndex($index, $after=null) { 184 185 // Detect duplicates first 186 if ($this->getIndex($index->getName())) { 187 throw new coding_exception('Duplicate index '.$index->getName().' specified in table '.$this->getName()); 188 } 189 190 // Make sure there are no keys with the index column specs because they would collide. 191 $newfields = $index->getFields(); 192 $allkeys = $this->getKeys(); 193 foreach ($allkeys as $key) { 194 $fields = $key->getFields(); 195 if ($fields === $newfields) { 196 throw new coding_exception('Key '.$key->getName().' collides with index'.$index->getName().' specified in table '.$this->getName()); 197 } 198 } 199 200 // Calculate the previous and next indexes 201 $previndex = null; 202 $nextindex = null; 203 204 if (!$after) { 205 $allindexes = $this->getIndexes(); 206 if (!empty($allindexes)) { 207 end($allindexes); 208 $previndex = $allindexes[key($allindexes)]; 209 } 210 } else { 211 $previndex = $this->getIndex($after); 212 } 213 if ($previndex && $previndex->getNext()) { 214 $nextindex = $this->getIndex($previndex->getNext()); 215 } 216 217 // Set current index previous and next attributes 218 if ($previndex) { 219 $index->setPrevious($previndex->getName()); 220 $previndex->setNext($index->getName()); 221 } 222 if ($nextindex) { 223 $index->setNext($nextindex->getName()); 224 $nextindex->setPrevious($index->getName()); 225 } 226 227 // Some more attributes 228 $index->setLoaded(true); 229 $index->setChanged(true); 230 // Add the new index 231 $this->indexes[] = $index; 232 // Reorder the indexes 233 $this->orderIndexes($this->indexes); 234 // Recalculate the hash 235 $this->calculateHash(true); 236 // We have one new index, so the table has changed 237 $this->setChanged(true); 238 } 239 240 /** 241 * This function will return the array of fields in the table 242 * @return xmldb_field[] 243 */ 244 public function getFields() { 245 return $this->fields; 246 } 247 248 /** 249 * This function will return the array of keys in the table 250 * @return xmldb_key[] 251 */ 252 public function getKeys() { 253 return $this->keys; 254 } 255 256 /** 257 * This function will return the array of indexes in the table 258 * @return xmldb_index[] 259 */ 260 public function getIndexes() { 261 return $this->indexes; 262 } 263 264 /** 265 * Returns one xmldb_field 266 * @param string $fieldname 267 * @return xmldb_field|null 268 */ 269 public function getField($fieldname) { 270 $i = $this->findFieldInArray($fieldname); 271 if ($i !== null) { 272 return $this->fields[$i]; 273 } 274 return null; 275 } 276 277 /** 278 * Returns the position of one field in the array. 279 * @param string $fieldname 280 * @return int|null index of the field, or null if not found. 281 */ 282 public function findFieldInArray($fieldname) { 283 foreach ($this->fields as $i => $field) { 284 if ($fieldname == $field->getName()) { 285 return $i; 286 } 287 } 288 return null; 289 } 290 291 /** 292 * This function will reorder the array of fields 293 * @return bool whether the reordering succeeded. 294 */ 295 public function orderFields() { 296 $result = $this->orderElements($this->fields); 297 if ($result) { 298 $this->setFields($result); 299 return true; 300 } else { 301 return false; 302 } 303 } 304 305 /** 306 * Returns one xmldb_key 307 * @param string $keyname 308 * @return xmldb_key|null 309 */ 310 public function getKey($keyname) { 311 $i = $this->findKeyInArray($keyname); 312 if ($i !== null) { 313 return $this->keys[$i]; 314 } 315 return null; 316 } 317 318 /** 319 * Returns the position of one key in the array. 320 * @param string $keyname 321 * @return int|null index of the key, or null if not found. 322 */ 323 public function findKeyInArray($keyname) { 324 foreach ($this->keys as $i => $key) { 325 if ($keyname == $key->getName()) { 326 return $i; 327 } 328 } 329 return null; 330 } 331 332 /** 333 * This function will reorder the array of keys 334 * @return bool whether the reordering succeeded. 335 */ 336 public function orderKeys() { 337 $result = $this->orderElements($this->keys); 338 if ($result) { 339 $this->setKeys($result); 340 return true; 341 } else { 342 return false; 343 } 344 } 345 346 /** 347 * Returns one xmldb_index 348 * @param string $indexname 349 * @return xmldb_index|null 350 */ 351 public function getIndex($indexname) { 352 $i = $this->findIndexInArray($indexname); 353 if ($i !== null) { 354 return $this->indexes[$i]; 355 } 356 return null; 357 } 358 359 /** 360 * Returns the position of one index in the array. 361 * @param string $indexname 362 * @return int|null index of the index, or null if not found. 363 */ 364 public function findIndexInArray($indexname) { 365 foreach ($this->indexes as $i => $index) { 366 if ($indexname == $index->getName()) { 367 return $i; 368 } 369 } 370 return null; 371 } 372 373 /** 374 * This function will reorder the array of indexes 375 * @return bool whether the reordering succeeded. 376 */ 377 public function orderIndexes() { 378 $result = $this->orderElements($this->indexes); 379 if ($result) { 380 $this->setIndexes($result); 381 return true; 382 } else { 383 return false; 384 } 385 } 386 387 /** 388 * This function will set the array of fields in the table 389 * @param xmldb_field[] $fields 390 */ 391 public function setFields($fields) { 392 $this->fields = $fields; 393 } 394 395 /** 396 * This function will set the array of keys in the table 397 * @param xmldb_key[] $keys 398 */ 399 public function setKeys($keys) { 400 $this->keys = $keys; 401 } 402 403 /** 404 * This function will set the array of indexes in the table 405 * @param xmldb_index[] $indexes 406 */ 407 public function setIndexes($indexes) { 408 $this->indexes = $indexes; 409 } 410 411 /** 412 * Delete one field from the table 413 * @param string $fieldname 414 */ 415 public function deleteField($fieldname) { 416 417 $field = $this->getField($fieldname); 418 if ($field) { 419 $i = $this->findFieldInArray($fieldname); 420 // Look for prev and next field 421 $prevfield = $this->getField($field->getPrevious()); 422 $nextfield = $this->getField($field->getNext()); 423 // Change their previous and next attributes 424 if ($prevfield) { 425 $prevfield->setNext($field->getNext()); 426 } 427 if ($nextfield) { 428 $nextfield->setPrevious($field->getPrevious()); 429 } 430 // Delete the field 431 unset($this->fields[$i]); 432 // Reorder the whole structure 433 $this->orderFields($this->fields); 434 // Recalculate the hash 435 $this->calculateHash(true); 436 // We have one deleted field, so the table has changed 437 $this->setChanged(true); 438 } 439 } 440 441 /** 442 * Delete one key from the table 443 * @param string $keyname 444 */ 445 public function deleteKey($keyname) { 446 447 $key = $this->getKey($keyname); 448 if ($key) { 449 $i = $this->findKeyInArray($keyname); 450 // Look for prev and next key 451 $prevkey = $this->getKey($key->getPrevious()); 452 $nextkey = $this->getKey($key->getNext()); 453 // Change their previous and next attributes 454 if ($prevkey) { 455 $prevkey->setNext($key->getNext()); 456 } 457 if ($nextkey) { 458 $nextkey->setPrevious($key->getPrevious()); 459 } 460 // Delete the key 461 unset($this->keys[$i]); 462 // Reorder the Keys 463 $this->orderKeys($this->keys); 464 // Recalculate the hash 465 $this->calculateHash(true); 466 // We have one deleted key, so the table has changed 467 $this->setChanged(true); 468 } 469 } 470 471 /** 472 * Delete one index from the table 473 * @param string $indexname 474 */ 475 public function deleteIndex($indexname) { 476 477 $index = $this->getIndex($indexname); 478 if ($index) { 479 $i = $this->findIndexInArray($indexname); 480 // Look for prev and next index 481 $previndex = $this->getIndex($index->getPrevious()); 482 $nextindex = $this->getIndex($index->getNext()); 483 // Change their previous and next attributes 484 if ($previndex) { 485 $previndex->setNext($index->getNext()); 486 } 487 if ($nextindex) { 488 $nextindex->setPrevious($index->getPrevious()); 489 } 490 // Delete the index 491 unset($this->indexes[$i]); 492 // Reorder the indexes 493 $this->orderIndexes($this->indexes); 494 // Recalculate the hash 495 $this->calculateHash(true); 496 // We have one deleted index, so the table has changed 497 $this->setChanged(true); 498 } 499 } 500 501 /** 502 * Load data from XML to the table 503 * @param array $xmlarr 504 * @return bool success 505 */ 506 public function arr2xmldb_table($xmlarr) { 507 508 global $CFG; 509 510 $result = true; 511 512 // Debug the table 513 // traverse_xmlize($xmlarr); //Debug 514 // print_object ($GLOBALS['traverse_array']); //Debug 515 // $GLOBALS['traverse_array']=""; //Debug 516 517 // Process table attributes (name, comment, previoustable and nexttable) 518 if (isset($xmlarr['@']['NAME'])) { 519 $this->name = trim($xmlarr['@']['NAME']); 520 } else { 521 $this->errormsg = 'Missing NAME attribute'; 522 $this->debug($this->errormsg); 523 $result = false; 524 } 525 if (isset($xmlarr['@']['COMMENT'])) { 526 $this->comment = trim($xmlarr['@']['COMMENT']); 527 } else if (!empty($CFG->xmldbdisablecommentchecking)) { 528 $this->comment = ''; 529 } else { 530 $this->errormsg = 'Missing COMMENT attribute'; 531 $this->debug($this->errormsg); 532 $result = false; 533 } 534 535 // Iterate over fields 536 if (isset($xmlarr['#']['FIELDS']['0']['#']['FIELD'])) { 537 foreach ($xmlarr['#']['FIELDS']['0']['#']['FIELD'] as $xmlfield) { 538 if (!$result) { //Skip on error 539 continue; 540 } 541 $name = trim($xmlfield['@']['NAME']); 542 $field = new xmldb_field($name); 543 $field->arr2xmldb_field($xmlfield); 544 $this->fields[] = $field; 545 if (!$field->isLoaded()) { 546 $this->errormsg = 'Problem loading field ' . $name; 547 $this->debug($this->errormsg); 548 $result = false; 549 } 550 } 551 } else { 552 $this->errormsg = 'Missing FIELDS section'; 553 $this->debug($this->errormsg); 554 $result = false; 555 } 556 557 // Perform some general checks over fields 558 if ($result && $this->fields) { 559 // Check field names are ok (lowercase, a-z _-) 560 if (!$this->checkNameValues($this->fields)) { 561 $this->errormsg = 'Some FIELDS name values are incorrect'; 562 $this->debug($this->errormsg); 563 $result = false; 564 } 565 // Compute prev/next. 566 $this->fixPrevNext($this->fields); 567 // Order fields 568 if ($result && !$this->orderFields($this->fields)) { 569 $this->errormsg = 'Error ordering the fields'; 570 $this->debug($this->errormsg); 571 $result = false; 572 } 573 } 574 575 // Iterate over keys 576 if (isset($xmlarr['#']['KEYS']['0']['#']['KEY'])) { 577 foreach ($xmlarr['#']['KEYS']['0']['#']['KEY'] as $xmlkey) { 578 if (!$result) { //Skip on error 579 continue; 580 } 581 $name = trim($xmlkey['@']['NAME']); 582 $key = new xmldb_key($name); 583 $key->arr2xmldb_key($xmlkey); 584 $this->keys[] = $key; 585 if (!$key->isLoaded()) { 586 $this->errormsg = 'Problem loading key ' . $name; 587 $this->debug($this->errormsg); 588 $result = false; 589 } 590 } 591 } else { 592 $this->errormsg = 'Missing KEYS section (at least one PK must exist)'; 593 $this->debug($this->errormsg); 594 $result = false; 595 } 596 597 // Perform some general checks over keys 598 if ($result && $this->keys) { 599 // Check keys names are ok (lowercase, a-z _-) 600 if (!$this->checkNameValues($this->keys)) { 601 $this->errormsg = 'Some KEYS name values are incorrect'; 602 $this->debug($this->errormsg); 603 $result = false; 604 } 605 // Compute prev/next. 606 $this->fixPrevNext($this->keys); 607 // Order keys 608 if ($result && !$this->orderKeys($this->keys)) { 609 $this->errormsg = 'Error ordering the keys'; 610 $this->debug($this->errormsg); 611 $result = false; 612 } 613 // TODO: Only one PK 614 // TODO: Not keys with repeated fields 615 // TODO: Check fields and reffieds exist in table 616 } 617 618 // Iterate over indexes 619 if (isset($xmlarr['#']['INDEXES']['0']['#']['INDEX'])) { 620 foreach ($xmlarr['#']['INDEXES']['0']['#']['INDEX'] as $xmlindex) { 621 if (!$result) { //Skip on error 622 continue; 623 } 624 $name = trim($xmlindex['@']['NAME']); 625 $index = new xmldb_index($name); 626 $index->arr2xmldb_index($xmlindex); 627 $this->indexes[] = $index; 628 if (!$index->isLoaded()) { 629 $this->errormsg = 'Problem loading index ' . $name; 630 $this->debug($this->errormsg); 631 $result = false; 632 } 633 } 634 } 635 636 // Perform some general checks over indexes 637 if ($result && $this->indexes) { 638 // Check field names are ok (lowercase, a-z _-) 639 if (!$this->checkNameValues($this->indexes)) { 640 $this->errormsg = 'Some INDEXES name values are incorrect'; 641 $this->debug($this->errormsg); 642 $result = false; 643 } 644 // Compute prev/next. 645 $this->fixPrevNext($this->indexes); 646 // Order indexes 647 if ($result && !$this->orderIndexes($this->indexes)) { 648 $this->errormsg = 'Error ordering the indexes'; 649 $this->debug($this->errormsg); 650 $result = false; 651 } 652 // TODO: Not indexes with repeated fields 653 // TODO: Check fields exist in table 654 } 655 656 // Set some attributes 657 if ($result) { 658 $this->loaded = true; 659 } 660 $this->calculateHash(); 661 return $result; 662 } 663 664 /** 665 * This function calculate and set the hash of one xmldb_table 666 * @param bool $recursive 667 */ 668 public function calculateHash($recursive = false) { 669 if (!$this->loaded) { 670 $this->hash = null; 671 } else { 672 $key = $this->name . $this->comment; 673 if ($this->fields) { 674 foreach ($this->fields as $fie) { 675 $field = $this->getField($fie->getName()); 676 if ($recursive) { 677 $field->calculateHash($recursive); 678 } 679 $key .= $field->getHash(); 680 } 681 } 682 if ($this->keys) { 683 foreach ($this->keys as $ke) { 684 $k = $this->getKey($ke->getName()); 685 if ($recursive) { 686 $k->calculateHash($recursive); 687 } 688 $key .= $k->getHash(); 689 } 690 } 691 if ($this->indexes) { 692 foreach ($this->indexes as $in) { 693 $index = $this->getIndex($in->getName()); 694 if ($recursive) { 695 $index->calculateHash($recursive); 696 } 697 $key .= $index->getHash(); 698 } 699 } 700 $this->hash = md5($key); 701 } 702 } 703 704 /** 705 * Validates the table restrictions (does not validate child elements). 706 * 707 * The error message should not be localised because it is intended for developers, 708 * end users and admins should never see these problems! 709 * 710 * @param xmldb_table $xmldb_table optional when object is table 711 * @return string null if ok, error message if problem found 712 */ 713 public function validateDefinition(xmldb_table $xmldb_table=null) { 714 // table parameter is ignored 715 $name = $this->getName(); 716 if (strlen($name) > self::NAME_MAX_LENGTH) { 717 return 'Invalid table name {'.$name.'}: name is too long. Limit is '.self::NAME_MAX_LENGTH.' chars.'; 718 } 719 if (!preg_match('/^[a-z][a-z0-9_]*$/', $name)) { 720 return 'Invalid table name {'.$name.'}: name includes invalid characters.'; 721 } 722 723 return null; 724 } 725 726 /** 727 * This function will output the XML text for one table 728 * @return string 729 */ 730 public function xmlOutput() { 731 $o = ''; 732 $o.= ' <TABLE NAME="' . $this->name . '"'; 733 if ($this->comment) { 734 $o.= ' COMMENT="' . htmlspecialchars($this->comment, ENT_COMPAT) . '"'; 735 } 736 $o.= '>' . "\n"; 737 // Now the fields 738 if ($this->fields) { 739 $o.= ' <FIELDS>' . "\n"; 740 foreach ($this->fields as $field) { 741 $o.= $field->xmlOutput(); 742 } 743 $o.= ' </FIELDS>' . "\n"; 744 } 745 // Now the keys 746 if ($this->keys) { 747 $o.= ' <KEYS>' . "\n"; 748 foreach ($this->keys as $key) { 749 $o.= $key->xmlOutput(); 750 } 751 $o.= ' </KEYS>' . "\n"; 752 } 753 // Now the indexes 754 if ($this->indexes) { 755 $o.= ' <INDEXES>' . "\n"; 756 foreach ($this->indexes as $index) { 757 $o.= $index->xmlOutput(); 758 } 759 $o.= ' </INDEXES>' . "\n"; 760 } 761 $o.= ' </TABLE>' . "\n"; 762 763 return $o; 764 } 765 766 /** 767 * This function will add one new field to the table with all 768 * its attributes defined 769 * 770 * @param string $name name of the field 771 * @param int $type XMLDB_TYPE_INTEGER, XMLDB_TYPE_NUMBER, XMLDB_TYPE_CHAR, XMLDB_TYPE_TEXT, XMLDB_TYPE_BINARY 772 * @param string $precision length for integers and chars, two-comma separated numbers for numbers 773 * @param bool $unsigned XMLDB_UNSIGNED or null (or false) 774 * @param bool $notnull XMLDB_NOTNULL or null (or false) 775 * @param bool $sequence XMLDB_SEQUENCE or null (or false) 776 * @param mixed $default meaningful default o null (or false) 777 * @param xmldb_object $previous name of the previous field in the table or null (or false) 778 * @return xmlddb_field 779 */ 780 public function add_field($name, $type, $precision=null, $unsigned=null, $notnull=null, $sequence=null, $default=null, $previous=null) { 781 $field = new xmldb_field($name, $type, $precision, $unsigned, $notnull, $sequence, $default); 782 $this->addField($field, $previous); 783 784 return $field; 785 } 786 787 /** 788 * This function will add one new key to the table with all 789 * its attributes defined 790 * 791 * @param string $name name of the key 792 * @param int $type XMLDB_KEY_PRIMARY, XMLDB_KEY_UNIQUE, XMLDB_KEY_FOREIGN 793 * @param array $fields an array of fieldnames to build the key over 794 * @param string $reftable name of the table the FK points to or null 795 * @param array $reffields an array of fieldnames in the FK table or null 796 */ 797 public function add_key($name, $type, $fields, $reftable=null, $reffields=null) { 798 $key = new xmldb_key($name, $type, $fields, $reftable, $reffields); 799 $this->addKey($key); 800 } 801 802 /** 803 * This function will add one new index to the table with all 804 * its attributes defined 805 * 806 * @param string $name name of the index 807 * @param int $type XMLDB_INDEX_UNIQUE, XMLDB_INDEX_NOTUNIQUE 808 * @param array $fields an array of fieldnames to build the index over 809 * @param array $hints optional index type hints 810 */ 811 public function add_index($name, $type, $fields, $hints = array()) { 812 $index = new xmldb_index($name, $type, $fields, $hints); 813 $this->addIndex($index); 814 } 815 816 /** 817 * This function will return all the errors found in one table 818 * looking recursively inside each field/key/index. Returns 819 * an array of errors or false 820 */ 821 public function getAllErrors() { 822 823 $errors = array(); 824 // First the table itself 825 if ($this->getError()) { 826 $errors[] = $this->getError(); 827 } 828 // Delegate to fields 829 if ($fields = $this->getFields()) { 830 foreach ($fields as $field) { 831 if ($field->getError()) { 832 $errors[] = $field->getError(); 833 } 834 } 835 } 836 // Delegate to keys 837 if ($keys = $this->getKeys()) { 838 foreach ($keys as $key) { 839 if ($key->getError()) { 840 $errors[] = $key->getError(); 841 } 842 } 843 } 844 // Delegate to indexes 845 if ($indexes = $this->getIndexes()) { 846 foreach ($indexes as $index) { 847 if ($index->getError()) { 848 $errors[] = $index->getError(); 849 } 850 } 851 } 852 // Return decision 853 if (count($errors)) { 854 return $errors; 855 } else { 856 return false; 857 } 858 } 859 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body