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 Field 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 26defined('MOODLE_INTERNAL') || die(); 27 28 29class xmldb_field extends xmldb_object { 30 31 /** @var int XMLDB_TYPE_ constants */ 32 protected $type; 33 34 /** @var int size of field */ 35 protected $length; 36 37 /** @var bool is null forbidden? XMLDB_NOTNULL */ 38 protected $notnull; 39 40 /** @var mixed default value */ 41 protected $default; 42 43 /** @var bool use automatic counter */ 44 protected $sequence; 45 46 /** @var int number of decimals */ 47 protected $decimals; 48 49 /** 50 * Note: 51 * - Oracle: VARCHAR2 has a limit of 4000 bytes 52 * - SQL Server: NVARCHAR has a limit of 40000 chars 53 * - MySQL: VARCHAR 65,535 chars 54 * - PostgreSQL: no limit 55 * 56 * @const maximum length of text field 57 */ 58 const CHAR_MAX_LENGTH = 1333; 59 60 61 /** 62 * @const maximum number of digits of integers 63 */ 64 const INTEGER_MAX_LENGTH = 20; 65 66 /** 67 * @const max length (precision, the total number of digits) of decimals 68 */ 69 const NUMBER_MAX_LENGTH = 38; 70 71 /** 72 * @const max length of floats 73 */ 74 const FLOAT_MAX_LENGTH = 20; 75 76 /** 77 * Note: 78 * - Oracle has 30 chars limit for all names 79 * 80 * @const maximumn length of field names 81 */ 82 const NAME_MAX_LENGTH = 30; 83 84 /** 85 * Creates one new xmldb_field 86 * @param string $name of field 87 * @param int $type XMLDB_TYPE_INTEGER, XMLDB_TYPE_NUMBER, XMLDB_TYPE_CHAR, XMLDB_TYPE_TEXT, XMLDB_TYPE_BINARY 88 * @param string $precision length for integers and chars, two-comma separated numbers for numbers 89 * @param bool $unsigned XMLDB_UNSIGNED or null (or false) 90 * @param bool $notnull XMLDB_NOTNULL or null (or false) 91 * @param bool $sequence XMLDB_SEQUENCE or null (or false) 92 * @param mixed $default meaningful default o null (or false) 93 * @param xmldb_object $previous 94 */ 95 public function __construct($name, $type=null, $precision=null, $unsigned=null, $notnull=null, $sequence=null, $default=null, $previous=null) { 96 $this->type = null; 97 $this->length = null; 98 $this->notnull = false; 99 $this->default = null; 100 $this->sequence = false; 101 $this->decimals = null; 102 parent::__construct($name); 103 $this->set_attributes($type, $precision, $unsigned, $notnull, $sequence, $default, $previous); 104 } 105 106 /** 107 * Set all the attributes of one xmldb_field 108 * 109 * @param int $type XMLDB_TYPE_INTEGER, XMLDB_TYPE_NUMBER, XMLDB_TYPE_CHAR, XMLDB_TYPE_TEXT, XMLDB_TYPE_BINARY 110 * @param string $precision length for integers and chars, two-comma separated numbers for numbers 111 * @param bool $unsigned XMLDB_UNSIGNED or null (or false) 112 * @param bool $notnull XMLDB_NOTNULL or null (or false) 113 * @param bool $sequence XMLDB_SEQUENCE or null (or false) 114 * @param mixed $default meaningful default o null (or false) 115 * @param xmldb_object $previous 116 */ 117 public function set_attributes($type, $precision=null, $unsigned=null, $notnull=null, $sequence=null, $default=null, $previous=null) { 118 $this->type = $type; 119 /// Try to split the precision into length and decimals and apply 120 /// each one as needed 121 $precisionarr = explode(',', $precision); 122 if (isset($precisionarr[0])) { 123 $this->length = trim($precisionarr[0]); 124 } 125 if (isset($precisionarr[1])) { 126 $this->decimals = trim($precisionarr[1]); 127 } 128 $this->precision = $type; 129 $this->notnull = !empty($notnull) ? true : false; 130 $this->sequence = !empty($sequence) ? true : false; 131 $this->setDefault($default); 132 133 if ($this->type == XMLDB_TYPE_BINARY || $this->type == XMLDB_TYPE_TEXT) { 134 $this->length = null; 135 $this->decimals = null; 136 } 137 138 $this->previous = $previous; 139 } 140 141 /** 142 * Get the type 143 * @return int 144 */ 145 public function getType() { 146 return $this->type; 147 } 148 149 /** 150 * Get the length 151 * @return int 152 */ 153 public function getLength() { 154 return $this->length; 155 } 156 157 /** 158 * Get the decimals 159 * @return string 160 */ 161 public function getDecimals() { 162 return $this->decimals; 163 } 164 165 /** 166 * Get the notnull 167 * @return bool 168 */ 169 public function getNotNull() { 170 return $this->notnull; 171 } 172 173 /** 174 * Get the unsigned 175 * @deprecated since moodle 2.3 176 * @return bool 177 */ 178 public function getUnsigned() { 179 return false; 180 } 181 182 /** 183 * Get the sequence 184 * @return bool 185 */ 186 public function getSequence() { 187 return $this->sequence; 188 } 189 190 /** 191 * Get the default 192 * @return mixed 193 */ 194 public function getDefault() { 195 return $this->default; 196 } 197 198 /** 199 * Set the field type 200 * @param int $type 201 */ 202 public function setType($type) { 203 $this->type = $type; 204 } 205 206 /** 207 * Set the field length 208 * @param int $length 209 */ 210 public function setLength($length) { 211 $this->length = $length; 212 } 213 214 /** 215 * Set the field decimals 216 * @param string 217 */ 218 public function setDecimals($decimals) { 219 $this->decimals = $decimals; 220 } 221 222 /** 223 * Set the field unsigned 224 * @deprecated since moodle 2.3 225 * @param bool $unsigned 226 */ 227 public function setUnsigned($unsigned=true) { 228 } 229 230 /** 231 * Set the field notnull 232 * @param bool $notnull 233 */ 234 public function setNotNull($notnull=true) { 235 $this->notnull = $notnull; 236 } 237 238 /** 239 * Set the field sequence 240 * @param bool $sequence 241 */ 242 public function setSequence($sequence=true) { 243 $this->sequence = $sequence; 244 } 245 246 /** 247 * Set the field default 248 * @param mixed $default 249 */ 250 public function setDefault($default) { 251 // Check, warn and auto-fix '' (empty) defaults for CHAR NOT NULL columns, changing them 252 // to NULL so XMLDB will apply the proper default 253 if ($this->type == XMLDB_TYPE_CHAR && $this->notnull && $default === '') { 254 $this->errormsg = 'XMLDB has detected one CHAR NOT NULL column (' . $this->name . ") with '' (empty string) as DEFAULT value. This type of columns must have one meaningful DEFAULT declared or none (NULL). XMLDB have fixed it automatically changing it to none (NULL). The process will continue ok and proper defaults will be created accordingly with each DB requirements. Please fix it in source (XML and/or upgrade script) to avoid this message to be displayed."; 255 $this->debug($this->errormsg); 256 $default = null; 257 } 258 // Check, warn and autofix TEXT|BINARY columns having a default clause (only null is allowed) 259 if (($this->type == XMLDB_TYPE_TEXT || $this->type == XMLDB_TYPE_BINARY) && $default !== null) { 260 $this->errormsg = 'XMLDB has detected one TEXT/BINARY column (' . $this->name . ") with some DEFAULT defined. This type of columns cannot have any default value. Please fix it in source (XML and/or upgrade script) to avoid this message to be displayed."; 261 $this->debug($this->errormsg); 262 $default = null; 263 } 264 $this->default = $default; 265 } 266 267 /** 268 * Load data from XML to the table 269 * @param array $xmlarr 270 * @return mixed 271 */ 272 public function arr2xmldb_field($xmlarr) { 273 274 $result = true; 275 276 // Debug the table 277 // traverse_xmlize($xmlarr); //Debug 278 // print_object ($GLOBALS['traverse_array']); //Debug 279 // $GLOBALS['traverse_array']=""; //Debug 280 281 // Process table attributes (name, type, length 282 // notnull, sequence, decimals, comment, previous, next) 283 if (isset($xmlarr['@']['NAME'])) { 284 $this->name = trim($xmlarr['@']['NAME']); 285 } else { 286 $this->errormsg = 'Missing NAME attribute'; 287 $this->debug($this->errormsg); 288 $result = false; 289 } 290 291 if (isset($xmlarr['@']['TYPE'])) { 292 // Check for valid type 293 $type = $this->getXMLDBFieldType(trim($xmlarr['@']['TYPE'])); 294 if ($type) { 295 $this->type = $type; 296 } else { 297 $this->errormsg = 'Invalid TYPE attribute'; 298 $this->debug($this->errormsg); 299 $result = false; 300 } 301 } else { 302 $this->errormsg = 'Missing TYPE attribute'; 303 $this->debug($this->errormsg); 304 $result = false; 305 } 306 307 if (isset($xmlarr['@']['LENGTH'])) { 308 $length = trim($xmlarr['@']['LENGTH']); 309 // Check for integer values 310 if ($this->type == XMLDB_TYPE_INTEGER || 311 $this->type == XMLDB_TYPE_NUMBER || 312 $this->type == XMLDB_TYPE_CHAR) { 313 if (!(is_numeric($length)&&(intval($length)==floatval($length)))) { 314 $this->errormsg = 'Incorrect LENGTH attribute for int, number or char fields'; 315 $this->debug($this->errormsg); 316 $result = false; 317 } else if (!$length) { 318 $this->errormsg = 'Zero LENGTH attribute'; 319 $this->debug($this->errormsg); 320 $result = false; 321 } 322 } 323 // Remove length from text and binary 324 if ($this->type == XMLDB_TYPE_TEXT || 325 $this->type == XMLDB_TYPE_BINARY) { 326 $length = null; 327 } 328 // Finally, set the length 329 $this->length = $length; 330 } 331 332 if (isset($xmlarr['@']['NOTNULL'])) { 333 $notnull = strtolower(trim($xmlarr['@']['NOTNULL'])); 334 if ($notnull == 'true') { 335 $this->notnull = true; 336 } else if ($notnull == 'false') { 337 $this->notnull = false; 338 } else { 339 $this->errormsg = 'Incorrect NOTNULL attribute (true/false allowed)'; 340 $this->debug($this->errormsg); 341 $result = false; 342 } 343 } 344 345 if (isset($xmlarr['@']['SEQUENCE'])) { 346 $sequence = strtolower(trim($xmlarr['@']['SEQUENCE'])); 347 if ($sequence == 'true') { 348 $this->sequence = true; 349 } else if ($sequence == 'false') { 350 $this->sequence = false; 351 } else { 352 $this->errormsg = 'Incorrect SEQUENCE attribute (true/false allowed)'; 353 $this->debug($this->errormsg); 354 $result = false; 355 } 356 } 357 358 if (isset($xmlarr['@']['DEFAULT'])) { 359 $this->setDefault(trim($xmlarr['@']['DEFAULT'])); 360 } 361 362 $decimals = null; 363 if (isset($xmlarr['@']['DECIMALS'])) { 364 $decimals = trim($xmlarr['@']['DECIMALS']); 365 // Check for integer values 366 if ($this->type == XMLDB_TYPE_NUMBER || 367 $this->type == XMLDB_TYPE_FLOAT) { 368 if (!(is_numeric($decimals)&&(intval($decimals)==floatval($decimals)))) { 369 $this->errormsg = 'Incorrect DECIMALS attribute for number field'; 370 $this->debug($this->errormsg); 371 $result = false; 372 } else if ($this->length <= $decimals){ 373 $this->errormsg = 'Incorrect DECIMALS attribute (bigget than length)'; 374 $this->debug($this->errormsg); 375 $result = false; 376 } 377 } else { 378 $this->errormsg = 'Incorrect DECIMALS attribute for non-number field'; 379 $this->debug($this->errormsg); 380 $result = false; 381 } 382 } else { 383 if ($this->type == XMLDB_TYPE_NUMBER) { 384 $decimals = 0; 385 } 386 } 387 // Finally, set the decimals 388 if ($this->type == XMLDB_TYPE_NUMBER || 389 $this->type == XMLDB_TYPE_FLOAT) { 390 $this->decimals = $decimals; 391 } 392 393 if (isset($xmlarr['@']['COMMENT'])) { 394 $this->comment = trim($xmlarr['@']['COMMENT']); 395 } 396 397 // Set some attributes 398 if ($result) { 399 $this->loaded = true; 400 } 401 $this->calculateHash(); 402 return $result; 403 } 404 405 /** 406 * This function returns the correct XMLDB_TYPE_XXX value for the 407 * string passed as argument 408 * @param string $type 409 * @return int 410 */ 411 public function getXMLDBFieldType($type) { 412 413 $result = XMLDB_TYPE_INCORRECT; 414 415 switch (strtolower($type)) { 416 case 'int': 417 $result = XMLDB_TYPE_INTEGER; 418 break; 419 case 'number': 420 $result = XMLDB_TYPE_NUMBER; 421 break; 422 case 'float': 423 $result = XMLDB_TYPE_FLOAT; 424 break; 425 case 'char': 426 $result = XMLDB_TYPE_CHAR; 427 break; 428 case 'text': 429 $result = XMLDB_TYPE_TEXT; 430 break; 431 case 'binary': 432 $result = XMLDB_TYPE_BINARY; 433 break; 434 case 'datetime': 435 $result = XMLDB_TYPE_DATETIME; 436 break; 437 } 438 // Return the normalized XMLDB_TYPE 439 return $result; 440 } 441 442 /** 443 * This function returns the correct name value for the 444 * XMLDB_TYPE_XXX passed as argument 445 * @param int $type 446 * @return string 447 */ 448 public function getXMLDBTypeName($type) { 449 450 $result = ""; 451 452 switch (strtolower($type)) { 453 case XMLDB_TYPE_INTEGER: 454 $result = 'int'; 455 break; 456 case XMLDB_TYPE_NUMBER: 457 $result = 'number'; 458 break; 459 case XMLDB_TYPE_FLOAT: 460 $result = 'float'; 461 break; 462 case XMLDB_TYPE_CHAR: 463 $result = 'char'; 464 break; 465 case XMLDB_TYPE_TEXT: 466 $result = 'text'; 467 break; 468 case XMLDB_TYPE_BINARY: 469 $result = 'binary'; 470 break; 471 case XMLDB_TYPE_DATETIME: 472 $result = 'datetime'; 473 break; 474 } 475 // Return the normalized name 476 return $result; 477 } 478 479 /** 480 * This function calculate and set the hash of one xmldb_field 481 * @param bool $recursive 482 * @return void, modifies $this->hash 483 */ 484 public function calculateHash($recursive = false) { 485 if (!$this->loaded) { 486 $this->hash = null; 487 } else { 488 $defaulthash = is_null($this->default) ? '' : sha1($this->default); 489 $key = $this->name . $this->type . $this->length . 490 $this->notnull . $this->sequence . 491 $this->decimals . $this->comment . $defaulthash; 492 $this->hash = md5($key); 493 } 494 } 495 496 /** 497 * This function will output the XML text for one field 498 * @return string 499 */ 500 public function xmlOutput() { 501 $o = ''; 502 $o.= ' <FIELD NAME="' . $this->name . '"'; 503 $o.= ' TYPE="' . $this->getXMLDBTypeName($this->type) . '"'; 504 if ($this->length) { 505 $o.= ' LENGTH="' . $this->length . '"'; 506 } 507 if ($this->notnull) { 508 $notnull = 'true'; 509 } else { 510 $notnull = 'false'; 511 } 512 $o.= ' NOTNULL="' . $notnull . '"'; 513 if (!$this->sequence && $this->default !== null) { 514 $o.= ' DEFAULT="' . $this->default . '"'; 515 } 516 if ($this->sequence) { 517 $sequence = 'true'; 518 } else { 519 $sequence = 'false'; 520 } 521 $o.= ' SEQUENCE="' . $sequence . '"'; 522 if ($this->decimals !== null) { 523 $o.= ' DECIMALS="' . $this->decimals . '"'; 524 } 525 if ($this->comment) { 526 $o.= ' COMMENT="' . htmlspecialchars($this->comment) . '"'; 527 } 528 $o.= '/>' . "\n"; 529 530 return $o; 531 } 532 533 /** 534 * This function will set all the attributes of the xmldb_field object 535 * based on information passed in one ADOField 536 * @param string $adofield 537 * @return void, sets $this->type 538 */ 539 public function setFromADOField($adofield) { 540 541 // Calculate the XMLDB_TYPE 542 switch (strtolower($adofield->type)) { 543 case 'int': 544 case 'tinyint': 545 case 'smallint': 546 case 'bigint': 547 case 'integer': 548 $this->type = XMLDB_TYPE_INTEGER; 549 break; 550 case 'number': 551 case 'decimal': 552 case 'dec': 553 case 'numeric': 554 $this->type = XMLDB_TYPE_NUMBER; 555 break; 556 case 'float': 557 case 'double': 558 $this->type = XMLDB_TYPE_FLOAT; 559 break; 560 case 'char': 561 case 'varchar': 562 case 'enum': 563 $this->type = XMLDB_TYPE_CHAR; 564 break; 565 case 'text': 566 case 'tinytext': 567 case 'mediumtext': 568 case 'longtext': 569 $this->type = XMLDB_TYPE_TEXT; 570 break; 571 case 'blob': 572 case 'tinyblob': 573 case 'mediumblob': 574 case 'longblob': 575 $this->type = XMLDB_TYPE_BINARY; 576 break; 577 case 'datetime': 578 case 'timestamp': 579 $this->type = XMLDB_TYPE_DATETIME; 580 break; 581 default: 582 $this->type = XMLDB_TYPE_TEXT; 583 } 584 // Calculate the length of the field 585 if ($adofield->max_length > 0 && 586 ($this->type == XMLDB_TYPE_INTEGER || 587 $this->type == XMLDB_TYPE_NUMBER || 588 $this->type == XMLDB_TYPE_FLOAT || 589 $this->type == XMLDB_TYPE_CHAR)) { 590 $this->length = $adofield->max_length; 591 } 592 if ($this->type == XMLDB_TYPE_TEXT) { 593 $this->length = null; 594 } 595 if ($this->type == XMLDB_TYPE_BINARY) { 596 $this->length = null; 597 } 598 // Calculate the decimals of the field 599 if ($adofield->max_length > 0 && 600 $adofield->scale && 601 ($this->type == XMLDB_TYPE_NUMBER || 602 $this->type == XMLDB_TYPE_FLOAT)) { 603 $this->decimals = $adofield->scale; 604 } 605 // Calculate the notnull field 606 if ($adofield->not_null) { 607 $this->notnull = true; 608 } 609 // Calculate the default field 610 if ($adofield->has_default) { 611 $this->default = $adofield->default_value; 612 } 613 // Calculate the sequence field 614 if ($adofield->auto_increment) { 615 $this->sequence = true; 616 } 617 // Some more fields 618 $this->loaded = true; 619 $this->changed = true; 620 } 621 622 /** 623 * Returns the PHP code needed to define one xmldb_field 624 * @param bool $includeprevious 625 * @return string 626 */ 627 public function getPHP($includeprevious=true) { 628 629 $result = ''; 630 631 // The XMLDBTYPE 632 switch ($this->getType()) { 633 case XMLDB_TYPE_INTEGER: 634 $result .= 'XMLDB_TYPE_INTEGER' . ', '; 635 break; 636 case XMLDB_TYPE_NUMBER: 637 $result .= 'XMLDB_TYPE_NUMBER' . ', '; 638 break; 639 case XMLDB_TYPE_FLOAT: 640 $result .= 'XMLDB_TYPE_FLOAT' . ', '; 641 break; 642 case XMLDB_TYPE_CHAR: 643 $result .= 'XMLDB_TYPE_CHAR' . ', '; 644 break; 645 case XMLDB_TYPE_TEXT: 646 $result .= 'XMLDB_TYPE_TEXT' . ', '; 647 break; 648 case XMLDB_TYPE_BINARY: 649 $result .= 'XMLDB_TYPE_BINARY' . ', '; 650 break; 651 case XMLDB_TYPE_DATETIME: 652 $result .= 'XMLDB_TYPE_DATETIME' . ', '; 653 break; 654 case XMLDB_TYPE_TIMESTAMP: 655 $result .= 'XMLDB_TYPE_TIMESTAMP' . ', '; 656 break; 657 } 658 // The length 659 $length = $this->getLength(); 660 $decimals = $this->getDecimals(); 661 if (!empty($length)) { 662 $result .= "'" . $length; 663 if (!empty($decimals)) { 664 $result .= ', ' . $decimals; 665 } 666 $result .= "', "; 667 } else { 668 $result .= 'null, '; 669 } 670 // Unsigned is not used any more since Moodle 2.3 671 $result .= 'null, '; 672 // Not Null 673 $notnull = $this->getNotnull(); 674 if (!empty($notnull)) { 675 $result .= 'XMLDB_NOTNULL' . ', '; 676 } else { 677 $result .= 'null, '; 678 } 679 // Sequence 680 $sequence = $this->getSequence(); 681 if (!empty($sequence)) { 682 $result .= 'XMLDB_SEQUENCE' . ', '; 683 } else { 684 $result .= 'null, '; 685 } 686 // Default 687 $default = $this->getDefault(); 688 if ($default !== null && !$this->getSequence()) { 689 $result .= "'" . $default . "'"; 690 } else { 691 $result .= 'null'; 692 } 693 // Previous (decided by parameter) 694 if ($includeprevious) { 695 $previous = $this->getPrevious(); 696 if (!empty($previous)) { 697 $result .= ", '" . $previous . "'"; 698 } else { 699 $result .= ', null'; 700 } 701 } 702 // Return result 703 return $result; 704 } 705 706 /** 707 * Shows info in a readable format 708 * @return string 709 */ 710 public function readableInfo() { 711 $o = ''; 712 // type 713 $o .= $this->getXMLDBTypeName($this->type); 714 // length 715 if ($this->type == XMLDB_TYPE_INTEGER || 716 $this->type == XMLDB_TYPE_NUMBER || 717 $this->type == XMLDB_TYPE_FLOAT || 718 $this->type == XMLDB_TYPE_CHAR) { 719 if ($this->length) { 720 $o .= ' (' . $this->length; 721 if ($this->type == XMLDB_TYPE_NUMBER || 722 $this->type == XMLDB_TYPE_FLOAT) { 723 if ($this->decimals !== null) { 724 $o .= ', ' . $this->decimals; 725 } 726 } 727 $o .= ')'; 728 } 729 } 730 // not null 731 if ($this->notnull) { 732 $o .= ' not null'; 733 } 734 // default 735 if ($this->default !== null) { 736 $o .= ' default '; 737 if ($this->type == XMLDB_TYPE_CHAR || 738 $this->type == XMLDB_TYPE_TEXT) { 739 $o .= "'" . $this->default . "'"; 740 } else { 741 $o .= $this->default; 742 } 743 } 744 // sequence 745 if ($this->sequence) { 746 $o .= ' auto-numbered'; 747 } 748 749 return $o; 750 } 751 752 /** 753 * Validates the field restrictions. 754 * 755 * The error message should not be localised because it is intended for developers, 756 * end users and admins should never see these problems! 757 * 758 * @param xmldb_table $xmldb_table optional when object is table 759 * @return string null if ok, error message if problem found 760 */ 761 public function validateDefinition(xmldb_table $xmldb_table=null) { 762 if (!$xmldb_table) { 763 return 'Invalid xmldb_field->validateDefinition() call, $xmldb_table is required.'; 764 } 765 766 $name = $this->getName(); 767 if (strlen($name) > self::NAME_MAX_LENGTH) { 768 return 'Invalid field name in table {'.$xmldb_table->getName().'}: field "'.$this->getName().'" name is too long.' 769 .' Limit is '.self::NAME_MAX_LENGTH.' chars.'; 770 } 771 if (!preg_match('/^[a-z][a-z0-9_]*$/', $name)) { 772 return 'Invalid field name in table {'.$xmldb_table->getName().'}: field "'.$this->getName().'" name includes invalid characters.'; 773 } 774 775 switch ($this->getType()) { 776 case XMLDB_TYPE_INTEGER: 777 $length = $this->getLength(); 778 if (!is_number($length) or $length <= 0 or $length > self::INTEGER_MAX_LENGTH) { 779 return 'Invalid field definition in table {'.$xmldb_table->getName().'}: XMLDB_TYPE_INTEGER field "'.$this->getName().'" has invalid length'; 780 } 781 $default = $this->getDefault(); 782 if (!empty($default) and !is_number($default)) { 783 return 'Invalid field definition in table {'.$xmldb_table->getName().'}: XMLDB_TYPE_INTEGER field "'.$this->getName().'" has invalid default'; 784 } 785 break; 786 787 case XMLDB_TYPE_NUMBER: 788 $maxlength = self::NUMBER_MAX_LENGTH; 789 $length = $this->getLength(); 790 if (!is_number($length) or $length <= 0 or $length > $maxlength) { 791 return 'Invalid field definition in table {'.$xmldb_table->getName().'}: XMLDB_TYPE_NUMBER field "'.$this->getName().'" has invalid length'; 792 } 793 $decimals = $this->getDecimals(); 794 $decimals = empty($decimals) ? 0 : $decimals; // fix missing decimals 795 if (!is_number($decimals) or $decimals < 0 or $decimals > $length) { 796 return 'Invalid field definition in table {'.$xmldb_table->getName().'}: XMLDB_TYPE_NUMBER field "'.$this->getName().'" has invalid decimals'; 797 } 798 if ($length - $decimals > self::INTEGER_MAX_LENGTH) { 799 return 'Invalid field definition in table {'.$xmldb_table->getName().'}: XMLDB_TYPE_NUMBER field "'. 800 $this->getName().'" has too big whole number part'; 801 } 802 $default = $this->getDefault(); 803 if (!empty($default) and !is_numeric($default)) { 804 return 'Invalid field definition in table {'.$xmldb_table->getName().'}: XMLDB_TYPE_NUMBER field "'.$this->getName().'" has invalid default'; 805 } 806 break; 807 808 case XMLDB_TYPE_FLOAT: 809 $length = $this->getLength(); 810 $length = empty($length) ? 6 : $length; // weird, it might be better to require something here... 811 if (!is_number($length) or $length <= 0 or $length > self::FLOAT_MAX_LENGTH) { 812 return 'Invalid field definition in table {'.$xmldb_table->getName().'}: XMLDB_TYPE_FLOAT field "'.$this->getName().'" has invalid length'; 813 } 814 $decimals = $this->getDecimals(); 815 $decimals = empty($decimals) ? 0 : $decimals; // fix missing decimals 816 if (!is_number($decimals) or $decimals < 0 or $decimals > $length) { 817 return 'Invalid field definition in table {'.$xmldb_table->getName().'}: XMLDB_TYPE_FLOAT field "'.$this->getName().'" has invalid decimals'; 818 } 819 $default = $this->getDefault(); 820 if (!empty($default) and !is_numeric($default)) { 821 return 'Invalid field definition in table {'.$xmldb_table->getName().'}: XMLDB_TYPE_FLOAT field "'.$this->getName().'" has invalid default'; 822 } 823 break; 824 825 case XMLDB_TYPE_CHAR: 826 if ($this->getLength() > self::CHAR_MAX_LENGTH) { 827 return 'Invalid field definition in table {'.$xmldb_table->getName(). '}: XMLDB_TYPE_CHAR field "'.$this->getName().'" is too long.' 828 .' Limit is '.self::CHAR_MAX_LENGTH.' chars.'; 829 } 830 break; 831 832 case XMLDB_TYPE_TEXT: 833 break; 834 835 case XMLDB_TYPE_BINARY: 836 break; 837 838 case XMLDB_TYPE_DATETIME: 839 break; 840 841 case XMLDB_TYPE_TIMESTAMP: 842 break; 843 } 844 845 return null; 846 } 847} 848