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