all static functions in enrolment_plugin_authorize moved to localfuncs.php. So, no...
[moodle.git] / lib / xmldb / classes / XMLDBField.class.php
CommitLineData
8165877a 1<?php // $Id$
2
3///////////////////////////////////////////////////////////////////////////
4// //
5// NOTICE OF COPYRIGHT //
6// //
7// Moodle - Modular Object-Oriented Dynamic Learning Environment //
8// http://moodle.com //
9// //
10// Copyright (C) 2001-3001 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///////////////////////////////////////////////////////////////////////////
26
27/// This class represent one XMLDB Field
28
29class XMLDBField extends XMLDBObject {
30
31 var $type;
32 var $length;
33 var $unsigned;
34 var $notnull;
35 var $default;
36 var $sequence;
37 var $enum;
38 var $enumvalues;
39 var $decimals;
40
41 /**
42 * Creates one new XMLDBField
43 */
44 function XMLDBField($name) {
45 parent::XMLDBObject($name);
46 $this->type = NULL;
47 $this->length = NULL;
48 $this->unsigned = false;
49 $this->notnull = false;
50 $this->default = NULL;
51 $this->sequence = false;
52 $this->enum = false;
53 $this->enumvalues = NULL;
54 $this->decimals = NULL;
55 }
56
76fd4736 57 /**
58 * Set all the attributes of one XMLDBField
59 *
60 * @param string type XMLDB_TYPE_INTEGER, XMLDB_TYPE_NUMBER, XMLDB_TYPE_CHAR, XMLDB_TYPE_TEXT, XMLDB_TYPE_BINARY
61 * @param string precision length for integers and chars, two-comma separated numbers for numbers and 'small', 'medium', 'big' for texts and binaries
62 * @param string unsigned XMLDB_UNSIGNED or null (or false)
63 * @param string notnull XMLDB_NOTNULL or null (or false)
64 * @param string sequence XMLDB_SEQUENCE or null (or false)
65 * @param string enum XMLDB_ENUM or null (or false)
66 * @param array enumvalues an array of possible values if XMLDB_ENUM is set
67 * @param string default meaningful default o null (or false)
68 */
69 function setAttributes($type, $precision=null, $unsigned=null, $notnull=null, $sequence=null, $enum=null, $enumvalues=null, $default=null, $previous=null) {
70 $this->type = $type;
71 /// Try to split the precision into length and decimals and apply
72 /// each one as needed
73 $precisionarr = explode(',', $precision);
74 if (isset($precisionarr[0])) {
75 $this->length = trim($precisionarr[0]);
76 }
77 if (isset($precisionarr[1])) {
78 $this->decimals = trim($precisionarr[1]);
79 }
80 $this->precision = $type;
81 $this->unsigned = !empty($unsigned) ? true : false;
82 $this->notnull = !empty($notnull) ? true : false;
83 $this->sequence = !empty($secuence) ? true : false;
84 $this->enum = !empty($enum) ? true : false;
85 /// Accept both quoted and non-quoted vales (quoting them)a
86 if (is_array($enumvalues)) {
87 $this->enumvalues = array();
88 foreach ($enumvalues as $value) {
89 /// trim each value quotes
90 $value = trim($value, "'");
91 /// add them back
92 $valus = "'" . $value . "'";
93 $this->enumvalues[] = $value;
94 }
95 }
96 $this->default = $default;
97 }
98
8165877a 99 /**
100 * Get the type
101 */
102 function getType() {
103 return $this->type;
104 }
105
106 /**
107 * Get the length
108 */
109 function getLength() {
110 return $this->length;
111 }
112
113 /**
114 * Get the decimals
115 */
116 function getDecimals() {
117 return $this->decimals;
118 }
119
120 /**
121 * Get the notnull
122 */
123 function getNotNull() {
124 return $this->notnull;
125 }
126
127 /**
128 * Get the unsigned
129 */
130 function getUnsigned() {
131 return $this->unsigned;
132 }
133
134 /**
135 * Get the sequence
136 */
137 function getSequence() {
138 return $this->sequence;
139 }
140
141 /**
142 * Get the enum
143 */
144 function getEnum() {
145 return $this->enum;
146 }
147
148 /**
149 * Get the enumvalues
150 */
151 function getEnumValues() {
152 return $this->enumvalues;
153 }
154
155 /**
156 * Get the default
157 */
158 function getDefault() {
159 return $this->default;
160 }
161
162 /**
163 * Set the field type
164 */
165 function setType($type) {
166 $this->type = $type;
167 }
168
169 /**
170 * Set the field length
171 */
172 function setLength($length) {
173 $this->length = $length;
174 }
175
176 /**
177 * Set the field decimals
178 */
179 function setDecimals($decimals) {
180 $this->decimals = $decimals;
181 }
182
183 /**
184 * Set the field unsigned
185 */
186 function setUnsigned($unsigned=true) {
187 $this->unsigned = $unsigned;
188 }
189
190 /**
191 * Set the field notnull
192 */
193 function setNotNull($notnull=true) {
194 $this->notnull = $notnull;
195 }
196
197 /**
198 * Set the field sequence
199 */
200 function setSequence($sequence=true) {
201 $this->sequence = $sequence;
202 }
203
204 /**
205 * Set the field enum
206 */
207 function setEnum($enum=true) {
208 $this->enum = $enum;
209 }
210
211 /**
212 * Set the field enumvalues
213 */
214 function setEnumValues($enumvalues) {
215 $this->enumvalues = $enumvalues;
216 }
217
218 /**
219 * Set the field default
220 */
221 function setDefault($default) {
222 $this->default = $default;
223 }
224
225 /**
226 * Load data from XML to the table
227 */
228 function arr2XMLDBField($xmlarr) {
229
230 $result = true;
231
232 /// Debug the table
233 /// traverse_xmlize($xmlarr); //Debug
234 /// print_object ($GLOBALS['traverse_array']); //Debug
235 /// $GLOBALS['traverse_array']=""; //Debug
236
237 /// Process table attributes (name, type, length, unsigned,
238 /// notnull, sequence, enum, enumvalues, decimals, comment,
239 /// previous, next)
240 if (isset($xmlarr['@']['NAME'])) {
241 $this->name = trim($xmlarr['@']['NAME']);
242 } else {
243 $this->errormsg = 'Missing NAME attribute';
244 $result = false;
245 }
246
247 if (isset($xmlarr['@']['TYPE'])) {
248 /// Check for valid type
249 $type = $this->getXMLDBFieldType(trim($xmlarr['@']['TYPE']));
250 if ($type) {
251 $this->type = $type;
252 } else {
253 $this->errormsg = 'Invalid TYPE attribute';
254 $result = false;
255 }
256 } else {
257 $this->errormsg = 'Missing TYPE attribute';
258 $result = false;
259 }
260
261 if (isset($xmlarr['@']['LENGTH'])) {
262 $length = trim($xmlarr['@']['LENGTH']);
263 /// Check for integer values
264 if ($this->type == XMLDB_TYPE_INTEGER ||
265 $this->type == XMLDB_TYPE_NUMBER ||
266 $this->type == XMLDB_TYPE_CHAR) {
267 if (!(is_numeric($length)&&(intval($length)==floatval($length)))) {
268 $this->errormsg = 'Incorrect LENGTH attribute for int, number or char fields';
269 $result = false;
270 } else if (!$length) {
271 $this->errormsg = 'Zero LENGTH attribute';
272 $result = false;
273 }
274 }
275 /// Check for big, medium, small to be applied to text and binary
276 if ($this->type == XMLDB_TYPE_TEXT ||
277 $this->type == XMLDB_TYPE_BINARY) {
278 if (!$length) {
279 $length == 'big';
280 }
281 if ($length != 'big' &&
282 $length != 'medium' &&
283 $length != 'small') {
284 $this->errormsg = 'Incorrect LENGTH attribute for text and binary fields (only big, medium and small allowed)';
285 $result = false;
286 }
287 }
288 /// Finally, set the length
289 $this->length = $length;
290 }
291
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 $result = false;
301 }
302 }
303
304 if (isset($xmlarr['@']['NOTNULL'])) {
305 $notnull = strtolower(trim($xmlarr['@']['NOTNULL']));
306 if ($notnull == 'true') {
307 $this->notnull = true;
308 } else if ($notnull == 'false') {
309 $this->notnull = false;
310 } else {
311 $this->errormsg = 'Incorrect NOTNULL attribute (true/false allowed)';
312 $result = false;
313 }
314 }
315
316 if (isset($xmlarr['@']['SEQUENCE'])) {
317 $sequence = strtolower(trim($xmlarr['@']['SEQUENCE']));
318 if ($sequence == 'true') {
319 $this->sequence = true;
320 } else if ($sequence == 'false') {
321 $this->sequence = false;
322 } else {
323 $this->errormsg = 'Incorrect SEQUENCE attribute (true/false allowed)';
324 $result = false;
325 }
326 }
327
328 if (isset($xmlarr['@']['DEFAULT'])) {
329 $this->default = trim($xmlarr['@']['DEFAULT']);
330 }
331
332 if (isset($xmlarr['@']['ENUM'])) {
333 $enum = strtolower(trim($xmlarr['@']['ENUM']));
334 if ($enum == 'true') {
335 $this->enum = true;
336 } else if ($enum == 'false') {
337 $this->enum = false;
338 } else {
339 $this->errormsg = 'Incorrect ENUM attribute (true/false allowed)';
340 $result = false;
341 }
342 }
343
344 if (isset($xmlarr['@']['ENUMVALUES'])) {
345 $enumvalues = strtolower(trim($xmlarr['@']['ENUMVALUES']));
346 if (!$this->enum) {
347 $this->errormsg = 'Wrong ENUMVALUES attribute (not ENUM)';
348 $result = false;
349 $this->enumvalues = $enumvalues;
350 } else {
351 /// Check we have a valid list (comma separated of quoted values)
352 $enumarr = explode(',',$enumvalues);
353 if ($enumarr) {
354 foreach ($enumarr as $key => $enumelement) {
355 /// Clear some spaces
356 $enumarr[$key] = trim($enumelement);
357 $enumelement = trim($enumelement);
358 /// Skip if under error
359 if (!$result) {
360 continue;
361 }
362 /// Look for quoted strings
363 if (substr($enumelement, 0, 1) != "'" ||
364 substr($enumelement, -1, 1) != "'") {
365 $this->errormsg = 'Incorrect ENUMVALUES attribute (some value is not properly quoted)';
366 $result = false;
367 }
368 }
369 } else {
370 $this->errormsg = 'Incorrect ENUMVALUES attribute (comma separated of quoted values)';
371 $result = false;
372 }
373 }
374 } else if ($this->enum) {
375 $this->errormsg = 'Incorrect ENUMVALUES attribute (field is not declared as ENUM)';
376 $result = false;
377 }
378 /// Finally, set the value
379 if ($this->enum) {
380 $this->enumvalues = $enumarr;
381 }
382
383 $decimals = NULL;
384 if (isset($xmlarr['@']['DECIMALS'])) {
385 $decimals = trim($xmlarr['@']['DECIMALS']);
386 /// Check for integer values
387 if ($this->type == XMLDB_TYPE_NUMBER ||
388 $this->type == XMLDB_TYPE_FLOAT) {
389 if (!(is_numeric($decimals)&&(intval($decimals)==floatval($decimals)))) {
390 $this->errormsg = 'Incorrect DECIMALS attribute for number field';
391 $result = false;
392 } else if ($this->length <= $decimals){
393 $this->errormsg = 'Incorrect DECIMALS attribute (bigget than length)';
394 $result = false;
395 }
396 } else {
397 $this->errormsg = 'Incorrect DECIMALS attribute for non-number field';
398 $result = false;
399 }
400 } else {
401 if ($this->type == XMLDB_TYPE_NUMBER) {
402 $decimals = 0;
403 }
404 }
405 // Finally, set the decimals
406 if ($this->type == XMLDB_TYPE_NUMBER ||
407 $this->type == XMLDB_TYPE_FLOAT) {
408 $this->decimals = $decimals;
409 }
410
411 if (isset($xmlarr['@']['COMMENT'])) {
412 $this->comment = trim($xmlarr['@']['COMMENT']);
413 }
414
415 if (isset($xmlarr['@']['PREVIOUS'])) {
416 $this->previous = trim($xmlarr['@']['PREVIOUS']);
417 }
418
419 if (isset($xmlarr['@']['NEXT'])) {
420 $this->next = trim($xmlarr['@']['NEXT']);
421 }
422
423 /// Set some attributes
424 if ($result) {
425 $this->loaded = true;
426 }
427 $this->calculateHash();
428 return $result;
429 }
430
431 /**
432 * This function returns the correct XMLDB_TYPE_XXX value for the
433 * string passed as argument
434 */
435 function getXMLDBFieldType($type) {
436
437 $result = XMLDB_TYPE_INCORRECT;
438
439 switch (strtolower($type)) {
440 case 'int':
441 $result = XMLDB_TYPE_INTEGER;
442 break;
443 case 'number':
444 $result = XMLDB_TYPE_NUMBER;
445 break;
446 case 'float':
447 $result = XMLDB_TYPE_FLOAT;
448 break;
449 case 'char':
450 $result = XMLDB_TYPE_CHAR;
451 break;
452 case 'text':
453 $result = XMLDB_TYPE_TEXT;
454 break;
455 case 'binary':
456 $result = XMLDB_TYPE_BINARY;
457 break;
458 case 'datetime':
459 $result = XMLDB_TYPE_DATETIME;
460 break;
461 }
462 /// Return the normalized XMLDB_TYPE
463 return $result;
464 }
465
466 /**
467 * This function returns the correct name value for the
468 * XMLDB_TYPE_XXX passed as argument
469 */
470 function getXMLDBTypeName($type) {
471
472 $result = "";
473
474 switch (strtolower($type)) {
475 case XMLDB_TYPE_INTEGER:
476 $result = 'int';
477 break;
478 case XMLDB_TYPE_NUMBER:
479 $result = 'number';
480 break;
481 case XMLDB_TYPE_FLOAT:
482 $result = 'float';
483 break;
484 case XMLDB_TYPE_CHAR:
485 $result = 'char';
486 break;
487 case XMLDB_TYPE_TEXT:
488 $result = 'text';
489 break;
490 case XMLDB_TYPE_BINARY:
491 $result = 'binary';
492 break;
493 case XMLDB_TYPE_DATETIME:
494 $result = 'datetime';
495 break;
496 }
497 /// Return the normalized name
498 return $result;
499 }
500
501 /**
502 * This function calculate and set the hash of one XMLDBField
503 */
504 function calculateHash($recursive = false) {
505 if (!$this->loaded) {
506 $this->hash = NULL;
507 } else {
508 $key = $this->name . $this->type . $this->length .
509 $this->unsigned . $this->notnull . $this->sequence .
510 $this->decimals . $this->comment;
511 if ($this->enum) {
512 $key .= implode(', ',$this->enumvalues);
513 }
514 $this->hash = md5($key);
515 }
516 }
517
518 /**
519 *This function will output the XML text for one field
520 */
521 function xmlOutput() {
522 $o = '';
523 $o.= ' <FIELD NAME="' . $this->name . '"';
524 $o.= ' TYPE="' . $this->getXMLDBTypeName($this->type) . '"';
525 if ($this->length) {
526 $o.= ' LENGTH="' . $this->length . '"';
527 }
528 if ($this->notnull) {
529 $notnull = 'true';
530 } else {
531 $notnull = 'false';
532 }
533 $o.= ' NOTNULL="' . $notnull . '"';
534 if ($this->unsigned) {
535 $unsigned = 'true';
536 } else {
537 $unsigned = 'false';
538 }
539 if ($this->type == XMLDB_TYPE_INTEGER ||
540 $this->type == XMLDB_TYPE_NUMBER ||
541 $this->type == XMLDB_TYPE_FLOAT) {
542 if ($this->unsigned) {
543 $unsigned = 'true';
544 } else {
545 $unsigned = 'false';
546 }
547 $o.= ' UNSIGNED="' . $unsigned . '"';
548 }
549 if (!$this->sequence && $this->default !== NULL) {
550 $o.= ' DEFAULT="' . $this->default . '"';
551 }
552 if ($this->sequence) {
553 $sequence = 'true';
554 } else {
555 $sequence = 'false';
556 }
557 $o.= ' SEQUENCE="' . $sequence . '"';
558 if ($this->enum) {
559 $enum = 'true';
560 } else {
561 $enum = 'false';
562 }
563 $o.= ' ENUM="' . $enum . '"';
564 if ($this->enum) {
565 $o.= ' ENUMVALUES="' . implode(', ', $this->enumvalues) . '"';
566 }
567 if ($this->decimals !== NULL) {
568 $o.= ' DECIMALS="' . $this->decimals . '"';
569 }
570 if ($this->comment) {
571 $o.= ' COMMENT="' . htmlspecialchars($this->comment) . '"';
572 }
573 if ($this->previous) {
574 $o.= ' PREVIOUS="' . $this->previous . '"';
575 }
576 if ($this->next) {
577 $o.= ' NEXT="' . $this->next . '"';
578 }
579 $o.= '/>' . "\n";
580
581 return $o;
582 }
583
584 /**
585 * This function will set all the attributes of the XMLDBField object
586 * based on information passed in one ADOField
587 */
588 function setFromADOField($adofield) {
589
590 /// Calculate the XMLDB_TYPE
591 switch (strtolower($adofield->type)) {
592 case 'int':
593 case 'tinyint':
594 case 'smallint':
595 case 'bigint':
596 case 'integer':
597 $this->type = XMLDB_TYPE_INTEGER;
598 break;
599 case 'number':
600 case 'decimal':
601 case 'dec':
602 case 'numeric':
603 $this->type = XMLDB_TYPE_NUMBER;
604 break;
605 case 'float':
606 case 'double':
607 $this->type = XMLDB_TYPE_FLOAT;
608 break;
609 case 'char':
610 case 'varchar':
611 case 'enum':
612 $this->type = XMLDB_TYPE_CHAR;
613 break;
614 case 'text':
615 case 'tinytext':
616 case 'mediumtext':
617 case 'longtext':
618 $this->type = XMLDB_TYPE_TEXT;
619 break;
620 case 'blob':
621 case 'tinyblob':
622 case 'mediumblob':
623 case 'longblob':
624 $this->type = XMLDB_TYPE_BINARY;
625 break;
626 case 'datetime':
627 case 'timestamp':
628 $this->type = XMLDB_TYPE_DATETIME;
629 break;
630 default:
631 $this->type = XMLDB_TYPE_TEXT;
632 }
633 /// Calculate the length of the field
634 if ($adofield->max_length > 0 &&
635 ($this->type == XMLDB_TYPE_INTEGER ||
636 $this->type == XMLDB_TYPE_NUMBER ||
637 $this->type == XMLDB_TYPE_FLOAT ||
638 $this->type == XMLDB_TYPE_CHAR)) {
639 $this->length = $adofield->max_length;
640 }
641 if ($this->type == XMLDB_TYPE_TEXT) {
642 switch (strtolower($adofield->type)) {
643 case 'tinytext':
644 case 'text':
645 $this->length = 'small';
646 break;
647 case 'mediumtext':
648 $this->length = 'medium';
649 break;
650 case 'longtext':
651 $this->length = 'big';
652 break;
653 default:
654 $this->length = 'small';
655 }
656 }
657 if ($this->type == XMLDB_TYPE_BINARY) {
658 switch (strtolower($adofield->type)) {
659 case 'tinyblob':
660 case 'blob':
661 $this->length = 'small';
662 break;
663 case 'mediumblob':
664 $this->length = 'medium';
665 break;
666 case 'longblob':
667 $this->length = 'big';
668 break;
669 default:
670 $this->length = 'small';
671 }
672 }
673 /// Calculate the decimals of the field
674 if ($adofield->max_length > 0 &&
675 $adofield->scale &&
676 ($this->type == XMLDB_TYPE_NUMBER ||
677 $this->type == XMLDB_TYPE_FLOAT)) {
678 $this->decimals = $adofield->scale;
679 }
680 /// Calculate the unsigned field
681 if ($adofield->unsigned &&
682 ($this->type == XMLDB_TYPE_INTEGER ||
683 $this->type == XMLDB_TYPE_NUMBER ||
684 $this->type == XMLDB_TYPE_FLOAT)) {
685 $this->unsigned = true;
686 }
687 /// Calculate the notnull field
688 if ($adofield->not_null) {
689 $this->notnull = true;
690 }
691 /// Calculate the default field
692 if ($adofield->has_default) {
693 $this->default = $adofield->default_value;
694 }
695 /// Calculate the sequence field
696 if ($adofield->auto_increment) {
697 $this->sequence = true;
698 /// Sequence fields are always unsigned
699 $this->unsigned = true;
700 }
701 /// Calculate the enum and enumvalues field
702 if ($adofield->type == 'enum') {
703 $this->enum = true;
704 $this->enumvalues = $adofield->enums;
705 }
706 /// Some more fields
707 $this->loaded = true;
708 $this->changed = true;
709 }
710
711 /**
712 * Shows info in a readable format
713 */
714 function readableInfo() {
715 $o = '';
716 /// type
717 $o .= $this->getXMLDBTypeName($this->type);
718 /// length
719 if ($this->type == XMLDB_TYPE_INTEGER ||
720 $this->type == XMLDB_TYPE_NUMBER ||
721 $this->type == XMLDB_TYPE_FLOAT ||
722 $this->type == XMLDB_TYPE_CHAR) {
723 if ($this->length) {
724 $o .= ' (' . $this->length;
725 if ($this->type == XMLDB_TYPE_NUMBER ||
726 $this->type == XMLDB_TYPE_FLOAT) {
727 if ($this->decimals !== NULL) {
728 $o .= ', ' . $this->decimals;
729 }
730 }
731 $o .= ')';
732 }
733 }
734 if ($this->type == XMLDB_TYPE_TEXT ||
735 $this->type == XMLDB_TYPE_BINARY) {
736 $o .= ' (' . $this->length . ')';
737 }
738 /// enum
739 if ($this->enum) {
740 $o .= ' enum(' . implode(', ', $this->enumvalues) . ')';
741 }
742 /// unsigned
743 if ($this->type == XMLDB_TYPE_INTEGER ||
744 $this->type == XMLDB_TYPE_NUMBER ||
745 $this->type == XMLDB_TYPE_FLOAT) {
746 if ($this->unsigned) {
747 $o .= ' unsigned';
748 } else {
749 $o .= ' signed';
750 }
751 }
752 /// not null
753 if ($this->notnull) {
754 $o .= ' not null';
755 }
756 /// default
757 if ($this->default !== NULL) {
758 $o .= ' default ';
759 if ($this->type == XMLDB_TYPE_CHAR ||
760 $this->type == XMLDB_TYPE_TEXT) {
761 $o .= "'" . $this->default . "'";
762 } else {
763 $o .= $this->default;
764 }
765 }
766 /// sequence
767 if ($this->sequence) {
768 $o .= ' auto-numbered';
769 }
770
771 return $o;
772 }
773}
774
775?>