You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
204 lines
8.3 KiB
204 lines
8.3 KiB
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
/**
|
|
* @author Robert Strutts <Robert@TryingToScale.com>
|
|
* @copyright Copyright (c) 2022, Robert Strutts.
|
|
* @license https://mit-license.org/
|
|
*/
|
|
|
|
namespace tts\traits\database;
|
|
|
|
trait validation {
|
|
|
|
/**
|
|
* Validate current class members
|
|
* @retval bool true valid, false failed tests
|
|
*/
|
|
public function validate_mysql(): bool {
|
|
$tbl = (\bs_tts\common::is_string_found($this->table, "`")) ? $this->table : "`{$this->table}`";
|
|
foreach ($this->members as $field => $value) {
|
|
if ($field == $this->primary_key) {
|
|
continue;
|
|
}
|
|
|
|
$validation_field = $this->get_vaildation_member($field);
|
|
if (isset($validation_field['native_type']) && isset($validation_field['len'])) {
|
|
$type = strtoupper($validation_field['native_type']);
|
|
$len = intval($validation_field['len']);
|
|
$meta = $validation_field;
|
|
} else {
|
|
$meta = $this->get_MySQL_meta_field($field, $this->table);
|
|
$type = (isset($meta['native_type']) ? $meta['native_type'] : '');
|
|
$len = $meta['len'];
|
|
}
|
|
|
|
switch ($type) { //This should be all uppercase input.
|
|
case 'SHORT': //Small INT
|
|
case 'INT24': //MED INT
|
|
case 'LONGLONG': //BIG INT or SERIAL is an alias for BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE.
|
|
case 'LONG': // Integers
|
|
if (!preg_match('/^[0-9]*$/', $value)) {
|
|
$this->do_verr("Failed Validation: NOT a digit {$type} {$field}");
|
|
return false;
|
|
} // Does not allow decimal numbers!!
|
|
if (strlen($value) > $len) {
|
|
$this->do_verr("Failed Validation: too long {$type} {$field}");
|
|
return false;
|
|
}
|
|
break;
|
|
case 'FLOAT':
|
|
if (strlen($value) > $len) {
|
|
$this->do_verr("Failed Validation: too long {$type} {$field}");
|
|
return false;
|
|
}
|
|
if (!is_float($value)) {
|
|
$this->do_verr("Failed Validation: NOT a float {$type} {$field}");
|
|
return false;
|
|
}
|
|
break;
|
|
case 'NEWDECIMAL':
|
|
$prec = intval($meta['precision']);
|
|
$maxlen = $len - $prec;
|
|
if (!\bs_tts\common::is_string_found($value, '.')) {
|
|
$this->do_verr("Failed Validation: No Decimal Found in field {$field}");
|
|
return false;
|
|
}
|
|
$x = explode('.', $value);
|
|
if (strlen($x[0]) >= ($maxlen - 1) || strlen($x[1]) > $prec) {
|
|
$this->do_verr("Failed Validation: too long {$type} {$field}");
|
|
return false;
|
|
}
|
|
break;
|
|
case 'DOUBLE':
|
|
if (strlen($value) > $len) {
|
|
$this->do_verr("Failed Validation: too long {$type} {$field}");
|
|
return false;
|
|
}
|
|
if (!is_double($value)) {
|
|
$this->do_verr("Failed Validation: NOT a double {$type} {$field}");
|
|
return false;
|
|
}
|
|
break;
|
|
case 'BLOB': // Text
|
|
if ($len == '4294967295' || $len == '16777215')
|
|
continue 2; //Too Big to process, 16777215 MEDIUMTEXT
|
|
if (strlen($value) > $len) {
|
|
$this->do_verr("Failed Validation: too long {$type} {$field}");
|
|
return false;
|
|
}
|
|
break;
|
|
case 'VAR_STRING': // VARCHAR or VARBINARY
|
|
case 'STRING': //CHAR or BINARY
|
|
if (strlen($value) > $len) {
|
|
$this->do_verr("Failed Validation: too long {$type} {$field}");
|
|
return false;
|
|
}
|
|
break;
|
|
case 'DATE':
|
|
if (!$this->is_valid_mysql_date($value)) {
|
|
$this->do_verr("Failed Validation: invalid date in {$field}");
|
|
return false;
|
|
}
|
|
break;
|
|
case 'TIME':
|
|
if (!$this->is_valid_mysql_time($value)) {
|
|
$this->do_verr("Failed Validation: invalid time in {$field}");
|
|
return false;
|
|
}
|
|
break;
|
|
case 'TIMESTAMP':
|
|
case 'DATETIME':
|
|
if (strlen($value) > $len) {
|
|
$this->do_verr("Failed Validation: too long {$type} {$field}");
|
|
return false;
|
|
}
|
|
if (!$this->is_valid_mysql_timestamp($value)) {
|
|
$this->do_verr("Failed Validation: invalid timestamp in {$field}");
|
|
return false;
|
|
}
|
|
break;
|
|
default: //TINYINT, Bit, Bool, or Year is the default for no meta data
|
|
//if (!is_Digits($value)) return false; //This fails so its commented out.
|
|
if ($len == 3) { // Tiny INT
|
|
if (intval($value) > 255) {
|
|
$this->do_verr("Failed Validation: too long {$type} {$field}");
|
|
return false;
|
|
}
|
|
if (intval($value) < -127) {
|
|
$this->do_verr("Failed Validation: too short {$type} {$field}");
|
|
return false;
|
|
}
|
|
} elseif ($len == 1) { // Bit or Bool
|
|
if (intval($value) > 9) {
|
|
$this->do_verr("Failed Validation: too long {$type} {$field}");
|
|
return false;
|
|
}
|
|
if (intval($value) < 0) {
|
|
$this->do_verr("Failed Validation: too short {$type} {$field}");
|
|
return false;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public function get_MySQL_meta_field(string $field, string $table): array {
|
|
$query = "SELECT `{$field}` FROM {$table} LIMIT 1";
|
|
$pdo_stmt = $this->pdo->prepare($query);
|
|
$pdo_stmt->execute();
|
|
return $pdo_stmt->getColumnMeta(0);
|
|
}
|
|
|
|
/**
|
|
* Check if valid timestamp/datetime
|
|
* @param type $Str
|
|
* @return type
|
|
*/
|
|
public function is_valid_mysql_timestamp(string $Str): bool {
|
|
$Stamp = strtotime($Str);
|
|
$Month = date('m', $Stamp);
|
|
$Day = date('d', $Stamp);
|
|
$Year = date('Y', $Stamp);
|
|
|
|
return checkdate($Month, $Day, $Year);
|
|
}
|
|
|
|
public function is_valid_mysql_date(string $str): bool {
|
|
$date_parts = explode('-', $str);
|
|
if (\main_tts\common::count($date_parts) != 3)
|
|
return false;
|
|
if ((strlen($date_parts[0]) != 4) || (!is_numeric($date_parts[0])))
|
|
return false;
|
|
if ((strlen($date_parts[1]) != 2) || (!is_numeric($date_parts[1])))
|
|
return false;
|
|
if ((strlen($date_parts[2]) != 2) || (!is_numeric($date_parts[2])))
|
|
return false;
|
|
if (!checkdate($date_parts[1], $date_parts[2], $date_parts[0]))
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
public function is_valid_mysql_time(string $str): bool {
|
|
return (strtotime($str) === false) ? false : true;
|
|
}
|
|
|
|
/**
|
|
* Helper function for validate mysql
|
|
* Will echo if not live error message
|
|
* If enabled will also log the error.
|
|
* @param string $msg error message
|
|
*/
|
|
private function do_verr(string $msg): void {
|
|
$this->error_message = $msg;
|
|
$exists = \main_tts\registry::get('di')->exists('log');
|
|
if ($exists && \main_tts\configure::get('database', 'log_validation_errors') === true) {
|
|
$log = \main_tts\registry::get('di')->get_service('log', ['validation_errors']);
|
|
$log->write($msg);
|
|
}
|
|
}
|
|
|
|
} |