File "WPDA_Simple_Form_Data.php"
Full Path: /home/vantageo/public_html/cache/cache/cache/cache/cache/.wp-cli/wp-content/plugins/wp-data-access/WPDataAccess/Simple_Form/WPDA_Simple_Form_Data.php
File size: 21.65 KB
MIME-type: text/x-php
Charset: utf-8
<?php
/**
* Suppress "error - 0 - No summary was found for this file" on phpdoc generation
*
* @package WPDataAccess\Simple_Form
*/
namespace WPDataAccess\Simple_Form;
use WPDataAccess\Connection\WPDADB;
use WPDataAccess\Data_Dictionary\WPDA_Dictionary_Exist;
use WPDataAccess\Data_Dictionary\WPDA_List_Columns;
use WPDataAccess\Plugin_Table_Models\WPDA_Table_Settings_Model;
use WPDataAccess\Utilities\WPDA_Message_Box;
use WPDataAccess\WPDA;
/**
* Class WPDA_Simple_Form_Data
*
* WPDA_Simple_Form_Data is responsible for data management. It queries the database, adds new records to tables
* and updates table data. Simple validations are performed based on information retrieved from the data dictionary.
*
* @author Peter Schulz
* @since 1.0.0
*/
class WPDA_Simple_Form_Data {
/**
* Database schema name
*
* @var string
*/
protected $schema_name;
/**
* Database table name
*
* @var string
*/
protected $table_name;
/**
* Reference to calling form
*
* @var WPDA_Simple_Form
*/
protected $calling_form;
/**
* Reference to column list
*
* @var WPDA_List_Columns
*/
protected $wpda_list_columns;
/**
* Default success message
*
* Is set in the constructor to support internationalization.
*
* @var string
*/
protected $wpda_success_msg;
/**
* Default failure message
*
* Is set in the constructor to support internationalization.
*
* @var string
*/
protected $wpda_failure_msg;
/**
* Handle to data dictionary object
*
* @var WPDA_Dictionary_Exist
*/
protected $wpda_data_dictionary;
/**
* WPDA_Simple_Form_Data constructor
*
* Check if table exists and access is granted.
*
* @param string $schema_name Database schema name.
* @param string $table_name Database table name.
* @param WPDA_List_Columns $wpda_list_columns Reference to column array.
* @param WPDA_Simple_Form $calling_form Reference to calling form.
* @param string $wpda_success_msg Message shown on success.
* @param string $wpda_failure_msg Message shown on failure.
*
* @since 1.0.0
*/
public function __construct(
$schema_name,
$table_name,
&$wpda_list_columns,
&$calling_form,
$wpda_success_msg,
$wpda_failure_msg
) {
$this->schema_name = $schema_name;
$this->table_name = $table_name;
// Table must exist and user must be authorized.
$this->wpda_data_dictionary = new WPDA_Dictionary_Exist($this->schema_name, $this->table_name);
if ( !$this->wpda_data_dictionary->table_exists() ) {
wp_die( __( 'ERROR: Invalid table name or not authorized' ) );
}
$this->calling_form = $calling_form;
$this->wpda_list_columns = $wpda_list_columns;
$this->wpda_success_msg = $wpda_success_msg;
$this->wpda_failure_msg = $wpda_failure_msg;
}
/**
* Create new record
*
* Nothing to do!
*
* @return null
* @since 1.0.0
*/
public function new_row() {
return null;
}
/**
* Add records to database table
*
* @return bool TRUE = record successfully added to table
* @since 1.0.0
*/
public function add_row() {
$column_values_to_be_inserted = null;
foreach ( $this->wpda_list_columns->get_table_columns() as $column ) {
if ( isset( $column['readonly'], $column['default'] ) ) {
$this->calling_form->insert_column_default( $column['column_name'], WPDA::convert_default_value( $column['default'] ) );
}
if ( $column['column_name'] === $this->wpda_list_columns->get_auto_increment_column_name() ) {
// Auto increment column is not added
} else {
if ( null === $this->calling_form->get_new_value( $column['column_name'] ) || '' === $this->calling_form->get_new_value( $column['column_name'] ) ) {
// Skip empty columns
} elseif ( 'date' === WPDA::get_type( $column['data_type'] ) || 'time' === WPDA::get_type( $column['data_type'] ) ) {
// Convert date and time values
$column_values_to_be_inserted[$column['column_name']] = self::convert_datetime( $column['data_type'], $this->calling_form->get_new_value( $column['column_name'] ) );
} else {
// Add value
$column_values_to_be_inserted[$column['column_name']] = $this->calling_form->get_new_value( $column['column_name'] );
}
}
}
$wpdadb = WPDADB::get_db_connection( $this->schema_name );
if ( null === $wpdadb ) {
wp_die( sprintf( __( 'ERROR - Remote database %s not available', 'wp-data-access' ), esc_attr( $this->schema_name ) ) );
}
$result = $wpdadb->insert( $this->table_name, $column_values_to_be_inserted );
// db call ok; no-cache ok.
if ( 1 === $result ) {
$msg = new WPDA_Message_Box(array(
'message_text' => $this->wpda_success_msg,
));
$msg->box();
// If inserted record contains an auto_increment column: return value.
if ( false !== $this->wpda_list_columns->get_auto_increment_column_name() ) {
return $wpdadb->insert_id;
// Return auto_increment value.
} else {
return true;
// Return true = transaction succeeded.
}
} else {
// An error occurred.
$msg = new WPDA_Message_Box(array(
'message_text' => ( '' === $wpdadb->last_error ? $this->wpda_failure_msg : $this->wpda_failure_msg . ' [' . $wpdadb->last_error . ']' ),
'message_type' => 'error',
'message_is_dismissible' => false,
));
$msg->box();
return false;
// Return false = transaction failed.
}
}
/**
* Get record from database table
*
* @param int $auto_increment_value Auto increment number (returned if provided by dbms).
* @param string $wpda_err Error message to be shown on failure.
*
* @return mixed
* @since 1.0.0
*/
public function get_row( $auto_increment_value, $wpda_err ) {
$settings_db = WPDA_Table_Settings_Model::query( $this->table_name, $this->schema_name );
if ( isset( $settings_db[0]['wpda_table_settings'] ) ) {
$settings_db_custom = json_decode( $settings_db[0]['wpda_table_settings'] );
if ( isset( $settings_db_custom->table_settings->row_level_security ) && 'true' === $settings_db_custom->table_settings->row_level_security ) {
// Check access
$wp_nonce = ( isset( $_REQUEST['rownonce'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['rownonce'] ) ) : '' );
// input var okay.
$keys = '';
foreach ( $this->wpda_list_columns->get_table_primary_key() as $key ) {
$keys .= "-{$key}-" . $this->calling_form->get_new_value( $key );
}
// Check action from list table
if ( !wp_verify_nonce( $wp_nonce, "wpda-row-level-security-{$this->table_name}{$keys}" ) ) {
// Check action from data entry form (standard behaviour)
$wp_nonce = ( isset( $_REQUEST['_wpnonce'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['_wpnonce'] ) ) : '' );
// input var okay.
if ( !wp_verify_nonce( $wp_nonce, $this->calling_form->get_nonce_action() ) ) {
wp_die( __( 'ERROR: Not authorized', 'wp-data-access' ) );
}
}
}
}
$wpdadb = WPDADB::get_db_connection( $this->schema_name );
if ( null === $wpdadb ) {
wp_die( sprintf( __( 'ERROR - Remote database %s not available', 'wp-data-access' ), esc_attr( $this->schema_name ) ) );
}
$table_columns = array();
// Get all table columns.
foreach ( $this->wpda_list_columns->get_table_columns() as $column ) {
$table_columns[$column['column_name']] = $column['data_type'];
}
$where = '';
// Compose where clause.
$use_primary_key = true;
if ( $auto_increment_value < 1 ) {
foreach ( $this->wpda_list_columns->get_table_primary_key() as $pk_column ) {
if ( '' === $this->calling_form->get_new_value( $pk_column ) ) {
$use_primary_key = false;
}
}
}
if ( isset( $_REQUEST['child_request'] ) && 'TRUE' === $_REQUEST['child_request'] && $auto_increment_value > -1 ) {
// Special case:
// - parent-child relation based on non-primary key parent column
// - parent primary key is auto increment
// - child primary key is auto increment
// - insert record
$use_primary_key = true;
}
if ( $use_primary_key ) {
foreach ( $this->wpda_list_columns->get_table_primary_key() as $pk_column ) {
$where_current = ( '' === $where ? ' where ' : ' and ' );
if ( WPDA::get_type( $table_columns[$pk_column] ) === 'number' ) {
// Column data type is numeric:
// For numeric columns we need to omit quotes. All numeric values will be handled as float. MySQL
// will automatically convert them if necessary. Values supplied in a wrong format will be handed
// over to MySQL as is and might result in unpredictable results. For our simple form we rely on
// the user's judgement.
$where_current .= " `{$pk_column}` = %d";
} else {
// Column data type is string:
// Quotes will be added to all non-numeric values. We might have issues with date and time fields.
// For our simple form we'll accept that limitation (at least for now).
$where_current .= " `{$pk_column}` = %s";
}
if ( $auto_increment_value > -1 && $pk_column === $this->wpda_list_columns->get_auto_increment_column_name() ) {
// For inserts with auto_increment columns use $wpdadb->insert_id.
$pkvalue = $auto_increment_value;
} else {
if ( 0 === $wpda_err ) {
// No errors: use new value.
if ( $this->calling_form->get_new_value( $pk_column ) === '' ) {
wp_die( __( 'ERROR: Wrong arguments [missing primary key value]', 'wp-data-access' ) );
}
$pkvalue = $this->calling_form->get_new_value( $pk_column );
} else {
// There are errors: use old values (in case a key value was changed).
if ( $this->calling_form->get_old_value( $pk_column ) === '' ) {
wp_die( __( 'ERROR: Wrong arguments [missing primary key value]', 'wp-data-access' ) );
}
$pkvalue = $this->calling_form->get_old_value( $pk_column );
}
}
if ( WPDA::get_type( $table_columns[$pk_column] ) === 'date' || WPDA::get_type( $table_columns[$pk_column] ) === 'time' ) {
// Convert date and time values
$pkvalue = self::convert_datetime( $table_columns[$pk_column], $pkvalue, $pkvalue );
}
$where .= $wpdadb->prepare( $where_current, $pkvalue );
// phpcs:ignore Standard.Category.SniffName.ErrorCode
}
} else {
$alternative_key_found = false;
// Check for alternative keys
foreach ( $this->wpda_list_columns->get_table_alternative_keys() as $alternative_keys ) {
foreach ( $alternative_keys as $alternative_key ) {
$alternative_keys_found = 0;
if ( $this->calling_form->get_new_value( $alternative_key ) !== '' ) {
$where_current = ( '' === $where ? ' where ' : ' and ' );
if ( WPDA::get_type( $table_columns[$alternative_key] ) === 'number' ) {
$where_current .= " `{$alternative_key}` = %f";
} else {
$where_current .= " `{$alternative_key}` = %s";
}
$pkvalue = $this->calling_form->get_new_value( $alternative_key );
$alternative_keys_found++;
}
}
if ( $alternative_keys_found === count( $alternative_keys ) ) {
//phpcs:ignore - 8.1 proof
$alternative_key_found = true;
}
}
if ( !$alternative_key_found ) {
wp_die( __( 'ERROR: Wrong arguments [missing key value]', 'wp-data-access' ) );
}
$where .= $wpdadb->prepare( $where_current, $pkvalue );
// phpcs:ignore Standard.Category.SniffName.ErrorCode
}
if ( '' === $this->schema_name ) {
$query = "\n\t\t\t\t\tselect *\n\t\t\t\t\tfrom `{$this->table_name}`\n\t\t\t\t\t{$where}\n\t\t\t\t";
} else {
$query = "\n\t\t\t\t\tselect *\n\t\t\t\t\tfrom `{$wpdadb->dbname}`.`{$this->table_name}`\n\t\t\t\t\t{$where}\n\t\t\t\t";
}
$result = $wpdadb->get_results( $query, 'ARRAY_A' );
// phpcs:ignore Standard.Category.SniffName.ErrorCode
if ( 1 === $wpdadb->num_rows ) {
return $result;
} else {
wp_die( __( 'ERROR: Wrong arguments [no data found]', 'wp-data-access' ) );
}
}
/**
* Update current record (write changes to database)
*
* @since 1.0.0
*/
public function set_row() {
$wpdadb = WPDADB::get_db_connection( $this->schema_name );
if ( null === $wpdadb ) {
wp_die( sprintf( __( 'ERROR - Remote database %s not available', 'wp-data-access' ), esc_attr( $this->schema_name ) ) );
}
$column_values_to_be_updated = null;
foreach ( $this->wpda_list_columns->get_table_columns() as $column ) {
if ( isset( $column['readonly'] ) ) {
$this->calling_form->revert_column_value( $column['column_name'] );
continue;
}
if ( $this->calling_form->get_old_value( $column['column_name'] ) !== $this->calling_form->get_new_value( $column['column_name'] ) ) {
if ( 'number' === WPDA::get_type( $column['data_type'] ) && '' === $this->calling_form->get_new_value( $column['column_name'] ) ) {
// Convert empty numeric value to null
$column_values_to_be_updated[$column['column_name']] = null;
} else {
if ( 'time' === WPDA::get_type( $column['data_type'] ) || 'date' === WPDA::get_type( $column['data_type'] ) ) {
// Convert date and time values
$column_values_to_be_updated[$column['column_name']] = self::convert_datetime( $column['data_type'], $this->calling_form->get_new_value( $column['column_name'] ) );
} else {
$new_value = $this->calling_form->get_new_value( $column['column_name'] );
if ( '' !== $new_value ) {
$column_values_to_be_updated[$column['column_name']] = $this->calling_form->get_new_value( $column['column_name'] );
} else {
if ( isset( $column['is_nullable'] ) && 'YES' === $column['is_nullable'] ) {
$column_values_to_be_updated[$column['column_name']] = null;
} else {
$column_values_to_be_updated[$column['column_name']] = $this->calling_form->get_new_value( $column['column_name'] );
}
}
}
}
}
}
if ( null === $column_values_to_be_updated ) {
// Nothing to update.
if ( $_REQUEST['wpda_message'] && '' !== $_REQUEST['wpda_message'] ) {
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput
// Happens when inserting new row on parent child page
$msgtxt = sanitize_text_field( wp_unslash( $_REQUEST['wpda_message'] ) );
// input var okay.
} else {
$msgtxt = __( 'Nothing to save', 'wp-data-access' );
}
$msg = new WPDA_Message_Box(array(
'message_text' => $msgtxt,
));
$msg->box();
} else {
// Write changes to database.
$where = array();
foreach ( $this->wpda_list_columns->get_table_primary_key() as $pk_column ) {
$action = $this->calling_form->get_form_action();
$action2 = $this->calling_form->get_form_action2();
if ( 'edit' === $action && 'save' === $action2 ) {
// Form was submitted after update: use old key value to build where clause.
if ( '' === $this->calling_form->get_old_value( $pk_column ) ) {
wp_die( __( 'ERROR: Wrong arguments [missing primary key value]', 'wp-data-access' ) );
}
$where[$pk_column] = $this->calling_form->get_old_value( $pk_column );
// Set primary keys value(s).
$data_type = $this->wpda_list_columns->get_column_data_type( $pk_column );
if ( 'time' === $data_type || 'date' === $data_type ) {
// Convert date and time values
$where[$pk_column] = self::convert_datetime( $data_type, $where[$pk_column] );
}
} else {
// Form submitted a new record: use new value (no old value available).
if ( $this->calling_form->get_new_value( $pk_column ) === '' ) {
wp_die( __( 'ERROR: Wrong arguments [missing primary key value]', 'wp-data-access' ) );
}
$where[$pk_column] = $this->calling_form->get_new_value( $pk_column );
// Set primary keys value(s).
}
}
// var_dump($column_values_to_be_updated);
$result = $wpdadb->update( $this->table_name, $column_values_to_be_updated, $where );
// db call ok; no-cache ok.
if ( 1 === $result ) {
// Since we are updating by key, result must be exactly 1 record.
$msg = new WPDA_Message_Box(array(
'message_text' => $this->wpda_success_msg,
));
$msg->box();
} else {
if ( 0 === $result && '' === $wpdadb->last_error ) {
$table_info = WPDA::get_table_values( $this->schema_name, $this->table_name );
if ( 1 === count( $table_info ) && 'connect' === strtolower( $table_info[0]['engine'] ) ) {
//phpcs:ignore - 8.1 proof
// Connect engine does not return number of rows updated
// Presuming update was successful when no error message was returned
$msg = new WPDA_Message_Box(array(
'message_text' => $this->wpda_success_msg,
));
$msg->box();
return;
}
// Nothing to update.
$msg = new WPDA_Message_Box(array(
'message_text' => __( 'Nothing to save', 'wp-data-access' ),
));
$msg->box();
} else {
// An error occurred.
$msg = new WPDA_Message_Box(array(
'message_text' => ( '' === $wpdadb->last_error ? $this->wpda_failure_msg : $this->wpda_failure_msg . ' [' . $wpdadb->last_error . ']' ),
'message_type' => 'error',
'message_is_dismissible' => false,
));
$msg->box();
}
}
}
}
public static function convert_datetime( $column_type, $column_value, $error_value = null ) {
if ( null === $column_value || '' === $column_value ) {
return null;
}
switch ( $column_type ) {
case 'time':
$date_format = WPDA::get_option( WPDA::OPTION_PLUGIN_TIME_FORMAT );
$db_format = WPDA::DB_TIME_FORMAT;
break;
case 'date':
$date_format = WPDA::get_option( WPDA::OPTION_PLUGIN_DATE_FORMAT );
$db_format = WPDA::DB_DATE_FORMAT;
break;
default:
$date_format = WPDA::get_option( WPDA::OPTION_PLUGIN_DATE_FORMAT ) . ' ' . WPDA::get_option( WPDA::OPTION_PLUGIN_TIME_FORMAT );
$db_format = WPDA::DB_DATETIME_FORMAT;
}
$convert_date = \DateTime::createFromFormat( $date_format, $column_value );
if ( false !== $convert_date ) {
$converted_value = $convert_date->format( $db_format );
} else {
$converted_value = $error_value;
}
return $converted_value;
}
}