<?php
namespace Fury\Modules\ThinBuilder;
/**
* trait ThinBuilderProcessing
* @author Eugene Sukhodolskiy <eugene.sukhodolskiy@gmail.com>
* @version 0.1
* Update at 18.08.2022
*/
trait ThinBuilderProcessing{
protected $pdo;
protected $db_config;
protected $history;
protected $history_enabled;
protected $driver;
protected $gen_sql_only = false;
public function __construct($db_config, $driver = null, $history_enabled = true){
$this -> db_config = $db_config;
$this -> pdo = $this -> create_connect($this -> db_config);
$this -> driver = $driver;
$this -> history_enabled = $history_enabled;
if($this -> history_enabled){
$this -> create_history_instance();
}
}
protected function create_history_instance(){
$this -> history = new History();
}
public function beginTransaction(): bool {
return $this -> pdo -> beginTransaction();
}
public function commit(): bool {
return $this -> pdo -> commit();
}
public function rollBack(): bool {
return $this -> pdo -> rollBack();
}
public function inTransaction(): bool {
return $this -> pdo -> inTransaction();
}
protected function create_connect($db_conf){
if(($db_conf['dblib'] ?? '') === 'sqlite'){
$dblib = "sqlite:" . ($db_conf['dbname'] ?? ':memory:');
$pdo = new \PDO($dblib);
} else {
$dblib = "{$db_conf['dblib']}:host={$db_conf['host']};dbname={$db_conf['dbname']};charset={$db_conf['charset']}";
$pdo = new \PDO($dblib, $db_conf['user'], $db_conf['password']);
}
$pdo -> setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
return $pdo;
}
protected function validate_identifier(String $name): String {
if(preg_match('/^[a-zA-Z0-9_]+$/', $name) !== 1){
throw new \Exception("Invalid SQL identifier: {$name}");
}
return $name;
}
protected function escape_string_in_arr($arr){
$result = [];
foreach ($arr as $key => $value) {
if(!is_array($value)){
$result[addslashes($key)] = addslashes($value);
}else{
$result[addslashes($key)] = $this -> escape_string_in_arr($value);
}
}
return $result;
}
protected function select_data_preprocessing($fields, $where, $order_fields, $limit){
// FIELDS PREPROCESSING
if(count($fields)){
foreach ($fields as $f) {
$this -> validate_identifier($f);
}
$fields_sql = '`' . implode('`,`', $fields) . '`';
}else{
$fields_sql = '*';
}
// ORDER PREPROCESSING
if(count($order_fields)){
foreach ($order_fields as $f) {
$this -> validate_identifier($f);
}
$order_sql = 'ORDER BY `' . implode("`,`", $order_fields) . '`';
}else{
$order_sql = '';
}
// WHERE PREPROCESSING
list($where_sql, $where_params) = $this -> where_processing($where);
// LIMIT PREPROCESSING
if(count($limit)){
$limit_sql = 'LIMIT ' . implode(',', array_map('intval', $limit));
}else{
$limit_sql = '';
}
return [$fields_sql, $where_sql, $order_sql, $limit_sql, $where_params];
}
protected function normalize_where($where) {
if(!count($where)){
return [];
}
// Если первый элемент — не массив и не логический оператор,
// значит where передан как плоский массив одного условия: ['field', '=', 'value']
if(!is_array($where[0]) && !in_array(strtoupper($where[0]), ['AND', 'OR'])) {
if(count($where) === 2) {
return [ [$where[0], '=', $where[1]] ];
}
return [ [$where[0], $where[1], $where[2]] ];
}
return $where;
}
protected function where_processing($where){
$where = $this -> normalize_where($where);
if(!count($where)){
return ['', []];
}
$sql_parts = [];
$params = [];
foreach ($where as $i => $w_item) {
if(is_array($w_item)){
if(count($w_item) === 2){
$w_item = [$w_item[0], '=', $w_item[1]];
}
$field = "`" . $this -> validate_identifier($w_item[0]) . "`";
$operator = strtoupper($w_item[1]);
if($operator == 'IN'){
$placeholders = array_fill(0, count($w_item[2]), '?');
$sql_parts[] = "{$field} IN (" . implode(',', $placeholders) . ")";
$params = array_merge($params, $w_item[2]);
} else {
$sql_parts[] = "{$field} {$operator} ?";
$params[] = $w_item[2];
}
} else {
$sql_parts[] = $w_item;
}
}
$sql = 'WHERE ' . implode(' ', $sql_parts);
return [$sql, $params];
}
}