Current File : /home/inlingua/public_html/crm/ninexb/wp-content/plugins/tablesome/includes/modules/myque/mysql.php |
<?php
namespace Tablesome\Includes\Modules\Myque;
// Refactor this class
// Query Builder for MySQL
if (!class_exists('\Tablesome\Includes\Modules\Myque\Mysql')) {
class Mysql
{
public $wpdb;
public $schema;
public function __construct()
{
global $wpdb;
$this->wpdb = $wpdb;
$this->schema = new \Tablesome\Includes\Lib\Table_Crud_WP\Schema();
}
public function create_table($table_name, $columns)
{
$column_names = array();
// error_log('columns : ' . print_r($columns, true));
foreach ($columns as $column) {
$name = "column_" . $column['id'];
$column_names[] = $name;
}
if (empty($table_name) || empty($columns)) {
error_log('create_table: $table_name or $columns is empty');
return false;
}
$query = "CREATE TABLE $table_name";
$query .= " ( ";
$query .= $this->schema->get_schema($column_names);
$query .= " ); ";
error_log('$query : ' . $query);
$result = $this->wpdb->query($query);
return $result;
}
public function insert_record($record, $table_name, $insert_args)
{
// error_log('insert_record $record : ' . print_r($record, true));
// error_log('insert_record $table_name : ' . print_r($table_name, true));
global $wpdb;
// For debugging purposes only
// $this->get_columns($table_name);
$response = '';
if (!isset($record) || is_null($record)) {
return 0;
}
$query = "INSERT INTO $table_name (";
$ii = 0;
if (count($record) == 0) {
return 0;
}
foreach ($record as $key => $cell) {
# code...
// $column_name = $this->get_column_name($cell);
$column_name = $key;
$query .= " `$column_name`";
// Add comma if not the last item
if ($ii < count($record) - 1) {
$query .= ",";
}
$ii++;
} // END of cell loop
$query .= ") SELECT ";
$ii = 0;
foreach ($record as $key => $value) {
# code...
// $value = $cell['value'];
$value = esc_sql($value);
$query .= " '$value'";
// Add comma if not the last item
if ($ii < count($record) - 1) {
$query .= ",";
}
$ii++;
} // END of cell loop
$query .= " ";
$enabled_prevent_duplication = isset($insert_args['enable_duplication_prevention']) && $insert_args['enable_duplication_prevention'] == 1 ? true : false;
$enabled_limit_submission = isset($insert_args['enable_submission_limit']) && $insert_args['enable_submission_limit'] == 1 ? true : false;
$submission_limit = isset($insert_args['max_allowed_submissions']) && !empty($insert_args['max_allowed_submissions']) ? intval($insert_args['max_allowed_submissions']) : 100;
$prevent_field_column = isset($insert_args['prevent_field_column']) ? $insert_args['prevent_field_column'] : "";
$can_add_prevent_query = ($enabled_prevent_duplication || $enabled_limit_submission);
if ($can_add_prevent_query) {
// WHERE clause
$query .= "FROM (SELECT COUNT(*) cnt FROM " . $table_name . ") sub";
$query .= " "; // space
$query .= "WHERE ";
if ($enabled_prevent_duplication && !empty($prevent_field_column) && isset($record[$prevent_field_column])) {
$query .= "NOT EXISTS (SELECT 1 FROM " . $table_name . " WHERE " . $prevent_field_column . " = '" . esc_sql($record[$prevent_field_column]) . "' ) ";
}
$query .= " "; // space
if ($enabled_prevent_duplication && $enabled_limit_submission) {
$query .= "AND ";
}
if ($enabled_limit_submission) {
$query .= "cnt < " . $submission_limit . ";";
}
}
// error_log('$query : ' . $query);
// Todo: Add wpdb->prepare() to $query
// Example: $wpdb->query( $wpdb->prepare($query) );
$insert_success_bool = $wpdb->query($query);
$inserted_record_id = $wpdb->insert_id;
// $inserted_record_id = $wpdb->query("SELECT LAST_INSERT_ID();");
// error_log('$inserted_record_id : ' . $inserted_record_id);
$record['record_id'] = $inserted_record_id;
// error_log('mysql->insert_record $record : ' . print_r($record, true));
return $record;
}
public function duplicate_column($args, $response = array())
{
global $wpdb;
$table_name = $wpdb->prefix . $args['table_name'];
$args['table_name'] = $table_name;
$source_column = $args['source_column'];
$target_column = $args['target_column'];
// Create New Column
$query = "ALTER TABLE $table_name ADD $target_column TEXT NOT NULL";
$response['new_column_created'] = $wpdb->query($query);
// Copy Data from Source Column to Target Column
$query = "UPDATE $table_name SET $target_column = $source_column";
error_log('$query : ' . $query);
$response['copied_column_records'] = $wpdb->query($query);
return $response;
}
public function get_row($record_id, $args)
{
if (empty($record_id)) {
return null;
}
$table_name = $args['table_name'];
$query = "select * from {$table_name} where id = {$record_id}";
$db_record = $this->wpdb->get_row($query);
if (is_wp_error($db_record)) {
error_log("get_record error:" . $db_record->get_error_message());
return null;
}
return $db_record;
}
public function get_rows($args)
{
// error_log(' Mysql $args : ' . print_r($args, true));
global $wpdb;
$table_name = $wpdb->prefix . $args['table_name'];
$args['table_name'] = $table_name;
$query = "SELECT * FROM $table_name";
if (isset($args['where'])) {
$query .= $this->convert_conditions_to_sql_string($args['where'], $table_name);
}
$query .= $this->orderby($args);
$query .= " LIMIT " . $args['limit'];
$result = $wpdb->get_results($query);
// error_log('Mysql->get_rows $query: ' . $query);
// error_log('Mysql->get_rows $result count: ' . count($result));
// error_log('Mysql->get_rows $result : ' . print_r($result, true));
return $result;
}
public function orderby($args)
{
$sql_string = " ORDER BY ";
$orderByArgs = [];
foreach ($args['orderby'] as $key => $value) {
$orderByArgs[] = $args['table_name'] . "." . $value;
}
// Looks like wptablesome_table_287.column_2, wptablesome_table_287.column_3 ....
$sql_string = $sql_string . implode(',', $orderByArgs);
$sql_string .= " " . $args['order'];
return $sql_string;
}
public function get_table_columns($table_name)
{
global $wpdb;
$table_name_escaped = esc_sql($table_name);
$sql = $this->wpdb->prepare("SHOW COLUMNS FROM %1s", $table_name_escaped);
// $query = "SHOW COLUMNS FROM $table_name";
$result = $wpdb->get_results($sql, 'ARRAY_A');
// error_log(' result: ' . print_r($result, true));
return $result;
}
public function does_column_exists($columns, $column_name)
{
foreach ($columns as $key => $column) {
if ($column['Field'] == $column_name) {
return true;
}
}
return false;
}
public function convert_conditions_to_sql_string($conditions, $table_name)
{
error_log('convert_conditions_to_sql_string: ');
// error_log('$conditions : ' . print_r($conditions, true));
$columns = $this->get_table_columns($table_name);
foreach ($conditions as $key => $condition) {
$column_name = $condition['operand_1'];
// Remove columns which are not in Table
if (!$this->does_column_exists($columns, $column_name)) {
unset($conditions[$key]);
continue;
}
if ($condition['operator'] == 'empty' || $condition['operator'] == 'is_empty') {
// Convert empty and not_empty to a condition_group
$conditions[$key] = $this->convert_condition_to_condition_group($condition, 'OR');
$new_condition = $condition;
$new_condition['operator'] = 'is_null';
array_push($conditions[$key]['conditions'], $new_condition);
}
if ($condition['operator'] == 'not_empty' || $condition['operator'] == 'is_not_empty') {
// Convert empty and not_empty to a condition_group
$conditions[$key] = $this->convert_condition_to_condition_group($condition, 'AND');
$new_condition = $condition;
$new_condition['operator'] = 'is_not_null';
array_push($conditions[$key]['conditions'], $new_condition);
}
}
error_log('$conditions : ' . print_r($conditions, true));
$count = count($conditions);
$ii = 0;
// Return if filter conditions are empty
if ($count <= 0) {
return "";
}
$sql_string = " WHERE ";
foreach ($conditions as $key => $condition) {
if (isset($condition['conditions'])) {
$sql_string .= $this->get_condition_group_sql($condition, $table_name);
} else {
$sql_string .= $this->get_single_condition_sql($condition, $table_name);
}
if ($ii < $count - 1) {
$sql_string .= " AND ";
}
$ii++;
}
$sql_string = rtrim($sql_string, ' AND ');
error_log('$sql_string : ' . $sql_string);
return $sql_string;
}
public function get_condition_group_sql($condition_group, $table_name)
{
error_log('$condition_group : ' . print_r($condition_group, true));
$sql_string = '';
$jj = 0;
$count = count($condition_group['conditions']);
// Return if filter conditions are empty
if ($count <= 0) {
return "";
}
$sql_string .= " ( ";
foreach ($condition_group['conditions'] as $key1 => $condition) {
$sql_string .= $this->get_single_condition_sql($condition, $table_name);
if ($jj < $count - 1) {
$sql_string .= isset($condition_group['relation']) ? " " . $condition_group['relation'] . " " : " AND ";
}
$jj++;
}
$sql_string .= " ) ";
return $sql_string;
}
public function convert_condition_to_condition_group($condition, $relation)
{
$condition_group = [
'conditions' => [
$condition,
],
'relation' => $relation,
];
return $condition_group;
}
public function get_single_condition_sql($condition, $table_name)
{
error_log('$condition : ' . print_r($condition, true));
$sql_string = '';
$condition = $this->condition_modifier($condition);
$operand1 = $condition['operand_1'];
$mysql_operator = $condition['mysql_operator'];
$operand2 = $condition['operand_2'];
error_log('$condition after : ' . print_r($condition, true));
if ($condition['data_type'] == 'datetime') {
// Todo: Detect operand2 format and convert to unix timestamp
$sql_string .= $this->date_statements($condition, $table_name);
// $sql_string .= "FROM_UNIXTIME(CAST($table_name.$operand1 / 1000 as UNSIGNED)) $mysql_operator '$operand2'";
} else if ($condition['data_type'] == 'number') {
$sql_string .= "CAST($table_name.$operand1 as UNSIGNED) $mysql_operator $operand2";
} else if ($condition['data_type'] == 'json') {
$sql_string .= "JSON_EXTRACT($table_name.$operand1, '$.value') $mysql_operator $operand2";
} else {
$sql_string .= "TRIM(" . $table_name . "." . $operand1 . ") " . $mysql_operator . " " . $operand2;
}
return $sql_string;
}
public function date_statements($condition, $table_name)
{
$sql_string = '';
$operand1 = $condition['operand_1'];
$mysql_operator = $condition['mysql_operator'];
$operand2 = $condition['operand_2'];
$operand2_meta = isset($condition['operand_2_meta']) ? $condition['operand_2_meta'] : '';
$operand1_date_format = isset($condition['operand_1_date_format']) ? $condition['operand_1_date_format'] : 'js_timestamp';
$operator = isset($condition['operator']) ? $condition['operator'] : '';
if ($condition['data_type'] != 'datetime') {
return $sql_string;
}
if ($operand2 == 'last_seven_days' || $operand2 == 'last_thirty_days' || $operand2 == 'last_n_days' || $operand2 == 'next_n_days') {
if ($mysql_operator == 'is' || $mysql_operator == '=') {
$mysql_operator = 'BETWEEN';
} else if ($mysql_operator == 'is_not' || $mysql_operator == '!=') {
$mysql_operator = 'NOT BETWEEN';
}
}
if ($operand1_date_format == "js_timestamp") {
$operand1_query_string = "FROM_UNIXTIME(CAST($table_name.$operand1 / 1000 as UNSIGNED))";
} else {
$operand1_query_string = $table_name . "." . $operand1;
}
// error_log('$mysql_operator : ' . $mysql_operator);
// error_log('date_statements $condition : ' . print_r($condition, true));
/* Special case for null and not null */
if ($operator == 'null' || $operator == 'not_null' || $operator == 'is_null' || $operator == 'is_not_null') {
$sql_string .= " $operand1_query_string $mysql_operator ";
return $sql_string;
}
if ($operand2 == 'today') {
$sql_string .= "DATE($operand1_query_string) $mysql_operator CURDATE()";
} else if ($operand2 == 'tomorrow') {
$sql_string .= "DATEDIFF($operand1_query_string, CURDATE()) $mysql_operator 1";
} else if ($operand2 == 'yesterday') {
$sql_string .= "DATEDIFF($operand1_query_string, CURDATE()) $mysql_operator -1";
} else if ($operand2 == 'last_seven_days') {
$sql_string .= "$operand1_query_string $mysql_operator CURDATE() - INTERVAL 7 DAY AND CURDATE()";
} else if ($operand2 == 'last_thirty_days') {
$sql_string .= "$operand1_query_string $mysql_operator CURDATE() - INTERVAL 30 DAY AND CURDATE()";
} else if ($operand2 == 'last_n_days') {
$operand2_meta = isset($operand2_meta) ? (int) $operand2_meta : 0;
$sql_string .= "$operand1_query_string $mysql_operator CURDATE() - INTERVAL $operand2_meta DAY AND CURDATE()";
} else if ($operand2 == 'next_n_days') {
$operand2_meta = isset($operand2_meta) ? (int) $operand2_meta : 0;
$sql_string .= "$operand1_query_string $mysql_operator CURDATE() AND CURDATE() + INTERVAL $operand2_meta DAY";
} else if ($operand2 == 'current_month') {
$sql_string .= "MONTH($operand1_query_string) $mysql_operator MONTH(CURRENT_DATE())";
} else if ($operand2 == 'current_year') {
$sql_string .= "YEAR($operand1_query_string) $mysql_operator YEAR(CURRENT_DATE())";
} else if ($operand2 == 'month') {
$sql_string .= "MONTH($operand1_query_string) $mysql_operator CAST($operand2_meta as UNSIGNED)";
} else if ($operand2 == 'year') {
$sql_string .= "YEAR($operand1_query_string) $mysql_operator CAST($operand2_meta as UNSIGNED)";
} else if ($operand2 == 'exact_date') {
$sql_string .= "DATE($operand1_query_string) $mysql_operator DATE(FROM_UNIXTIME(CAST($operand2_meta / 1000 as UNSIGNED)))";
} else {
$sql_string .= "DATE($operand1_query_string) $mysql_operator DATE(FROM_UNIXTIME(CAST($operand2 / 1000 as UNSIGNED)))";
}
return $sql_string;
}
public function condition_modifier($condition)
{
if ($this->is_general_condition($condition)) {
$condition = $this->general_condition_modifier($condition);
return $condition;
}
// Number and Datetime
$condition = $this->number_condition_modifier($condition);
// Text, RichText
$condition = $this->string_condition_modifier($condition);
error_log('$condition condition_modifier : ' . print_r($condition, true));
return $condition;
}
public function is_general_condition($condition)
{
$general_conditions = array('empty', 'is_empty', 'not_empty', 'is_not_empty', 'is_null', 'is_not_null');
return in_array($condition['operator'], $general_conditions);
}
public function general_condition_modifier($condition)
{
if ($condition['operator'] == 'empty' || $condition['operator'] == 'is_empty') {
$condition['operand_2'] = "''";
$condition['mysql_operator'] = "=";
} else if ($condition['operator'] == 'not_empty' || $condition['operator'] == 'is_not_empty') {
$condition['operand_2'] = "''";
$condition['mysql_operator'] = "<>";
} else if ($condition['operator'] == 'is_null') {
$condition['operand_2'] = "";
$condition['mysql_operator'] = "IS NULL";
} else if ($condition['operator'] == 'is_not_null') {
$condition['operand_2'] = "";
$condition['mysql_operator'] = "IS NOT NULL";
}
return $condition;
}
public function number_condition_modifier($condition)
{
// Allow only number and datetime
if ($condition['data_type'] != 'number' && $condition['data_type'] != 'datetime') {
return $condition;
}
$condition['mysql_operator'] = $condition['operator'];
return $condition;
}
public function string_condition_modifier($condition)
{
// Allow only text and json
if ($condition['data_type'] != 'text' && $condition['data_type'] != 'json') {
// $condition['mysql_operator'] = $condition['operator'];
return $condition;
}
error_log('$condition[operator] : ' . $condition['operator']);
if ($condition['operator'] == 'contains') {
$condition['operand_2'] = "%" . $condition['operand_2'] . "%";
$condition['mysql_operator'] = "LIKE";
} else if ($condition['operator'] == 'does_not_contain') {
$condition['operand_2'] = "%" . $condition['operand_2'] . "%";
$condition['mysql_operator'] = "NOT LIKE";
} else if ($condition['operator'] == 'starts_with') {
$condition['operand_2'] = $condition['operand_2'] . "%";
$condition['mysql_operator'] = "LIKE";
} else if ($condition['operator'] == 'ends_with') {
$condition['operand_2'] = "%" . $condition['operand_2'];
$condition['mysql_operator'] = "LIKE";
} else if ($condition['operator'] == 'is') {
$condition['operand_2'] = $condition['operand_2'];
$condition['mysql_operator'] = "=";
} else if ($condition['operator'] == 'is_not') {
$condition['operand_2'] = $condition['operand_2'];
$condition['mysql_operator'] = "<>";
} else {
$condition['mysql_operator'] = $condition['operator'];
}
//
// SHOULD ADD ' '
$condition['operand_2'] = "'" . $condition['operand_2'] . "'";
return $condition;
}
public function delete_table($table_id)
{
global $wpdb;
$table_name = TABLESOME_TABLE_NAME . '_' . $table_id;
$table_name = $wpdb->prefix . $table_name;
$query = "DROP TABLE IF EXISTS $table_name";
$result = $wpdb->query($query);
error_log('delete_table $result : ' . $result);
return $result;
}
public function empty_the_table($table_id)
{
global $wpdb;
$table_name = TABLESOME_TABLE_NAME . '_' . $table_id;
$table_name = $wpdb->prefix . $table_name;
$query = "DELETE FROM $table_name";
$result = $wpdb->query($query);
return $result;
}
} // END CLASS
}
//