2009-11-01 11:42:23 +00:00
< ? php
2012-06-05 13:13:21 +02:00
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This class represent one XMLDB Field
*
* @ package core_xmldb
* @ copyright 1999 onwards Martin Dougiamas http :// dougiamas . com
* 2001 - 3001 Eloy Lafuente ( stronk7 ) http :// contiento . com
* @ license http :// www . gnu . org / copyleft / gpl . html GNU GPL v3 or later
*/
defined ( 'MOODLE_INTERNAL' ) || die ();
2006-08-15 09:14:31 +00:00
2008-05-20 23:24:40 +00:00
class xmldb_field extends xmldb_object {
2006-09-20 21:00:45 +00:00
2012-06-05 13:13:21 +02:00
/** @var int XMLDB_TYPE_ constants */
2012-06-05 13:16:37 +02:00
protected $type ;
2012-06-05 13:13:21 +02:00
/** @var int size of field */
2012-06-05 13:16:37 +02:00
protected $length ;
2012-06-05 13:13:21 +02:00
/** @var bool is null forbidden? XMLDB_NOTNULL */
2012-06-05 13:16:37 +02:00
protected $notnull ;
2012-06-05 13:13:21 +02:00
/** @var mixed default value */
2012-06-05 13:16:37 +02:00
protected $default ;
2012-06-05 13:13:21 +02:00
/** @var bool use automatic counter */
2012-06-05 13:16:37 +02:00
protected $sequence ;
2012-06-05 13:13:21 +02:00
/** @var int number of decimals */
2012-06-05 13:16:37 +02:00
protected $decimals ;
2006-08-15 09:14:31 +00:00
2011-09-11 20:30:42 +02:00
/**
* Note :
* - Oracle : VARCHAR2 has a limit of 4000 bytes
* - SQL Server : NVARCHAR has a limit of 40000 chars
* - MySQL : VARCHAR 65 , 535 chars
* - PostgreSQL : no limit
*
2023-07-03 15:58:16 +02:00
* @ var maximum length of text field
2011-09-11 20:30:42 +02:00
*/
2011-09-12 16:38:55 +02:00
const CHAR_MAX_LENGTH = 1333 ;
2011-09-11 20:30:42 +02:00
2012-03-20 19:30:45 +01:00
/**
2023-07-03 15:58:16 +02:00
* @ var maximum number of digits of integers
2012-03-20 19:30:45 +01:00
*/
const INTEGER_MAX_LENGTH = 20 ;
/**
2023-07-03 15:58:16 +02:00
* @ var max length ( precision , the total number of digits ) of decimals
2012-03-20 19:30:45 +01:00
*/
2017-12-21 16:16:50 +01:00
const NUMBER_MAX_LENGTH = 38 ;
2012-03-20 19:30:45 +01:00
/**
2023-07-03 15:58:16 +02:00
* @ var max length of floats
2012-03-20 19:30:45 +01:00
*/
const FLOAT_MAX_LENGTH = 20 ;
/**
* Note :
MDL-76459 xmldb: Raise the table & column length limits
With Oracle 19 being the minimum version for Moodle >= 4.1, now
we can safely raise the table and column length limits by a
considerable amount.
In both tables and columns the new limit it 63, coming from PostgreSQL,
that is the one now having the more restrictive limit.
1) NP with columns, let's allow up to 63 ascii chars (bytes) there.
2) But, for table names, now we need to specify a maximum prefix length,
to know how many chars we leave remaining for table names (without
prefix). 63 - 10 (max prefix length) = 53 ascii chars (bytes).
So, in this patch, we are introducing a new constant:
xmldb_table::PREFIX_MAX_LENGTH = 10
That will be used to:
- Validate that we aren't using a prefix longer than it.
- Calculate the final table limit that will be 63 minus
the prefix max length.
Details added to 4.2 main upgrade.txt file.
Also, update related to tests to (near) always use the constants
so they won't need modification in the future.
2023-03-06 23:49:41 +01:00
* - PostgreSQL has a limit of 63 ascii chars ( bytes ) for table names . Others have greater limits .
2012-03-20 19:30:45 +01:00
*
MDL-76459 xmldb: Raise the table & column length limits
With Oracle 19 being the minimum version for Moodle >= 4.1, now
we can safely raise the table and column length limits by a
considerable amount.
In both tables and columns the new limit it 63, coming from PostgreSQL,
that is the one now having the more restrictive limit.
1) NP with columns, let's allow up to 63 ascii chars (bytes) there.
2) But, for table names, now we need to specify a maximum prefix length,
to know how many chars we leave remaining for table names (without
prefix). 63 - 10 (max prefix length) = 53 ascii chars (bytes).
So, in this patch, we are introducing a new constant:
xmldb_table::PREFIX_MAX_LENGTH = 10
That will be used to:
- Validate that we aren't using a prefix longer than it.
- Calculate the final table limit that will be 63 minus
the prefix max length.
Details added to 4.2 main upgrade.txt file.
Also, update related to tests to (near) always use the constants
so they won't need modification in the future.
2023-03-06 23:49:41 +01:00
* @ var int max length of field names .
2012-03-20 19:30:45 +01:00
*/
MDL-76459 xmldb: Raise the table & column length limits
With Oracle 19 being the minimum version for Moodle >= 4.1, now
we can safely raise the table and column length limits by a
considerable amount.
In both tables and columns the new limit it 63, coming from PostgreSQL,
that is the one now having the more restrictive limit.
1) NP with columns, let's allow up to 63 ascii chars (bytes) there.
2) But, for table names, now we need to specify a maximum prefix length,
to know how many chars we leave remaining for table names (without
prefix). 63 - 10 (max prefix length) = 53 ascii chars (bytes).
So, in this patch, we are introducing a new constant:
xmldb_table::PREFIX_MAX_LENGTH = 10
That will be used to:
- Validate that we aren't using a prefix longer than it.
- Calculate the final table limit that will be 63 minus
the prefix max length.
Details added to 4.2 main upgrade.txt file.
Also, update related to tests to (near) always use the constants
so they won't need modification in the future.
2023-03-06 23:49:41 +01:00
const NAME_MAX_LENGTH = 63 ;
2012-03-20 19:30:45 +01:00
2006-08-15 09:14:31 +00:00
/**
2008-05-20 23:24:40 +00:00
* Creates one new xmldb_field
2012-06-05 13:13:21 +02:00
* @ param string $name of field
* @ param int $type XMLDB_TYPE_INTEGER , XMLDB_TYPE_NUMBER , XMLDB_TYPE_CHAR , XMLDB_TYPE_TEXT , XMLDB_TYPE_BINARY
* @ param string $precision length for integers and chars , two - comma separated numbers for numbers
* @ param bool $unsigned XMLDB_UNSIGNED or null ( or false )
* @ param bool $notnull XMLDB_NOTNULL or null ( or false )
* @ param bool $sequence XMLDB_SEQUENCE or null ( or false )
* @ param mixed $default meaningful default o null ( or false )
2023-02-28 13:13:42 +00:00
* @ param string $previous
2006-08-15 09:14:31 +00:00
*/
2012-06-06 11:07:18 +02:00
public function __construct ( $name , $type = null , $precision = null , $unsigned = null , $notnull = null , $sequence = null , $default = null , $previous = null ) {
2012-06-06 11:30:51 +02:00
$this -> type = null ;
$this -> length = null ;
2006-08-15 09:14:31 +00:00
$this -> notnull = false ;
2012-06-06 11:30:51 +02:00
$this -> default = null ;
2006-08-15 09:14:31 +00:00
$this -> sequence = false ;
2012-06-06 11:30:51 +02:00
$this -> decimals = null ;
2008-05-22 00:09:59 +00:00
parent :: __construct ( $name );
2009-05-01 01:19:16 +00:00
$this -> set_attributes ( $type , $precision , $unsigned , $notnull , $sequence , $default , $previous );
2008-05-22 00:09:59 +00:00
}
2006-09-02 23:51:39 +00:00
/**
2008-05-20 23:24:40 +00:00
* Set all the attributes of one xmldb_field
2006-09-02 23:51:39 +00:00
*
2012-06-05 13:13:21 +02:00
* @ param int $type XMLDB_TYPE_INTEGER , XMLDB_TYPE_NUMBER , XMLDB_TYPE_CHAR , XMLDB_TYPE_TEXT , XMLDB_TYPE_BINARY
* @ param string $precision length for integers and chars , two - comma separated numbers for numbers
* @ param bool $unsigned XMLDB_UNSIGNED or null ( or false )
* @ param bool $notnull XMLDB_NOTNULL or null ( or false )
* @ param bool $sequence XMLDB_SEQUENCE or null ( or false )
* @ param mixed $default meaningful default o null ( or false )
2023-02-28 13:13:42 +00:00
* @ param string $previous
2006-09-02 23:51:39 +00:00
*/
2012-06-06 11:07:18 +02:00
public function set_attributes ( $type , $precision = null , $unsigned = null , $notnull = null , $sequence = null , $default = null , $previous = null ) {
2006-09-02 23:51:39 +00:00
$this -> type = $type ;
2006-09-12 22:56:52 +00:00
2022-11-24 00:58:16 +01:00
// LOBs (BINARY OR TEXT) don't support any precision (neither length or decimals).
if ( $type == XMLDB_TYPE_BINARY || $this -> type == XMLDB_TYPE_TEXT ) {
2012-03-11 13:42:37 +01:00
$this -> length = null ;
$this -> decimals = null ;
2022-11-24 00:58:16 +01:00
} else if ( ! is_null ( $precision )) {
// Try to split the not null precision into length and decimals and apply each one as needed.
$precisionarr = explode ( ',' , $precision );
if ( isset ( $precisionarr [ 0 ])) {
$this -> length = trim ( $precisionarr [ 0 ]);
}
if ( isset ( $precisionarr [ 1 ])) {
$this -> decimals = trim ( $precisionarr [ 1 ]);
}
2012-03-11 13:42:37 +01:00
}
2022-11-24 00:58:16 +01:00
$this -> notnull = ! empty ( $notnull ) ? true : false ;
$this -> sequence = ! empty ( $sequence ) ? true : false ;
$this -> setDefault ( $default );
2006-09-12 22:56:52 +00:00
$this -> previous = $previous ;
2006-09-02 23:51:39 +00:00
}
2006-08-15 09:14:31 +00:00
/**
* Get the type
2012-06-05 13:13:21 +02:00
* @ return int
2006-08-15 09:14:31 +00:00
*/
2012-06-06 11:07:18 +02:00
public function getType () {
2006-08-15 09:14:31 +00:00
return $this -> type ;
}
/**
* Get the length
2012-06-05 13:13:21 +02:00
* @ return int
2006-08-15 09:14:31 +00:00
*/
2012-06-06 11:07:18 +02:00
public function getLength () {
2006-08-15 09:14:31 +00:00
return $this -> length ;
}
/**
* Get the decimals
2012-06-05 13:13:21 +02:00
* @ return string
2006-08-15 09:14:31 +00:00
*/
2012-06-06 11:07:18 +02:00
public function getDecimals () {
2006-08-15 09:14:31 +00:00
return $this -> decimals ;
}
/**
* Get the notnull
2012-06-05 13:13:21 +02:00
* @ return bool
2006-08-15 09:14:31 +00:00
*/
2012-06-06 11:07:18 +02:00
public function getNotNull () {
2006-08-15 09:14:31 +00:00
return $this -> notnull ;
}
/**
* Get the unsigned
2012-01-22 18:01:16 +01:00
* @ deprecated since moodle 2.3
2012-06-05 13:13:21 +02:00
* @ return bool
2006-08-15 09:14:31 +00:00
*/
2012-06-06 11:07:18 +02:00
public function getUnsigned () {
2012-01-22 18:01:16 +01:00
return false ;
2006-08-15 09:14:31 +00:00
}
/**
* Get the sequence
2012-06-05 13:13:21 +02:00
* @ return bool
2006-08-15 09:14:31 +00:00
*/
2012-06-06 11:07:18 +02:00
public function getSequence () {
2006-08-15 09:14:31 +00:00
return $this -> sequence ;
}
/**
* Get the default
2012-06-05 13:13:21 +02:00
* @ return mixed
2006-08-15 09:14:31 +00:00
*/
2012-06-06 11:07:18 +02:00
public function getDefault () {
2006-08-15 09:14:31 +00:00
return $this -> default ;
}
/**
* Set the field type
2012-06-05 13:13:21 +02:00
* @ param int $type
2006-08-15 09:14:31 +00:00
*/
2012-06-06 11:07:18 +02:00
public function setType ( $type ) {
2006-08-15 09:14:31 +00:00
$this -> type = $type ;
}
/**
* Set the field length
2012-06-05 13:13:21 +02:00
* @ param int $length
2006-08-15 09:14:31 +00:00
*/
2012-06-06 11:07:18 +02:00
public function setLength ( $length ) {
2006-08-15 09:14:31 +00:00
$this -> length = $length ;
}
/**
* Set the field decimals
2012-06-05 13:13:21 +02:00
* @ param string
2006-08-15 09:14:31 +00:00
*/
2012-06-06 11:07:18 +02:00
public function setDecimals ( $decimals ) {
2006-08-15 09:14:31 +00:00
$this -> decimals = $decimals ;
}
/**
* Set the field unsigned
2012-01-22 18:01:16 +01:00
* @ deprecated since moodle 2.3
2012-06-05 13:13:21 +02:00
* @ param bool $unsigned
2006-08-15 09:14:31 +00:00
*/
2012-06-06 11:07:18 +02:00
public function setUnsigned ( $unsigned = true ) {
2006-08-15 09:14:31 +00:00
}
/**
* Set the field notnull
2012-06-05 13:13:21 +02:00
* @ param bool $notnull
2006-08-15 09:14:31 +00:00
*/
2012-06-06 11:07:18 +02:00
public function setNotNull ( $notnull = true ) {
2006-08-15 09:14:31 +00:00
$this -> notnull = $notnull ;
}
/**
* Set the field sequence
2012-06-05 13:13:21 +02:00
* @ param bool $sequence
2006-08-15 09:14:31 +00:00
*/
2012-06-06 11:07:18 +02:00
public function setSequence ( $sequence = true ) {
2006-08-15 09:14:31 +00:00
$this -> sequence = $sequence ;
}
/**
* Set the field default
2012-06-05 13:13:21 +02:00
* @ param mixed $default
2006-08-15 09:14:31 +00:00
*/
2012-06-06 11:07:18 +02:00
public function setDefault ( $default ) {
2012-06-05 13:13:21 +02:00
// Check, warn and auto-fix '' (empty) defaults for CHAR NOT NULL columns, changing them
// to NULL so XMLDB will apply the proper default
2007-08-11 21:50:25 +00:00
if ( $this -> type == XMLDB_TYPE_CHAR && $this -> notnull && $default === '' ) {
$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. " ;
$this -> debug ( $this -> errormsg );
2009-07-03 01:12:59 +00:00
$default = null ;
}
2012-06-05 13:13:21 +02:00
// Check, warn and autofix TEXT|BINARY columns having a default clause (only null is allowed)
2009-07-03 01:12:59 +00:00
if (( $this -> type == XMLDB_TYPE_TEXT || $this -> type == XMLDB_TYPE_BINARY ) && $default !== null ) {
$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. " ;
$this -> debug ( $this -> errormsg );
$default = null ;
2007-08-11 21:50:25 +00:00
}
2006-08-15 09:14:31 +00:00
$this -> default = $default ;
}
/**
* Load data from XML to the table
2012-06-05 13:13:21 +02:00
* @ param array $xmlarr
2012-06-06 11:07:18 +02:00
* @ return mixed
2006-08-15 09:14:31 +00:00
*/
2012-06-06 11:07:18 +02:00
public function arr2xmldb_field ( $xmlarr ) {
2006-08-15 09:14:31 +00:00
$result = true ;
2012-06-05 13:13:21 +02:00
// Debug the table
// traverse_xmlize($xmlarr); //Debug
// print_object ($GLOBALS['traverse_array']); //Debug
// $GLOBALS['traverse_array']=""; //Debug
2006-08-15 09:14:31 +00:00
2012-06-05 13:13:21 +02:00
// Process table attributes (name, type, length
// notnull, sequence, decimals, comment, previous, next)
2006-08-15 09:14:31 +00:00
if ( isset ( $xmlarr [ '@' ][ 'NAME' ])) {
$this -> name = trim ( $xmlarr [ '@' ][ 'NAME' ]);
} else {
$this -> errormsg = 'Missing NAME attribute' ;
2006-10-28 15:18:40 +00:00
$this -> debug ( $this -> errormsg );
2006-08-15 09:14:31 +00:00
$result = false ;
}
if ( isset ( $xmlarr [ '@' ][ 'TYPE' ])) {
2012-06-05 13:13:21 +02:00
// Check for valid type
2006-08-15 09:14:31 +00:00
$type = $this -> getXMLDBFieldType ( trim ( $xmlarr [ '@' ][ 'TYPE' ]));
if ( $type ) {
$this -> type = $type ;
} else {
$this -> errormsg = 'Invalid TYPE attribute' ;
2006-10-28 15:18:40 +00:00
$this -> debug ( $this -> errormsg );
2006-08-15 09:14:31 +00:00
$result = false ;
}
} else {
$this -> errormsg = 'Missing TYPE attribute' ;
2006-10-28 15:18:40 +00:00
$this -> debug ( $this -> errormsg );
2006-08-15 09:14:31 +00:00
$result = false ;
}
if ( isset ( $xmlarr [ '@' ][ 'LENGTH' ])) {
$length = trim ( $xmlarr [ '@' ][ 'LENGTH' ]);
2012-06-05 13:13:21 +02:00
// Check for integer values
2006-08-15 09:14:31 +00:00
if ( $this -> type == XMLDB_TYPE_INTEGER ||
$this -> type == XMLDB_TYPE_NUMBER ||
$this -> type == XMLDB_TYPE_CHAR ) {
if ( ! ( is_numeric ( $length ) && ( intval ( $length ) == floatval ( $length )))) {
$this -> errormsg = 'Incorrect LENGTH attribute for int, number or char fields' ;
2006-10-28 15:18:40 +00:00
$this -> debug ( $this -> errormsg );
2006-08-15 09:14:31 +00:00
$result = false ;
} else if ( ! $length ) {
$this -> errormsg = 'Zero LENGTH attribute' ;
2006-10-28 15:18:40 +00:00
$this -> debug ( $this -> errormsg );
2006-08-15 09:14:31 +00:00
$result = false ;
}
}
2012-06-05 13:13:21 +02:00
// Remove length from text and binary
2006-08-15 09:14:31 +00:00
if ( $this -> type == XMLDB_TYPE_TEXT ||
$this -> type == XMLDB_TYPE_BINARY ) {
2012-03-11 13:42:37 +01:00
$length = null ;
2006-08-15 09:14:31 +00:00
}
2012-06-05 13:13:21 +02:00
// Finally, set the length
2006-08-15 09:14:31 +00:00
$this -> length = $length ;
}
if ( isset ( $xmlarr [ '@' ][ 'NOTNULL' ])) {
$notnull = strtolower ( trim ( $xmlarr [ '@' ][ 'NOTNULL' ]));
if ( $notnull == 'true' ) {
$this -> notnull = true ;
} else if ( $notnull == 'false' ) {
$this -> notnull = false ;
} else {
$this -> errormsg = 'Incorrect NOTNULL attribute (true/false allowed)' ;
2006-10-28 15:18:40 +00:00
$this -> debug ( $this -> errormsg );
2006-08-15 09:14:31 +00:00
$result = false ;
}
}
if ( isset ( $xmlarr [ '@' ][ 'SEQUENCE' ])) {
$sequence = strtolower ( trim ( $xmlarr [ '@' ][ 'SEQUENCE' ]));
if ( $sequence == 'true' ) {
$this -> sequence = true ;
} else if ( $sequence == 'false' ) {
$this -> sequence = false ;
} else {
$this -> errormsg = 'Incorrect SEQUENCE attribute (true/false allowed)' ;
2006-10-28 15:18:40 +00:00
$this -> debug ( $this -> errormsg );
2006-08-15 09:14:31 +00:00
$result = false ;
}
}
if ( isset ( $xmlarr [ '@' ][ 'DEFAULT' ])) {
2007-08-11 21:50:25 +00:00
$this -> setDefault ( trim ( $xmlarr [ '@' ][ 'DEFAULT' ]));
2006-08-15 09:14:31 +00:00
}
2012-06-06 11:30:51 +02:00
$decimals = null ;
2006-08-15 09:14:31 +00:00
if ( isset ( $xmlarr [ '@' ][ 'DECIMALS' ])) {
$decimals = trim ( $xmlarr [ '@' ][ 'DECIMALS' ]);
2012-06-05 13:13:21 +02:00
// Check for integer values
2006-09-20 21:00:45 +00:00
if ( $this -> type == XMLDB_TYPE_NUMBER ||
2006-08-15 09:14:31 +00:00
$this -> type == XMLDB_TYPE_FLOAT ) {
if ( ! ( is_numeric ( $decimals ) && ( intval ( $decimals ) == floatval ( $decimals )))) {
$this -> errormsg = 'Incorrect DECIMALS attribute for number field' ;
2006-10-28 15:18:40 +00:00
$this -> debug ( $this -> errormsg );
2006-08-15 09:14:31 +00:00
$result = false ;
} else if ( $this -> length <= $decimals ){
$this -> errormsg = 'Incorrect DECIMALS attribute (bigget than length)' ;
2006-10-28 15:18:40 +00:00
$this -> debug ( $this -> errormsg );
2006-08-15 09:14:31 +00:00
$result = false ;
}
} else {
$this -> errormsg = 'Incorrect DECIMALS attribute for non-number field' ;
2006-10-28 15:18:40 +00:00
$this -> debug ( $this -> errormsg );
2006-08-15 09:14:31 +00:00
$result = false ;
}
} else {
if ( $this -> type == XMLDB_TYPE_NUMBER ) {
$decimals = 0 ;
}
}
2012-06-05 13:13:21 +02:00
// Finally, set the decimals
2006-08-15 09:14:31 +00:00
if ( $this -> type == XMLDB_TYPE_NUMBER ||
$this -> type == XMLDB_TYPE_FLOAT ) {
$this -> decimals = $decimals ;
}
if ( isset ( $xmlarr [ '@' ][ 'COMMENT' ])) {
$this -> comment = trim ( $xmlarr [ '@' ][ 'COMMENT' ]);
}
2012-06-05 13:13:21 +02:00
// Set some attributes
2006-08-15 09:14:31 +00:00
if ( $result ) {
$this -> loaded = true ;
}
$this -> calculateHash ();
return $result ;
}
/**
* This function returns the correct XMLDB_TYPE_XXX value for the
* string passed as argument
2012-06-05 13:13:21 +02:00
* @ param string $type
* @ return int
2006-08-15 09:14:31 +00:00
*/
2012-06-06 11:07:18 +02:00
public function getXMLDBFieldType ( $type ) {
2006-08-15 09:14:31 +00:00
$result = XMLDB_TYPE_INCORRECT ;
2006-09-20 21:00:45 +00:00
2006-08-15 09:14:31 +00:00
switch ( strtolower ( $type )) {
case 'int' :
$result = XMLDB_TYPE_INTEGER ;
break ;
case 'number' :
$result = XMLDB_TYPE_NUMBER ;
break ;
case 'float' :
$result = XMLDB_TYPE_FLOAT ;
break ;
case 'char' :
$result = XMLDB_TYPE_CHAR ;
break ;
case 'text' :
$result = XMLDB_TYPE_TEXT ;
break ;
case 'binary' :
$result = XMLDB_TYPE_BINARY ;
break ;
case 'datetime' :
$result = XMLDB_TYPE_DATETIME ;
break ;
}
2012-06-05 13:13:21 +02:00
// Return the normalized XMLDB_TYPE
2006-08-15 09:14:31 +00:00
return $result ;
}
/**
* This function returns the correct name value for the
* XMLDB_TYPE_XXX passed as argument
2012-06-05 13:13:21 +02:00
* @ param int $type
* @ return string
2006-08-15 09:14:31 +00:00
*/
2012-06-06 11:07:18 +02:00
public function getXMLDBTypeName ( $type ) {
2006-08-15 09:14:31 +00:00
$result = " " ;
2006-09-20 21:00:45 +00:00
2006-08-15 09:14:31 +00:00
switch ( strtolower ( $type )) {
case XMLDB_TYPE_INTEGER :
$result = 'int' ;
break ;
case XMLDB_TYPE_NUMBER :
$result = 'number' ;
break ;
case XMLDB_TYPE_FLOAT :
$result = 'float' ;
break ;
case XMLDB_TYPE_CHAR :
$result = 'char' ;
break ;
case XMLDB_TYPE_TEXT :
$result = 'text' ;
break ;
case XMLDB_TYPE_BINARY :
$result = 'binary' ;
break ;
case XMLDB_TYPE_DATETIME :
$result = 'datetime' ;
break ;
}
2012-06-05 13:13:21 +02:00
// Return the normalized name
2006-08-15 09:14:31 +00:00
return $result ;
}
/**
2008-05-20 23:24:40 +00:00
* This function calculate and set the hash of one xmldb_field
2012-06-05 13:13:21 +02:00
* @ param bool $recursive
* @ return void , modifies $this -> hash
2006-08-15 09:14:31 +00:00
*/
2012-06-06 11:07:18 +02:00
public function calculateHash ( $recursive = false ) {
2006-08-15 09:14:31 +00:00
if ( ! $this -> loaded ) {
2012-06-06 11:30:51 +02:00
$this -> hash = null ;
2006-08-15 09:14:31 +00:00
} else {
2012-07-23 20:48:14 +02:00
$defaulthash = is_null ( $this -> default ) ? '' : sha1 ( $this -> default );
2006-08-15 09:14:31 +00:00
$key = $this -> name . $this -> type . $this -> length .
2012-01-22 18:01:16 +01:00
$this -> notnull . $this -> sequence .
2012-07-23 20:48:14 +02:00
$this -> decimals . $this -> comment . $defaulthash ;
2006-08-15 09:14:31 +00:00
$this -> hash = md5 ( $key );
}
}
2006-09-20 21:00:45 +00:00
/**
2012-06-05 13:13:21 +02:00
* This function will output the XML text for one field
* @ return string
2006-08-15 09:14:31 +00:00
*/
2012-06-06 11:07:18 +02:00
public function xmlOutput () {
2006-08-15 09:14:31 +00:00
$o = '' ;
$o .= ' <FIELD NAME="' . $this -> name . '"' ;
$o .= ' TYPE="' . $this -> getXMLDBTypeName ( $this -> type ) . '"' ;
if ( $this -> length ) {
$o .= ' LENGTH="' . $this -> length . '"' ;
}
if ( $this -> notnull ) {
$notnull = 'true' ;
} else {
$notnull = 'false' ;
}
$o .= ' NOTNULL="' . $notnull . '"' ;
2012-06-06 11:30:51 +02:00
if ( ! $this -> sequence && $this -> default !== null ) {
2006-08-15 09:14:31 +00:00
$o .= ' DEFAULT="' . $this -> default . '"' ;
}
if ( $this -> sequence ) {
$sequence = 'true' ;
} else {
$sequence = 'false' ;
}
$o .= ' SEQUENCE="' . $sequence . '"' ;
2012-06-06 11:30:51 +02:00
if ( $this -> decimals !== null ) {
2006-08-15 09:14:31 +00:00
$o .= ' DECIMALS="' . $this -> decimals . '"' ;
}
if ( $this -> comment ) {
2022-10-28 10:27:37 +02:00
$o .= ' COMMENT="' . htmlspecialchars ( $this -> comment , ENT_COMPAT ) . '"' ;
2006-08-15 09:14:31 +00:00
}
$o .= '/>' . " \n " ;
return $o ;
}
/**
2008-05-20 23:24:40 +00:00
* This function will set all the attributes of the xmldb_field object
2006-08-15 09:14:31 +00:00
* based on information passed in one ADOField
2023-02-28 13:13:42 +00:00
* @ param database_column_info $adofield
2012-06-05 13:13:21 +02:00
* @ return void , sets $this -> type
2006-08-15 09:14:31 +00:00
*/
2012-06-06 11:07:18 +02:00
public function setFromADOField ( $adofield ) {
2006-08-15 09:14:31 +00:00
2012-06-05 13:13:21 +02:00
// Calculate the XMLDB_TYPE
2006-08-15 09:14:31 +00:00
switch ( strtolower ( $adofield -> type )) {
case 'int' :
case 'tinyint' :
case 'smallint' :
case 'bigint' :
case 'integer' :
$this -> type = XMLDB_TYPE_INTEGER ;
break ;
case 'number' :
case 'decimal' :
case 'dec' :
case 'numeric' :
$this -> type = XMLDB_TYPE_NUMBER ;
break ;
case 'float' :
case 'double' :
$this -> type = XMLDB_TYPE_FLOAT ;
break ;
case 'char' :
case 'varchar' :
case 'enum' :
$this -> type = XMLDB_TYPE_CHAR ;
break ;
case 'text' :
case 'tinytext' :
case 'mediumtext' :
case 'longtext' :
$this -> type = XMLDB_TYPE_TEXT ;
break ;
case 'blob' :
case 'tinyblob' :
case 'mediumblob' :
case 'longblob' :
$this -> type = XMLDB_TYPE_BINARY ;
break ;
case 'datetime' :
case 'timestamp' :
$this -> type = XMLDB_TYPE_DATETIME ;
break ;
default :
$this -> type = XMLDB_TYPE_TEXT ;
}
2012-06-05 13:13:21 +02:00
// Calculate the length of the field
2006-09-20 21:00:45 +00:00
if ( $adofield -> max_length > 0 &&
2006-08-15 09:14:31 +00:00
( $this -> type == XMLDB_TYPE_INTEGER ||
$this -> type == XMLDB_TYPE_NUMBER ||
$this -> type == XMLDB_TYPE_FLOAT ||
$this -> type == XMLDB_TYPE_CHAR )) {
$this -> length = $adofield -> max_length ;
}
if ( $this -> type == XMLDB_TYPE_TEXT ) {
2012-03-11 13:42:37 +01:00
$this -> length = null ;
2006-08-15 09:14:31 +00:00
}
if ( $this -> type == XMLDB_TYPE_BINARY ) {
2012-03-11 13:42:37 +01:00
$this -> length = null ;
2006-08-15 09:14:31 +00:00
}
2012-06-05 13:13:21 +02:00
// Calculate the decimals of the field
2006-08-15 09:14:31 +00:00
if ( $adofield -> max_length > 0 &&
2006-09-20 21:00:45 +00:00
$adofield -> scale &&
2006-08-15 09:14:31 +00:00
( $this -> type == XMLDB_TYPE_NUMBER ||
$this -> type == XMLDB_TYPE_FLOAT )) {
$this -> decimals = $adofield -> scale ;
}
2012-06-05 13:13:21 +02:00
// Calculate the notnull field
2006-08-15 09:14:31 +00:00
if ( $adofield -> not_null ) {
$this -> notnull = true ;
}
2012-06-05 13:13:21 +02:00
// Calculate the default field
2006-08-15 09:14:31 +00:00
if ( $adofield -> has_default ) {
$this -> default = $adofield -> default_value ;
2006-09-20 21:00:45 +00:00
}
2012-06-05 13:13:21 +02:00
// Calculate the sequence field
2006-08-15 09:14:31 +00:00
if ( $adofield -> auto_increment ) {
$this -> sequence = true ;
}
2012-06-05 13:13:21 +02:00
// Some more fields
2006-08-15 09:14:31 +00:00
$this -> loaded = true ;
$this -> changed = true ;
}
2006-09-06 19:31:03 +00:00
/**
2008-05-20 23:24:40 +00:00
* Returns the PHP code needed to define one xmldb_field
2012-06-05 13:13:21 +02:00
* @ param bool $includeprevious
* @ return string
2006-09-06 19:31:03 +00:00
*/
2012-06-06 11:07:18 +02:00
public function getPHP ( $includeprevious = true ) {
2006-09-06 19:31:03 +00:00
$result = '' ;
2012-06-05 13:13:21 +02:00
// The XMLDBTYPE
2006-09-06 19:31:03 +00:00
switch ( $this -> getType ()) {
case XMLDB_TYPE_INTEGER :
$result .= 'XMLDB_TYPE_INTEGER' . ', ' ;
break ;
case XMLDB_TYPE_NUMBER :
$result .= 'XMLDB_TYPE_NUMBER' . ', ' ;
break ;
case XMLDB_TYPE_FLOAT :
$result .= 'XMLDB_TYPE_FLOAT' . ', ' ;
break ;
case XMLDB_TYPE_CHAR :
$result .= 'XMLDB_TYPE_CHAR' . ', ' ;
break ;
case XMLDB_TYPE_TEXT :
$result .= 'XMLDB_TYPE_TEXT' . ', ' ;
break ;
case XMLDB_TYPE_BINARY :
$result .= 'XMLDB_TYPE_BINARY' . ', ' ;
break ;
case XMLDB_TYPE_DATETIME :
$result .= 'XMLDB_TYPE_DATETIME' . ', ' ;
break ;
case XMLDB_TYPE_TIMESTAMP :
$result .= 'XMLDB_TYPE_TIMESTAMP' . ', ' ;
break ;
}
2012-06-05 13:13:21 +02:00
// The length
2006-09-06 19:31:03 +00:00
$length = $this -> getLength ();
$decimals = $this -> getDecimals ();
if ( ! empty ( $length )) {
$result .= " ' " . $length ;
if ( ! empty ( $decimals )) {
$result .= ', ' . $decimals ;
}
$result .= " ', " ;
} else {
$result .= 'null, ' ;
}
2012-06-05 13:13:21 +02:00
// Unsigned is not used any more since Moodle 2.3
2012-01-22 18:01:16 +01:00
$result .= 'null, ' ;
2012-06-05 13:13:21 +02:00
// Not Null
2006-09-06 19:31:03 +00:00
$notnull = $this -> getNotnull ();
if ( ! empty ( $notnull )) {
$result .= 'XMLDB_NOTNULL' . ', ' ;
} else {
$result .= 'null, ' ;
}
2012-06-05 13:13:21 +02:00
// Sequence
2006-09-06 19:31:03 +00:00
$sequence = $this -> getSequence ();
if ( ! empty ( $sequence )) {
$result .= 'XMLDB_SEQUENCE' . ', ' ;
} else {
$result .= 'null, ' ;
}
2012-06-05 13:13:21 +02:00
// Default
2006-09-06 19:31:03 +00:00
$default = $this -> getDefault ();
2006-09-12 16:45:46 +00:00
if ( $default !== null && ! $this -> getSequence ()) {
2006-09-06 19:31:03 +00:00
$result .= " ' " . $default . " ' " ;
} else {
$result .= 'null' ;
}
2012-06-05 13:13:21 +02:00
// Previous (decided by parameter)
2006-09-06 19:31:03 +00:00
if ( $includeprevious ) {
$previous = $this -> getPrevious ();
if ( ! empty ( $previous )) {
$result .= " , ' " . $previous . " ' " ;
} else {
$result .= ', null' ;
}
}
2012-06-05 13:13:21 +02:00
// Return result
2006-09-06 19:31:03 +00:00
return $result ;
}
2006-08-15 09:14:31 +00:00
/**
* Shows info in a readable format
2012-06-05 13:13:21 +02:00
* @ return string
2006-08-15 09:14:31 +00:00
*/
2012-06-06 11:07:18 +02:00
public function readableInfo () {
2006-08-15 09:14:31 +00:00
$o = '' ;
2012-06-05 13:13:21 +02:00
// type
2006-08-15 09:14:31 +00:00
$o .= $this -> getXMLDBTypeName ( $this -> type );
2012-06-05 13:13:21 +02:00
// length
2006-08-15 09:14:31 +00:00
if ( $this -> type == XMLDB_TYPE_INTEGER ||
$this -> type == XMLDB_TYPE_NUMBER ||
$this -> type == XMLDB_TYPE_FLOAT ||
$this -> type == XMLDB_TYPE_CHAR ) {
if ( $this -> length ) {
$o .= ' (' . $this -> length ;
if ( $this -> type == XMLDB_TYPE_NUMBER ||
$this -> type == XMLDB_TYPE_FLOAT ) {
2012-06-06 11:30:51 +02:00
if ( $this -> decimals !== null ) {
2006-08-15 09:14:31 +00:00
$o .= ', ' . $this -> decimals ;
}
}
$o .= ')' ;
}
}
2012-06-05 13:13:21 +02:00
// not null
2006-08-15 09:14:31 +00:00
if ( $this -> notnull ) {
$o .= ' not null' ;
}
2012-06-05 13:13:21 +02:00
// default
2012-06-06 11:30:51 +02:00
if ( $this -> default !== null ) {
2006-08-15 09:14:31 +00:00
$o .= ' default ' ;
if ( $this -> type == XMLDB_TYPE_CHAR ||
$this -> type == XMLDB_TYPE_TEXT ) {
$o .= " ' " . $this -> default . " ' " ;
} else {
$o .= $this -> default ;
}
}
2012-06-05 13:13:21 +02:00
// sequence
2006-08-15 09:14:31 +00:00
if ( $this -> sequence ) {
$o .= ' auto-numbered' ;
}
return $o ;
}
2011-09-11 20:30:42 +02:00
/**
* Validates the field restrictions .
*
* The error message should not be localised because it is intended for developers ,
* end users and admins should never see these problems !
*
* @ param xmldb_table $xmldb_table optional when object is table
* @ return string null if ok , error message if problem found
*/
2012-06-06 11:07:18 +02:00
public function validateDefinition ( xmldb_table $xmldb_table = null ) {
2011-09-11 20:30:42 +02:00
if ( ! $xmldb_table ) {
2012-03-19 18:44:33 +01:00
return 'Invalid xmldb_field->validateDefinition() call, $xmldb_table is required.' ;
}
$name = $this -> getName ();
2012-03-20 19:30:45 +01:00
if ( strlen ( $name ) > self :: NAME_MAX_LENGTH ) {
2012-03-19 18:44:33 +01:00
return 'Invalid field name in table {' . $xmldb_table -> getName () . '}: field "' . $this -> getName () . '" name is too long.'
2012-03-20 19:30:45 +01:00
. ' Limit is ' . self :: NAME_MAX_LENGTH . ' chars.' ;
2012-03-19 18:44:33 +01:00
}
if ( ! preg_match ( '/^[a-z][a-z0-9_]*$/' , $name )) {
return 'Invalid field name in table {' . $xmldb_table -> getName () . '}: field "' . $this -> getName () . '" name includes invalid characters.' ;
2011-09-11 20:30:42 +02:00
}
switch ( $this -> getType ()) {
case XMLDB_TYPE_INTEGER :
2012-03-19 19:49:28 +01:00
$length = $this -> getLength ();
2012-03-20 19:30:45 +01:00
if ( ! is_number ( $length ) or $length <= 0 or $length > self :: INTEGER_MAX_LENGTH ) {
return 'Invalid field definition in table {' . $xmldb_table -> getName () . '}: XMLDB_TYPE_INTEGER field "' . $this -> getName () . '" has invalid length' ;
2012-03-19 19:49:28 +01:00
}
$default = $this -> getDefault ();
if ( ! empty ( $default ) and ! is_number ( $default )) {
2012-03-20 19:30:45 +01:00
return 'Invalid field definition in table {' . $xmldb_table -> getName () . '}: XMLDB_TYPE_INTEGER field "' . $this -> getName () . '" has invalid default' ;
2012-03-19 19:49:28 +01:00
}
2011-09-19 01:24:51 +02:00
break ;
2011-09-11 20:30:42 +02:00
case XMLDB_TYPE_NUMBER :
2012-03-20 19:30:45 +01:00
$maxlength = self :: NUMBER_MAX_LENGTH ;
2012-03-19 20:00:33 +01:00
$length = $this -> getLength ();
2012-03-19 20:48:48 +01:00
if ( ! is_number ( $length ) or $length <= 0 or $length > $maxlength ) {
2012-03-20 19:30:45 +01:00
return 'Invalid field definition in table {' . $xmldb_table -> getName () . '}: XMLDB_TYPE_NUMBER field "' . $this -> getName () . '" has invalid length' ;
2012-03-19 20:00:33 +01:00
}
$decimals = $this -> getDecimals ();
$decimals = empty ( $decimals ) ? 0 : $decimals ; // fix missing decimals
if ( ! is_number ( $decimals ) or $decimals < 0 or $decimals > $length ) {
2012-03-20 19:30:45 +01:00
return 'Invalid field definition in table {' . $xmldb_table -> getName () . '}: XMLDB_TYPE_NUMBER field "' . $this -> getName () . '" has invalid decimals' ;
2012-03-19 20:00:33 +01:00
}
2017-12-21 16:16:50 +01:00
if ( $length - $decimals > self :: INTEGER_MAX_LENGTH ) {
return 'Invalid field definition in table {' . $xmldb_table -> getName () . '}: XMLDB_TYPE_NUMBER field "' .
$this -> getName () . '" has too big whole number part' ;
}
2012-03-19 20:00:33 +01:00
$default = $this -> getDefault ();
if ( ! empty ( $default ) and ! is_numeric ( $default )) {
2012-03-20 19:30:45 +01:00
return 'Invalid field definition in table {' . $xmldb_table -> getName () . '}: XMLDB_TYPE_NUMBER field "' . $this -> getName () . '" has invalid default' ;
2012-03-19 20:00:33 +01:00
}
2011-09-19 01:24:51 +02:00
break ;
2011-09-11 20:30:42 +02:00
case XMLDB_TYPE_FLOAT :
2012-03-19 20:10:01 +01:00
$length = $this -> getLength ();
$length = empty ( $length ) ? 6 : $length ; // weird, it might be better to require something here...
2012-03-20 19:30:45 +01:00
if ( ! is_number ( $length ) or $length <= 0 or $length > self :: FLOAT_MAX_LENGTH ) {
return 'Invalid field definition in table {' . $xmldb_table -> getName () . '}: XMLDB_TYPE_FLOAT field "' . $this -> getName () . '" has invalid length' ;
2012-03-19 20:10:01 +01:00
}
$decimals = $this -> getDecimals ();
$decimals = empty ( $decimals ) ? 0 : $decimals ; // fix missing decimals
if ( ! is_number ( $decimals ) or $decimals < 0 or $decimals > $length ) {
2012-03-20 19:30:45 +01:00
return 'Invalid field definition in table {' . $xmldb_table -> getName () . '}: XMLDB_TYPE_FLOAT field "' . $this -> getName () . '" has invalid decimals' ;
2012-03-19 20:10:01 +01:00
}
$default = $this -> getDefault ();
if ( ! empty ( $default ) and ! is_numeric ( $default )) {
2012-03-20 19:30:45 +01:00
return 'Invalid field definition in table {' . $xmldb_table -> getName () . '}: XMLDB_TYPE_FLOAT field "' . $this -> getName () . '" has invalid default' ;
2012-03-19 20:10:01 +01:00
}
2011-09-19 01:24:51 +02:00
break ;
2011-09-11 20:30:42 +02:00
case XMLDB_TYPE_CHAR :
if ( $this -> getLength () > self :: CHAR_MAX_LENGTH ) {
return 'Invalid field definition in table {' . $xmldb_table -> getName () . '}: XMLDB_TYPE_CHAR field "' . $this -> getName () . '" is too long.'
. ' Limit is ' . self :: CHAR_MAX_LENGTH . ' chars.' ;
}
2011-09-19 01:24:51 +02:00
break ;
2011-09-11 20:30:42 +02:00
case XMLDB_TYPE_TEXT :
2011-09-19 01:24:51 +02:00
break ;
2011-09-11 20:30:42 +02:00
case XMLDB_TYPE_BINARY :
2011-09-19 01:24:51 +02:00
break ;
2011-09-11 20:30:42 +02:00
case XMLDB_TYPE_DATETIME :
2011-09-19 01:24:51 +02:00
break ;
2011-09-11 20:30:42 +02:00
case XMLDB_TYPE_TIMESTAMP :
2011-09-19 01:24:51 +02:00
break ;
2011-09-11 20:30:42 +02:00
}
return null ;
}
2006-08-15 09:14:31 +00:00
}