MDL-29313 allow larger char fields
[moodle.git] / lib / xmldb / xmldb_field.php
1 <?php
3 ///////////////////////////////////////////////////////////////////////////
4 //                                                                       //
5 // NOTICE OF COPYRIGHT                                                   //
6 //                                                                       //
7 // Moodle - Modular Object-Oriented Dynamic Learning Environment         //
8 //          http://moodle.com                                            //
9 //                                                                       //
10 // Copyright (C) 1999 onwards Martin Dougiamas     http://dougiamas.com  //
11 //           (C) 2001-3001 Eloy Lafuente (stronk7) http://contiento.com  //
12 //                                                                       //
13 // This program is free software; you can redistribute it and/or modify  //
14 // it under the terms of the GNU General Public License as published by  //
15 // the Free Software Foundation; either version 2 of the License, or     //
16 // (at your option) any later version.                                   //
17 //                                                                       //
18 // This program is distributed in the hope that it will be useful,       //
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of        //
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
21 // GNU General Public License for more details:                          //
22 //                                                                       //
23 //          http://www.gnu.org/copyleft/gpl.html                         //
24 //                                                                       //
25 ///////////////////////////////////////////////////////////////////////////
27 /// This class represent one XMLDB Field
29 class xmldb_field extends xmldb_object {
31     var $type;
32     var $length;
33     var $unsigned;
34     var $notnull;
35     var $default;
36     var $sequence;
37     var $decimals;
39     /**
40      * Note:
41      *  - Oracle: VARCHAR2 has a limit of 4000 bytes
42      *  - SQL Server: NVARCHAR has a limit of 40000 chars
43      *  - MySQL: VARCHAR 65,535 chars
44      *  - PostgreSQL: no limit
45      *
46      * @const maximum length of text field
47      */
48     const CHAR_MAX_LENGTH = 1333;
50     /**
51      * Creates one new xmldb_field
52      */
53     function __construct($name, $type=null, $precision=null, $unsigned=null, $notnull=null, $sequence=null, $default=null, $previous=null) {
54         $this->type = NULL;
55         $this->length = NULL;
56         $this->unsigned = true;
57         $this->notnull = false;
58         $this->default = NULL;
59         $this->sequence = false;
60         $this->decimals = NULL;
61         parent::__construct($name);
62         $this->set_attributes($type, $precision, $unsigned, $notnull, $sequence, $default, $previous);
63     }
65 /// TODO: Delete for 2.1 (deprecated in 2.0).
66 /// Deprecated API starts here
68     function setAttributes($type, $precision=null, $unsigned=null, $notnull=null, $sequence=null, $enum=null, $enumvalues=null, $default=null, $previous=null) {
70         debugging('XMLDBField->setAttributes() has been deprecated in Moodle 2.0. Will be out in Moodle 2.1. Please use xmldb_field->set_attributes() instead.', DEBUG_DEVELOPER);
71         if ($enum) {
72             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.');
73         }
75         return $this->set_attributes($type, $precision, $unsigned, $notnull, $sequence, $default, $previous);
76     }
77 /// Deprecated API ends here
79     /**
80      * Set all the attributes of one xmldb_field
81      *
82      * @param string type XMLDB_TYPE_INTEGER, XMLDB_TYPE_NUMBER, XMLDB_TYPE_CHAR, XMLDB_TYPE_TEXT, XMLDB_TYPE_BINARY
83      * @param string precision length for integers and chars, two-comma separated numbers for numbers and 'small', 'medium', 'big' for texts and binaries
84      * @param string unsigned XMLDB_UNSIGNED or null (or false)
85      * @param string notnull XMLDB_NOTNULL or null (or false)
86      * @param string sequence XMLDB_SEQUENCE or null (or false)
87      * @param string default meaningful default o null (or false)
88      */
89     function set_attributes($type, $precision=null, $unsigned=null, $notnull=null, $sequence=null, $default=null, $previous=null) {
90         $this->type = $type;
91     /// Try to split the precision into length and decimals and apply
92     /// each one as needed
93         $precisionarr = explode(',', $precision);
94         if (isset($precisionarr[0])) {
95             $this->length = trim($precisionarr[0]);
96         }
97         if (isset($precisionarr[1])) {
98             $this->decimals = trim($precisionarr[1]);
99         }
100         $this->precision = $type;
101         $this->unsigned = !empty($unsigned) ? true : false;
102         $this->notnull = !empty($notnull) ? true : false;
103         $this->sequence = !empty($sequence) ? true : false;
104         $this->setDefault($default);
106         $this->previous = $previous;
107     }
109     /**
110      * Get the type
111      */
112     function getType() {
113         return $this->type;
114     }
116     /**
117      * Get the length
118      */
119     function getLength() {
120         return $this->length;
121     }
123     /**
124      * Get the decimals
125      */
126     function getDecimals() {
127         return $this->decimals;
128     }
130     /**
131      * Get the notnull
132      */
133     function getNotNull() {
134         return $this->notnull;
135     }
137     /**
138      * Get the unsigned
139      */
140     function getUnsigned() {
141         return $this->unsigned;
142     }
144     /**
145      * Get the sequence
146      */
147     function getSequence() {
148         return $this->sequence;
149     }
151     /**
152      * Get the default
153      */
154     function getDefault() {
155         return $this->default;
156     }
158     /**
159      * Set the field type
160      */
161     function setType($type) {
162         $this->type = $type;
163     }
165     /**
166      * Set the field length
167      */
168     function setLength($length) {
169         $this->length = $length;
170     }
172     /**
173      * Set the field decimals
174      */
175     function setDecimals($decimals) {
176         $this->decimals = $decimals;
177     }
179     /**
180      * Set the field unsigned
181      */
182     function setUnsigned($unsigned=true) {
183         $this->unsigned = $unsigned;
184     }
186     /**
187      * Set the field notnull
188      */
189     function setNotNull($notnull=true) {
190         $this->notnull = $notnull;
191     }
193     /**
194      * Set the field sequence
195      */
196     function setSequence($sequence=true) {
197         $this->sequence = $sequence;
198     }
200     /**
201      * Set the field default
202      */
203     function setDefault($default) {
204     /// Check, warn and auto-fix '' (empty) defaults for CHAR NOT NULL columns, changing them
205     /// to NULL so XMLDB will apply the proper default
206         if ($this->type == XMLDB_TYPE_CHAR && $this->notnull && $default === '') {
207             $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.";
208             $this->debug($this->errormsg);
209             $default = null;
210         }
211     /// Check, warn and autofix TEXT|BINARY columns having a default clause (only null is allowed)
212         if (($this->type == XMLDB_TYPE_TEXT || $this->type == XMLDB_TYPE_BINARY) && $default !== null) {
213             $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.";
214             $this->debug($this->errormsg);
215             $default = null;
216         }
217         $this->default = $default;
218     }
220     /**
221      * Load data from XML to the table
222      */
223     function arr2xmldb_field($xmlarr) {
225         $result = true;
227     /// Debug the table
228     /// traverse_xmlize($xmlarr);                   //Debug
229     /// print_object ($GLOBALS['traverse_array']);  //Debug
230     /// $GLOBALS['traverse_array']="";              //Debug
232     /// Process table attributes (name, type, length, unsigned,
233     /// notnull, sequence, decimals, comment, previous, next)
234         if (isset($xmlarr['@']['NAME'])) {
235             $this->name = trim($xmlarr['@']['NAME']);
236         } else {
237             $this->errormsg = 'Missing NAME attribute';
238             $this->debug($this->errormsg);
239             $result = false;
240         }
242         if (isset($xmlarr['@']['TYPE'])) {
243         /// Check for valid type
244             $type = $this->getXMLDBFieldType(trim($xmlarr['@']['TYPE']));
245             if ($type) {
246                 $this->type = $type;
247             } else {
248                 $this->errormsg = 'Invalid TYPE attribute';
249                 $this->debug($this->errormsg);
250                 $result = false;
251             }
252         } else {
253             $this->errormsg = 'Missing TYPE attribute';
254             $this->debug($this->errormsg);
255             $result = false;
256         }
258         if (isset($xmlarr['@']['LENGTH'])) {
259             $length = trim($xmlarr['@']['LENGTH']);
260         /// Check for integer values
261             if ($this->type == XMLDB_TYPE_INTEGER ||
262                 $this->type == XMLDB_TYPE_NUMBER ||
263                 $this->type == XMLDB_TYPE_CHAR) {
264                 if (!(is_numeric($length)&&(intval($length)==floatval($length)))) {
265                     $this->errormsg = 'Incorrect LENGTH attribute for int, number or char fields';
266                     $this->debug($this->errormsg);
267                     $result = false;
268                 } else if (!$length) {
269                     $this->errormsg = 'Zero LENGTH attribute';
270                     $this->debug($this->errormsg);
271                     $result = false;
272                 }
273             }
274         /// Check for big, medium, small to be applied to text and binary
275             if ($this->type == XMLDB_TYPE_TEXT ||
276                 $this->type == XMLDB_TYPE_BINARY) {
277                 if (!$length) {
278                     $length == 'big';
279                 }
280                 if ($length != 'big' &&
281                     $length != 'medium' &&
282                     $length != 'small') {
283                     $this->errormsg = 'Incorrect LENGTH attribute for text and binary fields (only big, medium and small allowed)';
284                     $this->debug($this->errormsg);
285                     $result = false;
286                 }
287             }
288         /// Finally, set the length
289             $this->length = $length;
290         }
292         if (isset($xmlarr['@']['UNSIGNED'])) {
293             $unsigned = strtolower(trim($xmlarr['@']['UNSIGNED']));
294             if ($unsigned == 'true') {
295                 $this->unsigned = true;
296             } else if ($unsigned == 'false') {
297                 $this->unsigned = false;
298             } else {
299                 $this->errormsg = 'Incorrect UNSIGNED attribute (true/false allowed)';
300                 $this->debug($this->errormsg);
301                 $result = false;
302             }
303         }
305         if (isset($xmlarr['@']['NOTNULL'])) {
306             $notnull = strtolower(trim($xmlarr['@']['NOTNULL']));
307             if ($notnull == 'true') {
308                 $this->notnull = true;
309             } else if ($notnull == 'false') {
310                 $this->notnull = false;
311             } else {
312                 $this->errormsg = 'Incorrect NOTNULL attribute (true/false allowed)';
313                 $this->debug($this->errormsg);
314                 $result = false;
315             }
316         }
318         if (isset($xmlarr['@']['SEQUENCE'])) {
319             $sequence = strtolower(trim($xmlarr['@']['SEQUENCE']));
320             if ($sequence == 'true') {
321                 $this->sequence = true;
322             } else if ($sequence == 'false') {
323                 $this->sequence = false;
324             } else {
325                 $this->errormsg = 'Incorrect SEQUENCE attribute (true/false allowed)';
326                 $this->debug($this->errormsg);
327                 $result = false;
328             }
329         }
331         if (isset($xmlarr['@']['DEFAULT'])) {
332             $this->setDefault(trim($xmlarr['@']['DEFAULT']));
333         }
335         $decimals = NULL;
336         if (isset($xmlarr['@']['DECIMALS'])) {
337             $decimals = trim($xmlarr['@']['DECIMALS']);
338         /// Check for integer values
339             if ($this->type == XMLDB_TYPE_NUMBER ||
340                 $this->type == XMLDB_TYPE_FLOAT) {
341                 if (!(is_numeric($decimals)&&(intval($decimals)==floatval($decimals)))) {
342                     $this->errormsg = 'Incorrect DECIMALS attribute for number field';
343                     $this->debug($this->errormsg);
344                     $result = false;
345                 } else if ($this->length <= $decimals){
346                     $this->errormsg = 'Incorrect DECIMALS attribute (bigget than length)';
347                     $this->debug($this->errormsg);
348                     $result = false;
349                 }
350             } else {
351                 $this->errormsg = 'Incorrect DECIMALS attribute for non-number field';
352                 $this->debug($this->errormsg);
353                 $result = false;
354             }
355         } else {
356             if ($this->type == XMLDB_TYPE_NUMBER) {
357                 $decimals = 0;
358             }
359         }
360      // Finally, set the decimals
361         if ($this->type == XMLDB_TYPE_NUMBER ||
362             $this->type == XMLDB_TYPE_FLOAT) {
363             $this->decimals = $decimals;
364         }
366         if (isset($xmlarr['@']['COMMENT'])) {
367             $this->comment = trim($xmlarr['@']['COMMENT']);
368         }
370         if (isset($xmlarr['@']['PREVIOUS'])) {
371             $this->previous = trim($xmlarr['@']['PREVIOUS']);
372         }
374         if (isset($xmlarr['@']['NEXT'])) {
375             $this->next = trim($xmlarr['@']['NEXT']);
376         }
378     /// TODO: Drop this check in Moodle 2.1
379     /// Detect if there is old enum information in the XML file
380         if (isset($xmlarr['@']['ENUM']) && isset($xmlarr['@']['ENUMVALUES'])) {
381             $this->hasenums = true;
382             if ($xmlarr['@']['ENUM'] == 'true') {
383                 $this->hasenumsenabled = true;
384             }
385         }
387     /// Set some attributes
388         if ($result) {
389             $this->loaded = true;
390         }
391         $this->calculateHash();
392         return $result;
393     }
395     /**
396      * This function returns the correct XMLDB_TYPE_XXX value for the
397      * string passed as argument
398      */
399     function getXMLDBFieldType($type) {
401         $result = XMLDB_TYPE_INCORRECT;
403         switch (strtolower($type)) {
404             case 'int':
405                 $result = XMLDB_TYPE_INTEGER;
406                 break;
407             case 'number':
408                 $result = XMLDB_TYPE_NUMBER;
409                 break;
410             case 'float':
411                 $result = XMLDB_TYPE_FLOAT;
412                 break;
413             case 'char':
414                 $result = XMLDB_TYPE_CHAR;
415                 break;
416             case 'text':
417                 $result = XMLDB_TYPE_TEXT;
418                 break;
419             case 'binary':
420                 $result = XMLDB_TYPE_BINARY;
421                 break;
422             case 'datetime':
423                 $result = XMLDB_TYPE_DATETIME;
424                 break;
425         }
426     /// Return the normalized XMLDB_TYPE
427         return $result;
428     }
430     /**
431      * This function returns the correct name value for the
432      * XMLDB_TYPE_XXX passed as argument
433      */
434     function getXMLDBTypeName($type) {
436         $result = "";
438         switch (strtolower($type)) {
439             case XMLDB_TYPE_INTEGER:
440                 $result = 'int';
441                 break;
442             case XMLDB_TYPE_NUMBER:
443                 $result = 'number';
444                 break;
445             case XMLDB_TYPE_FLOAT:
446                 $result = 'float';
447                 break;
448             case XMLDB_TYPE_CHAR:
449                 $result = 'char';
450                 break;
451             case XMLDB_TYPE_TEXT:
452                 $result = 'text';
453                 break;
454             case XMLDB_TYPE_BINARY:
455                 $result = 'binary';
456                 break;
457             case XMLDB_TYPE_DATETIME:
458                 $result = 'datetime';
459                 break;
460         }
461     /// Return the normalized name
462         return $result;
463     }
465     /**
466      * This function calculate and set the hash of one xmldb_field
467      */
468      function calculateHash($recursive = false) {
469         if (!$this->loaded) {
470             $this->hash = NULL;
471         } else {
472             $key = $this->name . $this->type . $this->length .
473                    $this->unsigned . $this->notnull . $this->sequence .
474                    $this->decimals . $this->comment;
475             $this->hash = md5($key);
476         }
477     }
479     /**
480      *This function will output the XML text for one field
481      */
482     function xmlOutput() {
483         $o = '';
484         $o.= '        <FIELD NAME="' . $this->name . '"';
485         $o.= ' TYPE="' . $this->getXMLDBTypeName($this->type) . '"';
486         if ($this->length) {
487             $o.= ' LENGTH="' . $this->length . '"';
488         }
489         if ($this->notnull) {
490             $notnull = 'true';
491         } else {
492             $notnull = 'false';
493         }
494         $o.= ' NOTNULL="' . $notnull . '"';
495         if ($this->type == XMLDB_TYPE_INTEGER ||
496             $this->type == XMLDB_TYPE_NUMBER ||
497             $this->type == XMLDB_TYPE_FLOAT) {
498             if ($this->unsigned) {
499                 $unsigned = 'true';
500             } else {
501                 $unsigned = 'false';
502             }
503             $o.= ' UNSIGNED="' . $unsigned . '"';
504         }
505         if (!$this->sequence && $this->default !== NULL) {
506             $o.= ' DEFAULT="' . $this->default . '"';
507         }
508         if ($this->sequence) {
509             $sequence = 'true';
510         } else {
511             $sequence = 'false';
512         }
513         $o.= ' SEQUENCE="' . $sequence . '"';
514         if ($this->decimals !== NULL) {
515             $o.= ' DECIMALS="' . $this->decimals . '"';
516         }
517         if ($this->comment) {
518             $o.= ' COMMENT="' . htmlspecialchars($this->comment) . '"';
519         }
520         if ($this->previous) {
521             $o.= ' PREVIOUS="' . $this->previous . '"';
522         }
523         if ($this->next) {
524             $o.= ' NEXT="' . $this->next . '"';
525         }
526         $o.= '/>' . "\n";
528         return $o;
529     }
531     /**
532      * This function will set all the attributes of the xmldb_field object
533      * based on information passed in one ADOField
534      */
535     function setFromADOField($adofield) {
537     /// Calculate the XMLDB_TYPE
538         switch (strtolower($adofield->type)) {
539             case 'int':
540             case 'tinyint':
541             case 'smallint':
542             case 'bigint':
543             case 'integer':
544                 $this->type = XMLDB_TYPE_INTEGER;
545                 break;
546             case 'number':
547             case 'decimal':
548             case 'dec':
549             case 'numeric':
550                 $this->type = XMLDB_TYPE_NUMBER;
551                 break;
552             case 'float':
553             case 'double':
554                 $this->type = XMLDB_TYPE_FLOAT;
555                 break;
556             case 'char':
557             case 'varchar':
558             case 'enum':
559                 $this->type = XMLDB_TYPE_CHAR;
560                 break;
561             case 'text':
562             case 'tinytext':
563             case 'mediumtext':
564             case 'longtext':
565                 $this->type = XMLDB_TYPE_TEXT;
566                 break;
567             case 'blob':
568             case 'tinyblob':
569             case 'mediumblob':
570             case 'longblob':
571                 $this->type = XMLDB_TYPE_BINARY;
572                 break;
573             case 'datetime':
574             case 'timestamp':
575                 $this->type = XMLDB_TYPE_DATETIME;
576                 break;
577             default:
578                 $this->type = XMLDB_TYPE_TEXT;
579         }
580     /// Calculate the length of the field
581         if ($adofield->max_length > 0 &&
582                ($this->type == XMLDB_TYPE_INTEGER ||
583                 $this->type == XMLDB_TYPE_NUMBER  ||
584                 $this->type == XMLDB_TYPE_FLOAT   ||
585                 $this->type == XMLDB_TYPE_CHAR)) {
586             $this->length = $adofield->max_length;
587         }
588         if ($this->type == XMLDB_TYPE_TEXT) {
589             switch (strtolower($adofield->type)) {
590                 case 'tinytext':
591                 case 'text':
592                     $this->length = 'small';
593                     break;
594                 case 'mediumtext':
595                     $this->length = 'medium';
596                     break;
597                 case 'longtext':
598                     $this->length = 'big';
599                     break;
600                 default:
601                     $this->length = 'small';
602             }
603         }
604         if ($this->type == XMLDB_TYPE_BINARY) {
605             switch (strtolower($adofield->type)) {
606                 case 'tinyblob':
607                 case 'blob':
608                     $this->length = 'small';
609                     break;
610                 case 'mediumblob':
611                     $this->length = 'medium';
612                     break;
613                 case 'longblob':
614                     $this->length = 'big';
615                     break;
616                 default:
617                     $this->length = 'small';
618             }
619         }
620     /// Calculate the decimals of the field
621         if ($adofield->max_length > 0 &&
622             $adofield->scale &&
623                ($this->type == XMLDB_TYPE_NUMBER ||
624                 $this->type == XMLDB_TYPE_FLOAT)) {
625             $this->decimals = $adofield->scale;
626         }
627     /// Calculate the unsigned field
628         if ($adofield->unsigned &&
629                ($this->type == XMLDB_TYPE_INTEGER ||
630                 $this->type == XMLDB_TYPE_NUMBER  ||
631                 $this->type == XMLDB_TYPE_FLOAT)) {
632             $this->unsigned = true;
633         }
634     /// Calculate the notnull field
635         if ($adofield->not_null) {
636             $this->notnull = true;
637         }
638     /// Calculate the default field
639         if ($adofield->has_default) {
640             $this->default = $adofield->default_value;
641         }
642     /// Calculate the sequence field
643         if ($adofield->auto_increment) {
644             $this->sequence = true;
645         /// Sequence fields are always unsigned
646             $this->unsigned = true;
647         }
648     /// Some more fields
649         $this->loaded = true;
650         $this->changed = true;
651     }
653     /**
654      * Returns the PHP code needed to define one xmldb_field
655      */
656     function getPHP($includeprevious=true) {
658         $result = '';
660     /// The XMLDBTYPE
661         switch ($this->getType()) {
662             case XMLDB_TYPE_INTEGER:
663                 $result .= 'XMLDB_TYPE_INTEGER' . ', ';
664                 break;
665             case XMLDB_TYPE_NUMBER:
666                 $result .= 'XMLDB_TYPE_NUMBER' . ', ';
667                 break;
668             case XMLDB_TYPE_FLOAT:
669                 $result .= 'XMLDB_TYPE_FLOAT' . ', ';
670                 break;
671             case XMLDB_TYPE_CHAR:
672                 $result .= 'XMLDB_TYPE_CHAR' . ', ';
673                 break;
674             case XMLDB_TYPE_TEXT:
675                 $result .= 'XMLDB_TYPE_TEXT' . ', ';
676                 break;
677             case XMLDB_TYPE_BINARY:
678                 $result .= 'XMLDB_TYPE_BINARY' . ', ';
679                 break;
680             case XMLDB_TYPE_DATETIME:
681                 $result .= 'XMLDB_TYPE_DATETIME' . ', ';
682                 break;
683             case XMLDB_TYPE_TIMESTAMP:
684                 $result .= 'XMLDB_TYPE_TIMESTAMP' . ', ';
685                 break;
686         }
687     /// The length
688         $length = $this->getLength();
689         $decimals = $this->getDecimals();
690         if (!empty($length)) {
691             $result .= "'" . $length;
692             if (!empty($decimals)) {
693                 $result .= ', ' . $decimals;
694             }
695             $result .= "', ";
696         } else {
697             $result .= 'null, ';
698         }
699     /// Unsigned (only applicable to numbers)
700         $unsigned = $this->getUnsigned();
701         if (!empty($unsigned) &&
702            ($this->getType() == XMLDB_TYPE_INTEGER || $this->getType() == XMLDB_TYPE_NUMBER || $this->getType() == XMLDB_TYPE_FLOAT)) {
703             $result .= 'XMLDB_UNSIGNED' . ', ';
704         } else {
705             $result .= 'null, ';
706         }
707     /// Not Null
708         $notnull = $this->getNotnull();
709         if (!empty($notnull)) {
710             $result .= 'XMLDB_NOTNULL' . ', ';
711         } else {
712             $result .= 'null, ';
713         }
714     /// Sequence
715         $sequence = $this->getSequence();
716         if (!empty($sequence)) {
717             $result .= 'XMLDB_SEQUENCE' . ', ';
718         } else {
719             $result .= 'null, ';
720         }
721     /// Default
722         $default =  $this->getDefault();
723         if ($default !== null && !$this->getSequence()) {
724             $result .= "'" . $default . "'";
725         } else {
726             $result .= 'null';
727         }
728     /// Previous (decided by parameter)
729         if ($includeprevious) {
730             $previous = $this->getPrevious();
731             if (!empty($previous)) {
732                 $result .= ", '" . $previous . "'";
733             } else {
734                 $result .= ', null';
735             }
736         }
737     /// Return result
738         return $result;
739     }
741     /**
742      * Shows info in a readable format
743      */
744     function readableInfo() {
745         $o = '';
746     /// type
747         $o .= $this->getXMLDBTypeName($this->type);
748     /// length
749         if ($this->type == XMLDB_TYPE_INTEGER ||
750             $this->type == XMLDB_TYPE_NUMBER  ||
751             $this->type == XMLDB_TYPE_FLOAT   ||
752             $this->type == XMLDB_TYPE_CHAR) {
753             if ($this->length) {
754                 $o .= ' (' . $this->length;
755                 if ($this->type == XMLDB_TYPE_NUMBER  ||
756                     $this->type == XMLDB_TYPE_FLOAT) {
757                     if ($this->decimals !== NULL) {
758                         $o .= ', ' . $this->decimals;
759                     }
760                 }
761                 $o .= ')';
762             }
763         }
764         if ($this->type == XMLDB_TYPE_TEXT ||
765             $this->type == XMLDB_TYPE_BINARY) {
766                 $o .= ' (' . $this->length . ')';
767         }
768     /// unsigned
769         if ($this->type == XMLDB_TYPE_INTEGER ||
770             $this->type == XMLDB_TYPE_NUMBER ||
771             $this->type == XMLDB_TYPE_FLOAT) {
772             if ($this->unsigned) {
773                 $o .= ' unsigned';
774             } else {
775                 $o .= ' signed';
776             }
777         }
778     /// not null
779         if ($this->notnull) {
780             $o .= ' not null';
781         }
782     /// default
783         if ($this->default !== NULL) {
784             $o .= ' default ';
785             if ($this->type == XMLDB_TYPE_CHAR ||
786                 $this->type == XMLDB_TYPE_TEXT) {
787                     $o .= "'" . $this->default . "'";
788             } else {
789                 $o .= $this->default;
790             }
791         }
792     /// sequence
793         if ($this->sequence) {
794             $o .= ' auto-numbered';
795         }
797         return $o;
798     }
800     /**
801      * Validates the field restrictions.
802      *
803      * The error message should not be localised because it is intended for developers,
804      * end users and admins should never see these problems!
805      *
806      * @param xmldb_table $xmldb_table optional when object is table
807      * @return string null if ok, error message if problem found
808      */
809     function validateDefinition(xmldb_table $xmldb_table=null) {
810         if (!$xmldb_table) {
811             return 'Invalid xmldb_field->validateDefinition() call, $xmldb_table si required.';
812         }
814         switch ($this->getType()) {
815             case XMLDB_TYPE_INTEGER:
816             break;
818             case XMLDB_TYPE_NUMBER:
819             break;
821             case XMLDB_TYPE_FLOAT:
822             break;
824             case XMLDB_TYPE_CHAR:
825                 if ($this->getLength() > self::CHAR_MAX_LENGTH) {
826                     return 'Invalid field definition in table {'.$xmldb_table->getName(). '}: XMLDB_TYPE_CHAR field "'.$this->getName().'" is too long.'
827                            .' Limit is '.self::CHAR_MAX_LENGTH.' chars.';
828                 }
829             break;
831             case XMLDB_TYPE_TEXT:
832             break;
834             case XMLDB_TYPE_BINARY:
835             break;
837             case XMLDB_TYPE_DATETIME:
838             break;
840             case XMLDB_TYPE_TIMESTAMP:
841             break;
842         }
844         return null;
845     }
848 /// TODO: Delete for 2.1 (deprecated in 2.0).
849 /// Deprecated API starts here
850 class XMLDBField extends xmldb_field {
852     function __construct($name) {
853         parent::__construct($name);
854     }
857 /// Deprecated API ends here