dblayeroo : Add the "realTypes" support with basic associated tests. If the user want some custom tests, it must extends the class and create checkRealType_XXX tests

git-svn-id: https://svn.fournier38.fr/svn/ProgSVN/trunk@4621 bf3deb0d-5f1a-0410-827f-c0cc1f45334c
This commit is contained in:
2018-10-24 12:56:55 +00:00
parent d269917682
commit c01a476a9a

View File

@@ -1,7 +1,8 @@
<?php
/** DomFramework
@package domframework
@author Dominique Fournier <dominique@fournier38.fr> */
* @package domframework
* @author Dominique Fournier <dominique@fournier38.fr>
*/
// dblayeroo.php
@@ -42,6 +43,12 @@ class dblayeroo
/** Titles
*/
private $titles = array ();
/** The real types of each fields. The real types are different of the SQL
* types : a "mail" type is stored in a "VARCHAR(255)" in SQL.
* The real types are optional : if not set, there is no check.
* They are more strict than the SQL types
*/
private $realTypes = array ();
/** Limit to one instance of the connection to the same database
*/
@@ -55,8 +62,8 @@ class dblayeroo
* @param string|null $password Password to connect
* @param string|null $driver_options Driver options to the database
*/
public function __construct ($dsn, $username=null, $password=null,
$driver_options=null)
public function __construct ($dsn, $username = null, $password = null,
$driver_options = null)
{
$this->connect ($dsn, $username, $password, $driver_options);
}
@@ -68,8 +75,8 @@ class dblayeroo
* @param string|null $password Password to connect
* @param string|null $driver_options Driver options to the database
*/
public function connect ($dsn, $username=null, $password=null,
$driver_options=null)
public function connect ($dsn, $username = null, $password = null,
$driver_options = null)
/* {{{ */
{
if (! function_exists ("mb_strlen"))
@@ -149,7 +156,7 @@ class dblayeroo
$this->DBException ("No Database provided in DSN");
// Force the GROUP_CONCAT value max to the max allowed from the server
$st = self::$instance[$this->dsn]->query (
"SHOW VARIABLES LIKE 'max_allowed_packet'", PDO::FETCH_COLUMN, 1);
"SHOW VARIABLES LIKE 'max_allowed_packet'", \PDO::FETCH_COLUMN, 1);
$rows = $st->fetchAll ();
if (! isset ($rows[0]))
throw new \Exception (
@@ -980,7 +987,7 @@ class dblayeroo
/** Get/Set the table property
* @param string|null $table The table to use
*/
public function table ($table=null)
public function table ($table = null)
/* {{{ */
{
$this->debugLog ("Entering table (",$table,")");
@@ -998,7 +1005,7 @@ class dblayeroo
/** Get/Set the tableprefix property
* @param string|null $tableprefix The prefix to append
*/
public function tableprefix ($tableprefix=null)
public function tableprefix ($tableprefix = null)
/* {{{ */
{
$this->debugLog ("Entering tableprefix (",$tableprefix,")");
@@ -1019,7 +1026,7 @@ class dblayeroo
* array ("fieldName"=>array ("type"[, "not null"[, "autoincrement"]]))
* @param array|null $fields The fields to define
*/
public function fields ($fields=null)
public function fields ($fields = null)
/* {{{ */
{
$this->debugLog ("Entering fields (VALUE)");
@@ -1105,7 +1112,7 @@ class dblayeroo
/** Get/Set the primary property
* @param string|null $primary The primary key to use
*/
public function primary ($primary=null)
public function primary ($primary = null)
/* {{{ */
{
$this->debugLog ("Entering primary (",$primary,")");
@@ -1125,7 +1132,7 @@ class dblayeroo
/** Get/Set the unique property
* @param array|null $unique The unique fields constraint to add
*/
public function unique ($unique=null)
public function unique ($unique = null)
/* {{{ */
{
$this->debugLog ("Entering unique (VALUE)");
@@ -1171,7 +1178,7 @@ class dblayeroo
* )
* Multiple field and parnentField can be provided, separated by comma
*/
public function foreign ($foreign=null)
public function foreign ($foreign = null)
/* {{{ */
{
$this->debugLog ("Entering foreign (VALUE)");
@@ -1232,7 +1239,7 @@ class dblayeroo
/** Get/Set the debug property
* @param integer|null $debug Set the debug value
*/
public function debug ($debug=null)
public function debug ($debug = null)
/* {{{ */
{
$this->debugLog ("Entering debug (",$debug,")");
@@ -1332,6 +1339,43 @@ class dblayeroo
}
/* }}} */
/** Define a real type array
* Must be array ("field" => "realtype")
* @param array $realTypes The realTypes to set
* The allowed real types are defined in test method :
* checkRealType_TYPE ($val, $definition)
* The allowed real types are : mail, date, datetime, allowedchars(a23d),
* uuid, time, array('val1','val2','val3'), regex(/^[a-zA-Z]{3,}$/i)
* integer, integerPositive,
* To be done :
* integerNegative,
* php_function(), function($val) { if ($val > 0) return "MESSAGE";}
*/
public function realTypes ($realTypes = null)
// {{{
{
if ($realTypes === null)
return $this->realTypes;
if (! is_array ($realTypes))
$this->DBException ("Invalid setRealType provided : not an array", 500);
foreach ($realTypes as $field => $realType)
{
if (! key_exists ($field, $this->fields))
$this->DBException ("Invalid setRealType provided : ".
"field '$field' doesn't exists");
list ($func, $param) = explode ("(", $realType);
$func = trim ($func);
$method = "checkRealType_".$func;
if (! method_exists ($this, $method))
$this->DBException ("Invalid setRealType provided : ".
"field '$field' : unknown realType provided '$func'");
}
$this->realTypes = $realTypes;
return $this;
}
// }}}
/////////////////////////////////////
/// MANAGE THE REQUEST BY OOP ///
/////////////////////////////////////
@@ -2138,7 +2182,7 @@ class dblayeroo
* If the parameter $full is set, add the table prefix/name to the result
* @param boolean|null $full Add the table prefix/name if set
*/
public function orderGet ($full=false)
public function orderGet ($full = false)
/* {{{ */
{
$order = array ();
@@ -2189,7 +2233,7 @@ class dblayeroo
* If the parameter $full is set, add the table prefix/name to the result
* @param boolean|null $full Add the table prefix/name if set
*/
public function groupByGet ($full=false)
public function groupByGet ($full = false)
/* {{{ */
{
if ($this->joinObject)
@@ -2846,6 +2890,9 @@ class dblayeroo
$this->debugLog ("Entering checkValues (",$update,")");
$update = !! $update;
$values = $this->setValues;
$errors = $this->checkRealType ($values, $update);
if (count ($errors))
$this->DBException (reset ($errors));
$errors = $this->verify ($values, $update);
if (count ($errors))
$this->DBException (reset ($errors));
@@ -2853,6 +2900,60 @@ class dblayeroo
}
/* }}} */
/** Check the types of the data against the realTypes
* Return an array with the field name in error and a message
* If allowEmpty is set, do not test the "NOT NULL" feature
* In UPDATE, the values don't need be not set : they are already in database
* so $allowEmpty is true
* @param array $values The values to test
* @param boolean|null $allowEmpty Allow the "not null" to not be set
* @return array empty array if no error
*/
public function checkRealType ($values, $allowEmpty = false)
// {{{
{
$this->debugLog ("Entering checkRealType (",$values,",",$allowEmpty,")");
if (! is_array ($values))
$this->DBException ("Invalid checkRealType provided : not an array", 500);
$errors = array ();
foreach ($this->fields as $field => $params)
{
if (! key_exists ($field, $values) || trim ($values[$field]) === "")
{
if (in_array ("not null", $params) &&
! in_array ("autoincrement", $params))
{
if ($allowEmpty === false)
$errors[$field] = dgettext ("domframework",
"The field can not be empty");
}
else
{
// Empty value is not tested and do not generate an error
}
}
elseif (! is_string ($values[$field]))
{
$errors[$field] = dgettext ("domframework",
"The value is not a string");
}
elseif (key_exists ($field, $this->realTypes))
{
$val = trim ($values[$field]);
list ($func, $param) = explode ("(", $this->realTypes[$field]);
$func = trim ($func);
$method = "checkRealType_".$func;
$res = $this->$method ($val, $this->realTypes[$field]);
if (is_string ($res))
$errors[$field] = $res;
}
}
$this->debugLog ("End checkRealType (", $values, ",", $allowEmpty, ") : ",
$errors);
return $errors;
}
// }}}
/** Execute the pre-defined query
* Return the content array if SELECT command is choosed
* Return the Last ID if INSERT command is choosed
@@ -3083,4 +3184,255 @@ class dblayeroo
echo "\n";
}
/* }}} */
//////////////////////////////////////////////
//// ALL THE CHECK REALTYPES METHODS ////
//////////////////////////////////////////////
// {{{
/** Check the type "integerPositive"
* @param string $val The value to check
* @param string $definition The definition of the type
* @return string or null
*/
private function checkRealType_integerPositive ($val, $definition)
// {{{
{
if (substr ($val, 0, 1) === "-")
return dgettext ("domframework", "Invalid positive integer : ".
"can not start by minus sign");
if (strspn ($val, "0123456789") !== strlen ($val))
return dgettext ("domframework", "Invalid positive integer : ".
"invalid char");
if (substr ($val, 0, 1) === "0" && $val !== "0")
return dgettext ("domframework", "Invalid positive integer : ".
"can not start by Zero");
return;
}
// }}}
/** Check the type "integer"
* @param string $val The value to check
* @param string $definition The definition of the type
* @return string or null
*/
private function checkRealType_integer ($val, $definition)
// {{{
{
if (strspn ($val, "0123456789-") !== strlen ($val))
return dgettext ("domframework", "Invalid integer : ".
"invalid char");
if (substr ($val, 0, 1) === "0" && $val !== "0")
return dgettext ("domframework", "Invalid integer : ".
"can not start by Zero");
if (substr ($val, 0, 2) === "-0")
return dgettext ("domframework", "Invalid integer : ".
"can not start by Minus Zero");
return;
}
// }}}
/** Check the type "allowedchars"
* the chars must be in UTF-8
* @param string $val The value to check
* @param string $definition The definition of the type
* @return string or null
*/
private function checkRealType_allowedchars ($val, $definition)
// {{{
{
list ($func, $param) = explode ("(", $definition);
if ($param === null)
$this->DBException ("Invalid allowedchars definied : ".
"must have a starting parenthesis");
if (substr ($param, -1) !== ")")
$this->DBException ("Invalid allowedchars definied : ".
"must have a ending parenthesis");
$allowedChars = mb_substr ($param, 0, -1);
$allowedChars = preg_quote ($allowedChars, "#");
preg_match ('#^['.$allowedChars.']+#u', $val, $matches);
if (isset ($matches[0]) &&
mb_strlen ($matches[0]) === mb_strlen ($val))
return;
return dgettext ("domframework", "Invalid char provided");
}
// }}}
/** Check the type "array"
* @param string $val The value to check
* @param string $definition The definition of the type
* @return string or null
*/
private function checkRealType_array ($val, $definition)
// {{{
{
list ($func, $param) = explode ("(", $definition);
if ($param === null)
$this->DBException ("Invalid array definied : ".
"must have a starting parenthesis");
if (substr ($param, -1) !== ")")
$this->DBException ("Invalid array definied : ".
"must have a ending parenthesis");
$param = mb_substr ($param, 0, -1);
$array = explode (",", $param);
foreach ($array as $key => $tmp)
{
$array[$key] = mb_substr ($tmp, 1, -1);
}
if (in_array ($val, $array))
return;
return dgettext ("domframework", "Invalid value provided : ".
"not in allowed list");
}
// }}}
/** Check the type "regex"
* Do not forget to add the separators, the ^ and $
* @param string $val The value to check
* @param string $definition The definition of the type
* @return string or null
*/
private function checkRealType_regex ($val, $definition)
// {{{
{
list ($func, $param) = explode ("(", $definition);
if ($param === null)
$this->DBException ("Invalid regex definied : ".
"must have a starting parenthesis");
if (substr ($param, -1) !== ")")
$this->DBException ("Invalid regex definied : ".
"must have a ending parenthesis");
$param = mb_substr ($param, 0, -1);
if (@preg_match ($param, $val) === false)
$this->DBException ("Invalid regex definied : ".
"must have a ending parenthesis");
if (preg_match ($param, $val))
return;
return dgettext ("domframework", "Invalid value provided : ".
"do not match the regex");
}
// }}}
/** Check the type "mail"
* @param string $val The value to check
* @param string $definition The definition of the type
* @return string or null
*/
private function checkRealType_mail ($val, $definition)
// {{{
{
if (!! filter_var ($val, FILTER_VALIDATE_EMAIL))
return;
return dgettext ("domframework", "Invalid mail provided");
}
// }}}
/** Check the type "uuid"
* @param string $val The value to check
* @param string $definition The definition of the type
* @return string or null
*/
private function checkRealType_uuid ($val, $definition)
// {{{
{
if (strlen ($val) !== 36)
return dgettext ("domframework", "Invalid UUID provided : ".
"invalid length");
if (strspn ($val, "0123456789abcdefABCDEF-") !== strlen ($val))
return dgettext ("domframework", "Invalid UUID provided : invalid char");
if ($val[8] !== "-" || $val[13] !== "-" || $val[18] !== "-" ||
$val[23] !== "-")
return dgettext ("domframework", "Invalid UUID provided : missing dash");
}
// }}}
/** Check the type "sqldate"
* @param string $val The value to check
* @param string $definition The definition of the type
* @return string or null
*/
private function checkRealType_sqldate ($val, $definition)
// {{{
{
if (strlen ($val) !== 10)
return dgettext ("domframework", "Invalid date provided : ".
"invalid length");
if (strspn ($val, "0123456789-") !== strlen ($val))
return dgettext ("domframework", "Invalid date provided : ".
"invalid chars");
$arr = \date_parse ($val);
if ($arr["warning_count"] !== 0)
return dgettext ("domframework", "Invalid date provided : ".
"can not parse the date");
if ($arr["error_count"] !== 0)
return dgettext ("domframework", "Invalid date provided : ".
"can not parse the date");
if (isset ($arr["tz_abbr"]))
return dgettext ("domframework", "Invalid date provided : ".
"can not parse the date");
if (\DateTime::createFromFormat("Y-m-d", $val) === false)
return dgettext ("domframework", "Invalid date provided : ".
"the date doesn't exists");
}
// }}}
/** Check the type "sqltime"
* @param string $val The value to check
* @param string $definition The definition of the type
* @return string or null
*/
private function checkRealType_sqltime ($val, $definition)
// {{{
{
if (strlen ($val) !== 8)
return dgettext ("domframework", "Invalid time provided : ".
"invalid length");
if (strspn ($val, "0123456789:") !== strlen ($val))
return dgettext ("domframework", "Invalid time provided : ".
"invalid chars");
$arr = \date_parse ($val);
if ($arr["warning_count"] !== 0)
return dgettext ("domframework", "Invalid time provided : ".
"can not parse the time");
if ($arr["error_count"] !== 0)
return dgettext ("domframework", "Invalid time provided : ".
"can not parse the time");
if (isset ($arr["tz_abbr"]))
return dgettext ("domframework", "Invalid time provided : ".
"can not parse the date");
if (\DateTime::createFromFormat("H:i:s", $val) === false)
return dgettext ("domframework", "Invalid time provided : ".
"the time doesn't exists");
}
// }}}
/** Check the type "sqldatetime"
* @param string $val The value to check
* @param string $definition The definition of the type
* @return string or null
*/
private function checkRealType_sqldatetime ($val, $definition)
// {{{
{
if (strlen ($val) !== 19)
return dgettext ("domframework", "Invalid date and time provided : ".
"invalid length");
if (strspn ($val, "0123456789 :-") !== strlen ($val))
return dgettext ("domframework", "Invalid date and time provided : ".
"invalid chars");
$arr = \date_parse ($val);
if ($arr["warning_count"] !== 0)
return dgettext ("domframework", "Invalid date and time provided : ".
"can not parse the date");
if ($arr["error_count"] !== 0)
return dgettext ("domframework", "Invalid date and time provided : ".
"can not parse the date");
if (isset ($arr["tz_abbr"]))
return dgettext ("domframework", "Invalid date and time provided : ".
"can not parse the date");
if (\DateTime::createFromFormat("Y-m-d H:i:s", $val) === false)
return dgettext ("domframework", "Invalid date and time provided : ".
"the date doesn't exists");
}
// }}}
// }}}
}