<?php
/**
* Suppress "error - 0 - No summary was found for this file" on phpdoc generation
*
* @package WPDataAccess\Simple_Form
*/
namespace WPDataAccess\Simple_Form;
use WPDataAccess\Data_Dictionary\WPDA_List_Columns;
use WPDataAccess\Plugin_Table_Models\WPDA_Media_Model;
use WPDataAccess\Plugin_Table_Models\WPDA_Table_Settings_Model;
use WPDataAccess\Utilities\WPDA_Message_Box;
use WPDataAccess\WPDA;
use WPDataAccess\Dashboard\WPDA_Dashboard;
/**
* Class WPDA_Simple_Form
*
* Generates a simple dynamic data entry form on request. Data entry form consists of the following components:
* + WPDA_Simple_Form (layout management)
* + WPDA_Simple_Form_Data (data management)
* + WPDA_Simple_Form_Item (data item management)
* + WPDA_Simple_Form_Type_Icon (data type icon)
*
* Simple forms can be generated for tables only. It is not possible to generate simple forms for views.
*
* Simple forms can be generated for tables with a primary key only. For tables that do not have a primary key it
* is not possible to generate a simple form as records in the table cannot be recognized uniquely.
*
* Primary key fields are disable in update mode. This is to prevent inconsistency. Use method
* {@see WPDA_Simple_Form::set_update_keys()} to allow updating primary key items. Make sure you understand to
* consequences!!!
*
* @author Peter Schulz
* @since 1.0.0
*/
class WPDA_Simple_Form {
/**
* Static id to create unique form names on the page
*
* @var int
*/
protected static $form_id = 0;
/**
* Warning icon
*/
const WARNING_ICON = '<span class="dashicons dashicons-warning"></span> ';
/**
* Form id
*
* @var int
*/
protected $current_form_id;
/**
* Page title
*
* @var string
*/
protected $title = null;
/**
* Add action to page title?
*
* @var string TRUE = add action
*/
protected $add_action_to_title;
/**
* Page subtitle
*
* @var string
*/
protected $subtitle = '';
/**
* Page fieldset title
*
* @var string
*/
protected $fieldset_title = '';
/**
* Hides warning update text
*
* @var string TRUE = hide warning (overwrites plugin settings)
*/
protected $no_warning_update_text = 'FALSE';
/**
* Database schema name
*
* @var string
*/
protected $schema_name;
/**
* Database table name
*
* @var string
*/
protected $table_name;
/**
* Handle to data management component
*
* @var WPDA_Simple_Form_Data
*/
protected $row_data;
/**
* Handle to database record
*
* @var object
*/
protected $row;
/**
* Handle to WPDA_List_Columns
*
* @var WPDA_List_Columns
*/
protected $wpda_list_columns;
/**
* Access column names
*
* @var array
*/
protected $table_columns;
/**
* Access column headers
*
* @var array
*/
protected $table_column_headers;
/**
* Display column headers
*
* @var array
*/
protected $table_column_header;
/**
* Column headers (labels, arguments)
*
* @var array
*/
protected $column_headers;
/**
* Form items
*
* @var array
*/
protected $form_items = array();
/**
* Form items named array
*
* Use this array to quickly find an item in the form
*
* @var array
*/
protected $form_items_named = array();
/**
* Form items old values (if applicable)
*
* @var array
*/
protected $form_items_old_values = array();
/**
* Form items new values (if applicable)
*
* @var array
*/
protected $form_items_new_values = array();
/**
* Menu slug current page
*
* @var string
*/
protected $page;
/**
* Primary page action
*
* @var string
*/
protected $action;
/**
* Secondary page action
*
* @var string
*/
protected $action2 = '';
/**
* Auto increment value
*
* @var int
*/
protected $auto_increment_value = -1;
/**
* Defines it keys are updatable
*
* @var bool
*/
protected $update_keys_allowed = false;
/**
* Error message number
*
* @var int
*/
protected $wpda_err = 0;
/**
* Error message text
*
* @var string
*/
protected $wpda_msg = '';
/**
* Indicates whether the title should be displayed or not
*
* @var bool
*/
protected $show_title = true;
/**
* Indicates whether the back button should be displayed or not
*
* @var bool
*/
protected $show_back_button = true;
/**
* Indicates whether the back icon in the title should be displayed or not
*
* @var bool
*/
protected $show_back_icon = true;
/**
* Indicates whether table type should be checked to display subtitle.
*
* @var bool
*/
protected $check_table_type = true;
/**
* Page number item name (default 'page_number')
*
* The name can be changed for pages on multiple levels. This is needed to get back to the right page in
* parent-child page.
*
* @var string
*/
protected $page_number_item_name = 'page_number';
/**
* Real page number
*
* @var null
*/
protected $page_number_link = '';
/**
* Page number text item
*
* @var null
*/
protected $page_number_item = '';
/**
* Used to changed button text
*
* @var string
*/
protected $back_to_list_text = '';
/**
* Table settings (taken from plugin table settings table)
*
* @var mixed|null
*/
protected $wpda_table_settings = null;
/**
* Show help icon if help url is available
*
* @var null|string
*/
protected $help_url = null;
/**
* Hide Add New button
*
* @var null|string
*/
protected $hide_add_new = false;
/**
* Group items into fieldsets
*
* @var array
*/
protected $fieldsets = array();
/**
* WPDA_Simple_Form constructor
*
* Performs the following steps:
* + Check if requested action is allowed
* + Check if table is provided
* + Save OLD and NEW request values
* + Create WPDA_Simple_Form_Data object
*
* @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 array $args Messages (named array).
*
* @since 1.0.0
*
* @see WPDA_Simple_Form_Data
*/
public function __construct(
$schema_name,
$table_name,
&$wpda_list_columns,
$args = array()
) {
// Get page and handling arguments.
if ( isset( $_REQUEST['page'] ) ) {
$this->page = sanitize_text_field( wp_unslash( $_REQUEST['page'] ) );
// input var okay.
} else {
wp_die( __( 'ERROR: Wrong arguments [missing page argument]', 'wp-data-access' ) );
}
if ( isset( $_REQUEST['action'] ) ) {
// Possible values: "new", "edit" and "view".
$this->action = sanitize_text_field( wp_unslash( $_REQUEST['action'] ) );
// input var okay.
} else {
if ( isset( $args['action'] ) ) {
$this->action = $args['action'];
} else {
wp_die( __( 'ERROR: Wrong arguments [missing action argument]', 'wp-data-access' ) );
}
}
if ( isset( $_REQUEST['action2'] ) ) {
$this->action2 = sanitize_text_field( wp_unslash( $_REQUEST['action2'] ) );
// input var okay.
}
$this->schema_name = $schema_name;
$this->table_name = $table_name;
if ( '' === $this->table_name ) {
// Without a table name it makes no sense to continue.
wp_die( __( 'ERROR: Wrong arguments [missing table_name argument]' ) );
}
if ( !WPDA::is_wpda_table( $this->table_name ) ) {
// Check access rights for tables that do not belong to the plugin.
if ( 'on' !== WPDA::get_option( WPDA::OPTION_BE_ALLOW_INSERT ) && 'new' === $this->action ) {
// Insert not allowed.
wp_die( __( 'ERROR: Not authorized', 'wp-data-access' ) );
}
if ( 'on' !== WPDA::get_option( WPDA::OPTION_BE_VIEW_LINK ) && 'view' === $this->action ) {
// Viewing not allowed.
wp_die( __( 'ERROR: Not authorized', 'wp-data-access' ) );
}
if ( 'on' !== WPDA::get_option( WPDA::OPTION_BE_ALLOW_UPDATE ) && 'edit' === $this->action ) {
// Update not allowed.
wp_die( __( 'ERROR: Not authorized', 'wp-data-access' ) );
}
}
// Get columns information.
$this->wpda_list_columns = $wpda_list_columns;
$this->table_columns = $this->wpda_list_columns->get_table_columns();
$this->table_column_headers = $this->wpda_list_columns->get_table_column_headers();
// Set page title.
if ( isset( $args['title'] ) ) {
$this->title = $args['title'];
$this->add_action_to_title = true;
if ( isset( $args['add_action_to_title'] ) && 'FALSE' === $args['add_action_to_title'] ) {
$this->add_action_to_title = false;
}
}
// Set page subtitle.
if ( isset( $args['subtitle'] ) ) {
$this->subtitle = $args['subtitle'];
} else {
if ( $this->check_table_type ) {
global $wpdb;
$wp_tables = $wpdb->tables( 'all', true );
if ( isset( $wp_tables[substr( $this->table_name, strlen( $wpdb->prefix ) )] ) ) {
$this->subtitle = self::WARNING_ICON . WPDA::get_table_type_text( WPDA::TABLE_TYPE_WP );
} elseif ( WPDA::is_wpda_table( $this->table_name ) ) {
$this->subtitle = self::WARNING_ICON . WPDA::get_table_type_text( WPDA::TABLE_TYPE_WPDA );
}
}
}
if ( isset( $args['no_warning_update_text'] ) ) {
$this->no_warning_update_text = $args['no_warning_update_text'];
}
// Add customizable success and failure messages to support i18n.
// This allows to overwrite message in classes extending WPDA_Simple_Form.
$args = wp_parse_args( $args, array(
'wpda_success_msg' => __( 'Succesfully saved changes to database', 'wp-data-access' ),
'wpda_failure_msg' => __( 'Saving changes to database failed', 'wp-data-access' ),
'show_title' => true,
'show_back_button' => true,
'show_back_icon' => true,
) );
// Get arguments from URL (old and new values).
$this->get_url_arguments();
// Add data object for DML.
$this->row_data = new WPDA_Simple_Form_Data(
$this->schema_name,
$this->table_name,
$this->wpda_list_columns,
$this,
$args['wpda_success_msg'],
$args['wpda_failure_msg']
);
$this->current_form_id = 'wpda_simple_form_' . self::$form_id++;
if ( isset( $args['show_title'] ) ) {
$this->show_title = $args['show_title'];
}
if ( isset( $args['show_back_button'] ) ) {
$this->show_back_button = $args['show_back_button'];
}
if ( isset( $args['show_back_icon'] ) ) {
$this->show_back_icon = $args['show_back_icon'];
}
// Overwrite column header text if column headers were provided.
$this->column_headers = ( isset( $args['column_headers'] ) ? $args['column_headers'] : '' );
// Get current page number of list table
if ( 'page_number' !== $this->page_number_item_name ) {
if ( isset( $_REQUEST['page_number'] ) ) {
$requested_page_number = sanitize_text_field( wp_unslash( $_REQUEST['page_number'] ) );
// input var okay.
$this->page_number_link = '&page_number=' . $requested_page_number;
$this->page_number_item = "<input type='hidden' name='page_number' value='{$requested_page_number}'/>";
}
}
if ( isset( $_REQUEST[$this->page_number_item_name] ) ) {
$requested_page_number = sanitize_text_field( wp_unslash( $_REQUEST[$this->page_number_item_name] ) );
// input var okay.
$this->page_number_link .= '&paged=' . $requested_page_number;
$this->page_number_item .= "<input type='hidden' name='" . $this->page_number_item_name . "' value='{$requested_page_number}'/>";
}
// Add search arguments to link to return to same page
foreach ( $_REQUEST as $key => $value ) {
if ( substr( $key, 0, 19 ) === 'wpda_search_column_' ) {
$this->page_number_link .= "&{$key}={$value}";
$this->page_number_item .= "<input type='hidden' name='{$key}' value='{$value}' />";
}
}
// Check if button text "back to list" should be changed
if ( isset( $args['back_to_list_text'] ) && '' !== $args['back_to_list_text'] ) {
$this->back_to_list_text = $args['back_to_list_text'];
} else {
$this->back_to_list_text = __( 'List', 'wp-data-access' );
}
// Get table settings
$wpda_table_settings = WPDA_Table_Settings_Model::query( $this->table_name, $this->schema_name );
if ( isset( $wpda_table_settings[0]['wpda_table_settings'] ) ) {
$this->wpda_table_settings = json_decode( $wpda_table_settings[0]['wpda_table_settings'] );
}
if ( isset( $args['help_url'] ) ) {
$this->help_url = $args['help_url'];
}
if ( isset( $args['hide_add_new'] ) ) {
$this->hide_add_new = $args['hide_add_new'];
}
global $wpda_project_mode;
if ( isset( $wpda_project_mode['allow_insert'] ) && 'only' === $wpda_project_mode['allow_insert'] ) {
$this->hide_add_new = true;
}
}
/**
* Get URL arguments.
*
* @since 1.5.0
*/
protected function get_url_arguments() {
// Get OLD and NEW values for all items.
foreach ( $this->wpda_list_columns->get_table_columns() as $column ) {
if ( isset( $_REQUEST[$column['column_name'] . '_old'] ) ) {
$this->form_items_old_values[$column['column_name']] = wp_unslash( $_REQUEST[$column['column_name'] . '_old'] );
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput
}
if ( isset( $_REQUEST[$column['column_name']] ) ) {
if ( is_array( $_REQUEST[$column['column_name']] ) ) {
$column_array = '';
foreach ( $_REQUEST[$column['column_name']] as $column_value ) {
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput
$column_array .= wp_unslash( $column_value ) . ',';
}
if ( '' !== $column_array ) {
$this->form_items_new_values[$column['column_name']] = substr( $column_array, 0, strlen( $column_array ) - 1 );
}
} else {
$this->form_items_new_values[$column['column_name']] = wp_unslash( $_REQUEST[$column['column_name']] );
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput
}
}
}
}
/**
* Prepare form items and handle transactions
*
* Performs the following steps:
* + Checks for posted data
* + Saves changes if applicable (displays success or failure message)
* + Prepares simple form
*
* @param bool $allow_save
*/
public function prepare_form( $allow_save = true ) {
$set_back_form_values = false;
if ( $allow_save && ('new' === $this->action || 'edit' === $this->action) && 'save' === $this->action2 ) {
// Security check (is action allowed?).
$wp_nonce = ( isset( $_REQUEST['_wpnonce'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['_wpnonce'] ) ) : '' );
// input var okay.
if ( !wp_verify_nonce( $wp_nonce, $this->get_nonce_action() ) ) {
wp_die( __( 'ERROR: Not authorized', 'wp-data-access' ) );
}
if ( 'new' === $this->action ) {
// Prepare row and items for validation
$this->row = $this->row_data->new_row();
$this->prepare_items( true );
// Save new record.
if ( !$this->validate( true ) ) {
$set_back_form_values = true;
} else {
// Insert record.
$add_row_result = $this->row_data->add_row();
if ( $add_row_result ) {
// Insert succeeded:
// (1) save auto_increment value (if applicable)
// (2) change action to edit
if ( is_numeric( $add_row_result ) ) {
// save auto_increment value (1).
$this->auto_increment_value = $add_row_result;
}
// change action to edit (2).
$this->action = 'edit';
$this->prepare_row();
} else {
// Insert failed:
// (1) set back form items
$set_back_form_values = true;
}
}
} else {
// Prepare row and items for validation
$this->row = $this->row_data->get_row( $this->auto_increment_value, $this->wpda_err );
$this->prepare_items( true );
// Update existing record.
if ( $this->validate() ) {
// Update record.
$this->row_data->set_row();
// Get values updated from database triggers
$this->row = $this->row_data->get_row( $this->auto_increment_value, $this->wpda_err );
foreach ( $this->form_items_new_values as $key => $value ) {
if ( isset( $this->row[0][$key] ) ) {
$this->form_items_new_values[$key] = $this->row[0][$key];
}
}
}
$this->prepare_row();
$set_back_form_values = true;
}
} else {
$this->prepare_row();
}
$this->prepare_items( $set_back_form_values );
if ( '1' === $this->wpda_err && $this->update_keys_allowed && 'edit' === $this->action && 'save' === $this->action2 ) {
$keys_have_changed = false;
// There was an error! If key updates are allowed, we might have needed to set back the keys to their
// original values. We'll inform the user with a message box.
foreach ( $this->wpda_list_columns->get_table_primary_key() as $pk_column ) {
if ( $this->get_old_value( $pk_column ) !== $this->get_new_value( $pk_column ) ) {
$keys_have_changed = true;
break;
}
}
if ( $keys_have_changed ) {
$msg = new WPDA_Message_Box(array(
'message_text' => __( 'Key columns have been reversed to their original values', 'wp-data-access' ),
));
$msg->box();
}
}
if ( null === $this->title ) {
if ( 'new' === $this->action ) {
$action_in_title = __( 'Add new row to', 'wp-data-access' );
} else {
$action_in_title = ucfirst( $this->action );
}
$this->title = $action_in_title . ' ' . __( 'table', 'wp-data-access' ) . ' ' . strtoupper( $this->table_name );
} else {
if ( 'new' === $this->action ) {
$title_action = 'Add New ';
} else {
$title_action = ucfirst( $this->action );
}
if ( $this->add_action_to_title ) {
$this->title = $title_action . ' ' . $this->title;
}
}
if ( is_admin() && ($this->page === \WP_Data_Access_Admin::PAGE_MAIN || substr( $this->page, 0, 13 ) === \WP_Data_Access_Admin::PAGE_EXPLORER) ) {
$this->fieldset_title = $this->title;
$this->title = 'Data Explorer';
}
}
/**
* Overwrite to group items into fieldsets
*/
protected function add_fieldsets() {
$fields = array();
foreach ( $this->form_items as $item ) {
$fields[] = $item->get_item_name();
}
// Add just one default fieldset which contains all fields
$this->fieldsets[$this->fieldset_title] = array(
'id' => '',
'fields' => $fields,
);
}
/**
* Show simple form
*
* Performs the following steps:
* + Shows simple form for requested table (HTML and Javascript)
*
* @param boolean $allow_save Allow to save data
* @param string $add_param Parameter to be added to form action.
*
* @since 1.0.0
*/
public function show( $allow_save = true, $add_param = '' ) {
$this->add_fieldsets();
// Prepare url
if ( is_admin() ) {
$url = "?page={$this->page}";
} else {
$url = '';
}
$url_back = $url;
$url .= $add_param;
?>
<div class="wrap">
<?php
if ( $this->show_title ) {
?>
<h1 class="wp-heading-inline">
<?php
if ( is_admin() && $this->show_back_icon ) {
?>
<a
href="javascript:void(0)"
onclick="jQuery('#<?php
echo esc_attr( $this->current_form_id );
?>_backbutton').submit()"
class="dashicons dashicons-arrow-left-alt2 wpda_tooltip"
title="<?php
echo esc_attr( $this->back_to_list_text );
?>"
></a>
<?php
}
?>
<?php
echo esc_attr( $this->title );
?>
<?php
if ( substr( $this->page, 0, 13 ) === \WP_Data_Access_Admin::PAGE_EXPLORER || !is_admin() ) {
// Button is available on web pages only
if ( 'view' !== $this->action && !$this->hide_add_new ) {
//phpcs:ignore - 8.1 proof
if ( WPDA::is_wpda_table( $this->table_name ) || ('on' === WPDA::get_option( WPDA::OPTION_BE_ALLOW_INSERT ) && count( $this->wpda_list_columns->get_table_primary_key() )) > 0 ) {
$title = __( 'Add new row to table', 'wp-data-access' );
?>
<form
method="post"
action="<?php
echo esc_attr( $url );
?>"
style="display: inline-block; vertical-align: bottom;"
>
<div>
<?php
if ( is_admin() ) {
// Hide schema and table name on front-end
?>
<input type="hidden" name="wpdaschema_name" value="<?php
echo esc_attr( $this->schema_name );
?>">
<input type="hidden" name="table_name" value="<?php
echo esc_attr( $this->table_name );
?>">
<?php
}
?>
<input type="hidden" name="action" value="new">
<button type="submit" class="page-title-action wpda_tooltip"
title="<?php
echo esc_attr( $title );
?>"
>
<i class="fas fa-plus-circle wpda_icon_on_button"></i>
<?php
echo __( 'Add New', 'wp-data-access' );
?>
</button>
</div>
</form>
<?php
}
}
}
?>
</h1>
<div class="wpda_subtitle"><strong><?php
echo wp_kses( $this->subtitle, array(
'span' => array(
'class' => array(),
),
) );
?></strong>
</div>
<?php
// Add custom code before the data entry form
do_action_ref_array( 'wpda_before_simple_form', array($this) );
?>
<p></p>
<?php
}
?>
<form id="<?php
echo esc_attr( $this->current_form_id );
?>"
method="post" enctype="multipart/form-data"
action="<?php
echo esc_attr( $url );
?>">
<div>
<?php
$js_code = '';
// All column JS code will be stored here and added to the end of the form.
foreach ( $this->fieldsets as $fieldset_title => $fieldset ) {
if ( isset( $fieldset['id'] ) && '' !== trim( $fieldset['id'] ) ) {
$id = trim( $fieldset['id'] );
} else {
$id = '';
}
$expandable = ( isset( $fieldset['expandable'] ) && true === $fieldset['expandable'] ? true : false );
$expandable_state = ( isset( $_REQUEST["wpda_fieldset_expand_{$id}"] ) ? sanitize_text_field( $_REQUEST["wpda_fieldset_expand_{$id}"] ) : 'off' );
$expandable_icons = ( 'on' === $expandable_state ? 'minus-circle' : 'plus-circle' );
?>
<fieldset class="wpda_fieldset">
<?php
if ( '' !== $fieldset_title ) {
?>
<legend <?php
echo ( '' === $id ? '' : 'id="' . esc_attr( $id ) . '"' );
?>>
<?php
if ( $expandable && '' !== $id ) {
echo '<div class="wpda-fieldset-expand" onclick="expandFieldset(\'' . esc_attr( $id ) . '\')">' . '<i id="wpda_field_expand_' . esc_attr( $id ) . '" class="wpda-fieldset-expand fas fa-' . esc_attr( $expandable_icons ) . '"></i> ' . '<span class="wpda-fieldset-expand">' . esc_html( $fieldset_title ) . '</span>' . '<input type="hidden" id="wpda_fieldset_expand_' . esc_attr( $id ) . '" name="wpda_fieldset_expand_' . esc_attr( $id ) . '" value="' . esc_attr( $expandable_state ) . '" />' . '</div>';
} else {
echo esc_html( $fieldset_title );
}
?>
</legend>
<?php
}
?>
<table id="wpda_table_expand_<?php
echo esc_attr( $id );
?>"
class="wpda_simple_table <?php
echo esc_attr( $this->table_name );
?>"
<?php
echo ( $expandable && 'off' === $expandable_state ? 'style="display: none"' : '' );
?>
cellspacing="0"
cellpadding="0"
>
<?php
$fieldset_columns = array_flip( $fieldset['fields'] );
//phpcs:ignore - 8.1 proof
foreach ( $this->form_items as $item ) {
if ( isset( $fieldset_columns[$item->get_item_name()] ) ) {
$item->show( $this->action, $this->update_keys_allowed );
$js_code .= $item->get_item_js();
// Add column specific JS code.
}
}
?>
</table>
</fieldset>
<?php
}
?>
</div>
<div><?php
$this->add_form_logic();
?></div>
<?php
// Add custom code after the data entry form
do_action_ref_array( 'wpda_after_simple_form', array($this) );
?>
<p></p>
<?php
if ( is_admin() ) {
// Hide schema and table name on front-end
?>
<input type="hidden" name="wpdaschema_name" value="<?php
echo esc_attr( $this->schema_name );
?>">
<input type="hidden" name="table_name" value="<?php
echo esc_attr( $this->table_name );
?>">
<?php
}
?>
<input type="hidden" name="action" value="<?php
echo esc_attr( $this->action );
?>"/>
<input type="hidden" name="action2" value="save"/>
<input type="hidden" name="wpda_message" value=""/>
<?php
if ( 'view' !== $this->action ) {
?>
<input type="hidden" name="postaction" id="postaction" value=""/>
<?php
}
?>
<?php
$this->add_parent_args();
echo $this->page_number_item;
// phpcs:ignore WordPress.Security.EscapeOutput
echo $this->add_case_sensitive_search();
wp_nonce_field( $this->get_nonce_action( false ), '_wpnonce', false );
?>
<?php
if ( 'view' !== $this->action ) {
?>
<button type="submit"
class="button button-primary"
name="submit_button"
onclick="return submit_form(event)">
<i class="fas fa-check wpda_icon_on_button"></i>
<?php
echo __( 'Submit', 'wp-data-access' );
?>
</button>
<?php
if ( $this->show_back_button && $this->show_back_icon ) {
?>
<button type="submit"
class="button button-secondary"
name="submit_button"
onclick="return submit_form(event)">
<i class="fas fa-check wpda_icon_on_button"></i>
<?php
echo __( 'Submit', 'wp-data-access' );
?>
<i class="fas fa-angle-right wpda_icon_on_button"></i>
<?php
echo esc_attr( $this->back_to_list_text );
?>
</button>
<?php
}
if ( $this->show_back_button ) {
?>
<button type="button"
onclick="jQuery('#<?php
echo esc_attr( $this->current_form_id );
?>_backbutton').submit();"
class="button button-secondary">
<i class="fas fa-angle-left wpda_icon_on_button"></i>
<?php
echo esc_attr( $this->back_to_list_text );
?>
</button>
<?php
}
?>
<span style="float:right;"><?php
$this->add_buttons();
?></span>
<?php
}
?>
<?php
if ( 'view' === $this->action ) {
?>
<button type="button"
onclick="jQuery('#<?php
echo esc_attr( $this->current_form_id );
?>_backbutton').submit()"
class="button button-secondary">
<i class="fas fa-angle-left wpda_icon_on_button"></i>
<?php
echo esc_attr( $this->back_to_list_text );
?>
</button>
<?php
}
?>
</form>
<form id="<?php
echo esc_attr( $this->current_form_id );
?>_backbutton"
method="post" style="display:none"
action="<?php
echo esc_attr( $url_back );
?>">
<?php
$this->add_parent_args();
echo $this->page_number_item;
// phpcs:ignore WordPress.Security.EscapeOutput
echo $this->add_case_sensitive_search();
?>
<?php
if ( is_admin() ) {
// Hide schema and table name on front-end
?>
<input type="hidden" name="wpdaschema_name" value="<?php
echo esc_attr( $this->schema_name );
?>">
<input type="hidden" name="table_name" value="<?php
echo esc_attr( $this->table_name );
?>">
<?php
}
?>
<input type="hidden" name="action" value="list">
</form>
</div>
<script type='text/javascript'>
<?php
if ( 'view' !== $this->action ) {
?>
function submit_form(e) {
if (typeof pre_submit_form === "function") {
// Perform pre submit
pre_submit = pre_submit_form();
if (!pre_submit) {
return false;
}
}
if (
jQuery(e.target).hasClass("button-secondary") ||
jQuery(e.target).parent().hasClass("button-secondary")
) {
<?php
if ( 'child_page_number' === $this->page_number_item_name ) {
?>
jQuery("#postaction").val("childlist");
<?php
} else {
?>
jQuery("#postaction").val("list");
<?php
}
?>
} else {
jQuery("#postaction").val("");
}
var failed = false;
jQuery('.wpda_not_null').each(function(i, obj) {
if (jQuery(obj).val() === '') {
objData = jQuery(obj).data();
if (objData.dbIsNull===undefined || objData.dbIsNull!==false) {
alert(<?php
echo __( '\'Item\'', 'wp-data-access' );
?> +' ' + jQuery(obj).attr('name') + ' ' + <?php
echo __( '\'must be entered\'', 'wp-data-access' );
?>);
failed = true;
} else {
element_old = jQuery("input[name=" + jQuery(obj).attr("name") + "_old" + "]");
if (element_old && element_old.val()!=='') {
alert(<?php
echo __( '\'Item\'', 'wp-data-access' );
?> +' ' + jQuery(obj).attr('name') + ' ' + <?php
echo __( '\'must be entered\'', 'wp-data-access' );
?>);
failed = true;
}
}
}
});
jQuery('.wpda_input_error').each(function(i, obj) {
alert(<?php
echo __( '\'Column\'', 'wp-data-access' );
?> +' ' + jQuery(obj).attr('name') + <?php
echo __( '\': max size exceeded\'', 'wp-data-access' );
?>);
failed = true;
});
jQuery('.wpda_hyperlink').each(function(i, obj) {
hyperlink_name = jQuery(obj).attr('name');
hyperlink_label = jQuery('#' + hyperlink_name + '_label').val();
hyperlink_url = jQuery('#' + hyperlink_name + '_url').val();
hyperlink_target = jQuery('#' + hyperlink_name + '_target').is(':checked') ? '_blank' : '';
hyperlink_update = {
"label" : hyperlink_label,
"url" : hyperlink_url,
"target" : hyperlink_target
};
jQuery(obj).val(JSON.stringify(hyperlink_update));
});
return !failed;
}
<?php
}
?>
jQuery(function () {
<?php
if ( 'view' === $this->action ) {
?>
jQuery("#<?php
echo esc_attr( $this->current_form_id );
?> input").not(':button').prop("readonly", true);
jQuery("#<?php
echo esc_attr( $this->current_form_id );
?> textarea").prop("readonly", true);
jQuery("#<?php
echo esc_attr( $this->current_form_id );
?> select").prop("disabled", true);
<?php
}
?>
<?php
if ( !$this->update_keys_allowed && 'new' !== $this->action ) {
?>
jQuery("#<?php
echo esc_attr( $this->current_form_id );
?> input.wpda_primary_key").prop("readonly", true);
jQuery("#<?php
echo esc_attr( $this->current_form_id );
?> select.wpda_primary_key").prop("disabled", true);
<?php
}
?>
<?php
if ( 'new' === $this->action ) {
?>
jQuery("#<?php
echo esc_attr( $this->current_form_id );
?> input.auto_increment").prop("readonly", true);
<?php
}
?>
jQuery("#<?php
echo esc_attr( $this->current_form_id );
?> input.wpda_readonly").prop("readonly", true);
jQuery('.wpda_data_type_number').on('keyup paste', function () {
numberFormat = jQuery(this).data('numberFormat').split(",");
this.value = this.value.replace(/[^\d\-]/g, ''); // Allow only 0-9
if (isNaN(this.value) || (numberFormat[0]!='' && this.value.length>numberFormat[0])) {
jQuery(this).addClass('wpda_input_error');
if (this.value.length>numberFormat[0]) {
jQuery.notify('<?php
echo __( 'Max size exceeded' );
?>','error');
}
} else {
jQuery(this).removeClass('wpda_input_error');
}
});
jQuery('.wpda_data_type_float').on('keyup paste', function () {
numberFormat = jQuery(this).data('numberFormat').split(",");
maxNumber = Math.pow(10, numberFormat[0] - numberFormat[1]);
this.value = this.value.replace(/[^\d\-\.\,]/g, ''); // Allow only 0-9 . ,
if (isNaN(this.value) || this.value>=maxNumber) {
jQuery(this).addClass('wpda_input_error');
if (this.value>=maxNumber) {
jQuery.notify('<?php
echo __( 'Max size exceeded' );
?>','error');
}
} else {
jQuery(this).removeClass('wpda_input_error');
}
currentNumber = this.value.split(".");
if (currentNumber.length===1) {
currentNumber = this.value.split(",");
}
if (currentNumber.length===2 && currentNumber[1].length>numberFormat[1]) {
jQuery(this).addClass('wpda_input_error');
jQuery.notify('<?php
echo __( 'Max size exceeded' );
?>','error');
}
});
jQuery( '.wpda_tooltip' ).tooltip();
// Add toolbar icons
jQuery("#wpda_toolbar_icon_add_row").on("click", function() {
jQuery("#wpda_new_row_table_name").val("<?php
echo esc_attr( $this->table_name );
?>");
jQuery("#wpda_new_row").submit();
});
});
<?php
echo $js_code;
// phpcs:ignore WordPress.Security.EscapeOutput
?>
</script>
<?php
}
private function add_case_sensitive_search() {
if ( isset( $_REQUEST['wpda_c'] ) && 'true' === $_REQUEST['wpda_c'] ) {
return '<input type="hidden" name="wpda_c" value="true">';
} else {
return '';
}
}
/**
* Overwrite to add logic to form
*
* @since 2.0.15
*/
public function add_form_logic() {
}
/**
* Overwrite to add buttons to right bottom
*
* @since 2.0.15
*/
public function add_buttons() {
}
/**
* Creates a wpnonce action
*
* Set wp_nonce action for security check:
* prefix + table name + primary key values
*
* @param boolean $use_old_value TRUE = use old key values, FALSE = use new key values.
*
* @return string wp_nonce action holding: prefix + table name + primary key values.
* @since 1.0.0
*/
public function get_nonce_action( $use_old_value = true ) {
// Add prefix + table name to wp_nonce action.
$wp_nonce_action = "wpda-simple-form-{$this->table_name}";
if ( $this->wpda_list_columns->get_table_alternative_keys() ) {
$wp_nonce_action .= '-*';
} else {
foreach ( $this->wpda_list_columns->get_table_primary_key() as $pk_column ) {
// Add primary key value to wp_nonce action.
if ( 'new' === $this->action ) {
// New records have no key values on form startup.
$wp_nonce_action .= '-?';
} else {
// Add primary key value to wp_nonce action.
if ( 'save' === $this->action2 && $use_old_value ) {
// Use old value (in cases where primary key update is allowed).
$wp_nonce_action .= ( isset( $_REQUEST[$pk_column . '_old'] ) ? '-' . sanitize_text_field( wp_unslash( $_REQUEST[$pk_column . '_old'] ) ) : '-?' );
// input var okay.
} else {
if ( isset( $_REQUEST[$pk_column] ) && '' !== sanitize_text_field( wp_unslash( $_REQUEST[$pk_column] ) ) ) {
// input var okay.
// Use new value.
$wp_nonce_action .= '-' . sanitize_text_field( wp_unslash( $_REQUEST[$pk_column] ) );
// input var okay.
} elseif ( -1 !== $this->auto_increment_value ) {
// Use auto increment value (updated wp_nonce action after insert).
$wp_nonce_action .= '-' . $this->auto_increment_value;
} else {
// No value found, let security check handle wrong wp_nonce action.
$wp_nonce_action .= '-?';
}
}
}
}
}
return str_replace( ' ', '_', $wp_nonce_action );
}
/**
* Perform validation check
*
* Called to perform default validation before insert and update.
*
* Extend class WPDA_Simple_Form and override this method if you need validation on insert and/or update or
* if you prefer to change error messages. If you want to handle inserts and updates differently, the
* following information might be helpful:
* + on insert: $this->action = 'new'
* + on update: $this->action = 'edit'
*
* Use set_message to show messages (info as well as error).
*
* @param boolean $pre_insert Do not check auto_increment during pre-insert
*
* @return boolean TRUE = validation succeeded, FALSE = validation failed.
* @since 1.0.0
*/
protected function validate( $pre_insert = false ) {
foreach ( $this->form_items as $item ) {
if ( !$item->is_valid( $pre_insert ) ) {
return false;
}
}
return true;
}
/**
* Get current from database table
*
* Handle insert, update and save differently.
*
* @since 1.0.0
*/
protected function prepare_row() {
if ( 'edit' === $this->action || 'view' === $this->action || 'save' === $this->action2 ) {
// Get record by primary key, use auto_increment for new records.
$this->row = $this->row_data->get_row( $this->auto_increment_value, $this->wpda_err );
} else {
// There's no record yet.
$this->row = $this->row_data->new_row();
}
}
/**
* Set item attributes
*
* If you want to change the layout of your simple form(s), consider to extend class WPDA_Simple_Form and
* override this method.
*
* @param boolean $set_back_form_values TRUE = set back user entered value, FALSE = set to database value.
*
* @since 1.0.0
*/
protected function prepare_items( $set_back_form_values = false ) {
$count_cols = count( $this->table_columns );
//phpcs:ignore - 8.1 proof
for ($i = 0; $i < $count_cols; $i++) {
$column_name = $this->table_columns[$i]['column_name'];
$item_enum = '';
if ( 'enum' === $this->table_columns[$i]['data_type'] || 'set' === $this->table_columns[$i]['data_type'] ) {
$item_enum = $this->table_columns[$i]['column_type'];
}
if ( $set_back_form_values ) {
// Set value to what user entered.
$item_value = $this->get_new_value( $column_name );
} else {
// Get value from database.
$item_value = ( isset( $this->row ) ? $this->row[0][$column_name] : null );
}
$wpda_simple_form_item_class = 'WPDataAccess\\Simple_Form\\WPDA_Simple_Form_Item';
$check_data_type = WPDA::get_type( $this->table_columns[$i]['data_type'] );
if ( 'enum' === $this->table_columns[$i]['data_type'] ) {
$wpda_simple_form_item_class = 'WPDataAccess\\Simple_Form\\WPDA_Simple_Form_Item_Enum';
} elseif ( 'set' === $this->table_columns[$i]['data_type'] ) {
$wpda_simple_form_item_class = 'WPDataAccess\\Simple_Form\\WPDA_Simple_Form_Item_Set';
} elseif ( 'date' === $check_data_type || 'time' === $check_data_type ) {
$wpda_simple_form_item_class = 'WPDataAccess\\Simple_Form\\WPDA_Simple_Form_Item_DateTime';
// Always initially use database data and time format
$item_value = ( isset( $this->row ) ? $this->row[0][$column_name] : null );
} elseif ( 'tinytext' === $this->table_columns[$i]['data_type'] || 'text' === $this->table_columns[$i]['data_type'] || 'mediumtext' === $this->table_columns[$i]['data_type'] || 'longtext' === $this->table_columns[$i]['data_type'] ) {
$wpda_simple_form_item_class = 'WPDataAccess\\Simple_Form\\WPDA_Simple_Form_Item_Textarea';
} elseif ( 'tinyint(1)' === $this->table_columns[$i]['column_type'] ) {
$wpda_simple_form_item_class = 'WPDataAccess\\Simple_Form\\WPDA_Simple_Form_Item_Boolean';
}
// Media support only available to logged-in users
if ( 0 < WPDA::get_current_user_id() ) {
$media_type = WPDA_Media_Model::get_column_media( $this->table_name, $column_name, $this->schema_name );
if ( 'Image' === $media_type ) {
$wpda_simple_form_item_class = 'WPDataAccess\\Simple_Form\\WPDA_Simple_Form_Item_Image';
} elseif ( 'Attachment' === $media_type ) {
$wpda_simple_form_item_class = 'WPDataAccess\\Simple_Form\\WPDA_Simple_Form_Item_Media';
} elseif ( 'Hyperlink' === $media_type ) {
if ( !(isset( $this->wpda_table_settings->table_settings->hyperlink_definition ) && 'text' === $this->wpda_table_settings->table_settings->hyperlink_definition) ) {
$wpda_simple_form_item_class = 'WPDataAccess\\Simple_Form\\WPDA_Simple_Form_Item_Hyperlink';
}
} elseif ( 'Audio' === $media_type ) {
$wpda_simple_form_item_class = 'WPDataAccess\\Simple_Form\\WPDA_Simple_Form_Item_Audio';
} elseif ( 'Video' === $media_type ) {
$wpda_simple_form_item_class = 'WPDataAccess\\Simple_Form\\WPDA_Simple_Form_Item_Video';
} elseif ( 'File' === $media_type ) {
$wpda_simple_form_item_class = 'WPDataAccess\\Simple_Form\\WPDA_Simple_Form_Item_File';
}
}
$item_label = '';
if ( isset( $this->column_headers[$column_name] ) ) {
$item_label = $this->column_headers[$column_name];
} elseif ( isset( $this->table_column_headers[$column_name] ) ) {
$item_label = $this->table_column_headers[$column_name];
}
$item = new $wpda_simple_form_item_class(array(
'item_name' => $column_name,
'data_type' => $this->table_columns[$i]['data_type'],
'item_label' => $item_label,
'item_value' => $item_value,
'item_default_value' => $this->table_columns[$i]['column_default'],
'item_extra' => $this->table_columns[$i]['extra'],
'item_enum' => $item_enum,
'column_type' => $this->table_columns[$i]['column_type'],
'is_nullable' => $this->table_columns[$i]['is_nullable'],
'user_update' => $set_back_form_values,
'character_maximum_length' => $this->table_columns[$i]['character_maximum_length'],
'numeric_precision' => $this->table_columns[$i]['numeric_precision'],
'numeric_scale' => ( null === $this->table_columns[$i]['numeric_scale'] ? 0 : $this->table_columns[$i]['numeric_scale'] ),
));
$item->set_is_key_column( $this->is_key_column( $column_name ) );
$this->add_form_item( $i, $item );
}
// Add dynamic hyperlinks (if applicable)
if ( isset( $this->wpda_table_settings->hyperlinks ) ) {
foreach ( $this->wpda_table_settings->hyperlinks as $hyperlink ) {
$hyperlink_label = ( isset( $hyperlink->hyperlink_label ) ? $hyperlink->hyperlink_label : '' );
$hyperlink_form = ( isset( $hyperlink->hyperlink_form ) ? $hyperlink->hyperlink_form : false );
$hyperlink_html = ( isset( $hyperlink->hyperlink_html ) ? $hyperlink->hyperlink_html : '' );
if ( true === $hyperlink_form && $hyperlink_label !== '' && $hyperlink_html !== '' ) {
$hyperlink_target = ( isset( $hyperlink->hyperlink_form ) ? $hyperlink->hyperlink_target : false );
foreach ( $this->form_items as $item ) {
$item_name = $item->get_item_name();
$item_value = $item->get_item_value();
$hyperlink_html = str_replace( "\$\${$item_name}\$\$", $item_value, $hyperlink_html );
}
$item = new WPDA_Simple_Form_Item_Dynamic_Hyperlink(array(
'item_name' => $hyperlink_label,
'data_type' => 'varchar2',
'hyperlink_label' => $hyperlink_label,
'hyperlink_target' => $hyperlink_target,
'hyperlink_html' => $hyperlink_html,
));
$this->add_form_item( $i++, $item );
}
}
}
}
/**
* Get new value for item
*
* Or empty if no new value available.
*
* @param string $column_name Column name.
*
* @return mixed|string New value for column or empty.
* @since 1.0.0
*/
public function get_new_value( $column_name ) {
return ( isset( $this->form_items_new_values[$column_name] ) ? $this->form_items_new_values[$column_name] : null );
}
/**
* Add item to form
*
* @param int $index Item sequence number.
* @param WPDA_Simple_Form_Item $item Reference to simple form item.
*
* @since 1.0.0
*
* @see WPDA_Simple_Form_Item
*/
protected function add_form_item( $index, $item ) {
// Add item to form
$this->form_items[$index] = $item;
// Add position to named array for quick access of single items
$item_name = $item->get_item_name();
$this->form_items_named[$item_name] = $index;
}
/**
* Get item position
*
* @param string $item_name Form item name
*
* @return bool|int Position item or false if not found
*
* @since 2.0.15
*/
protected function get_item_index( $item_name ) {
if ( isset( $this->form_items_named[$item_name] ) ) {
return $this->form_items_named[$item_name];
} else {
return false;
}
}
/**
* Get old value form item
*
* Or empty if no old value available.
*
* @param string $column_name Column name.
*
* @return mixed|string Old value for column or empty.
* @since 1.0.0
*/
public function get_old_value( $column_name ) {
return ( isset( $this->form_items_old_values[$column_name] ) ? $this->form_items_old_values[$column_name] : null );
}
public function revert_column_value( $column_name ) {
@($this->form_items_new_values[$column_name] = $this->form_items_old_values[$column_name]);
}
public function insert_column_default( $column_name, $item_default_value ) {
if ( isset( $this->form_items_old_values ) ) {
@($this->form_items_new_values[$column_name] = $item_default_value);
}
}
/**
* Is column part of primary key?
*
* @param string $column_name Column name.
*
* @return bool TRUE = column is part of primary key, FALSE = column is not part of primary key.
* @since 1.0.0
*/
protected function is_key_column( $column_name ) {
foreach ( $this->wpda_list_columns->get_table_primary_key() as $pk_column ) {
if ( $column_name === $pk_column ) {
return true;
}
}
return false;
}
/**
* Get primary form action
*
* @return string Primary page action
* @since 1.0.0
*/
public function get_form_action() {
return $this->action;
}
/**
* Get secondary form action
*
* @return string Secondary page action
* @since 1.0.0
*/
public function get_form_action2() {
return $this->action2;
}
/**
* Defines whether primary key item can be updated
*
* @param boolean $update_keys_allowed Allow keys to be updated.
*
* @since 1.0.0
*/
protected function set_update_keys( $update_keys_allowed ) {
$this->update_keys_allowed = $update_keys_allowed;
}
/**
* Reorder columns
*
* Reorders the column array in the order as defined in argument $columns_ordered.
*
* @param array $columns_ordered Ordered column names.
*
* @since 1.0.0
*/
protected function order_and_filter_columns( $columns_ordered ) {
$column_array_ordered = array();
$i = 0;
foreach ( $columns_ordered as $key => $value ) {
$column_array_ordered[$i++] = $this->table_columns[$this->get_column_position( $this->table_columns, $value )];
}
$this->table_columns = $column_array_ordered;
}
/**
* Get column position in column array
*
* @param array $column_array Column array.
* @param string $column_name Column name.
*
* @return int Position of $column_name in $column_array
* @since 1.0.0
*/
protected function get_column_position( $column_array, $column_name ) {
if ( !is_array( $column_array ) ) {
return -1;
}
$count_cols = count( $column_array );
//phpcs:ignore - 8.1 proof
for ($i = 0; $i < $count_cols; $i++) {
if ( $column_array[$i]['column_name'] === $column_name ) {
return $i;
}
}
return -1;
}
/**
* Add dummy column to form
*
* @param string $column_name Column name.
*
* @since 1.0.0
*/
protected function add_dummy_column( $column_name ) {
$this->table_columns[] = array(
'column_name' => $column_name,
'data_type' => 'varchar',
'extra' => '',
'column_type' => '',
'is_nullable' => 'YES',
'column_default' => '',
);
}
/**
* Set message number and text
*
* Assigns values to $this->wpda_err and $this->wpda_msg.
*
* @param string $wpda_err '0' = INFO, '1' = ERROR.
* @param string $wpda_msg Message to be displayed.
*
* @since 1.0.0
*/
protected function set_message( $wpda_err, $wpda_msg ) {
// Wrong values will be handled by message box class.
$this->wpda_err = $wpda_err;
$this->wpda_msg = $wpda_msg;
}
/**
* Use this method to build parent child relationships.
*
* Overwrite this function if you want to use the form as a child form related to some parent
* form. You can add parent arguments to calls to make sure you get back to the right parent.
*
* @since 1.5.0
*/
protected function add_parent_args() {
}
/**
* Use this method to build parent child relationships.
*
* Overwrite this function if you want to use the form as a child form related to some parent
* form. You can add parent arguments to calls to make sure you get back to the right parent.
*
* @since 1.6.9
*/
protected function add_parent_args_to_back_button() {
}
/**
* Set item labels
*
* @param array $item_labels Named array containing item name/label pairs
*
* @since 2.0.15
*/
public function set_labels( $item_labels ) {
if ( is_array( $item_labels ) ) {
foreach ( $item_labels as $key => $label ) {
foreach ( $this->form_items as $form_item ) {
if ( $form_item->get_item_name() === $key ) {
$form_item->set_label( $label );
}
}
}
}
}
/**
* Hide items
*
* @param array $items_to_hide Array contains item names of items to be defined as hidden
*
* @since 2.0.15
*/
public function hide_items( $items_to_hide ) {
if ( is_array( $items_to_hide ) ) {
foreach ( $items_to_hide as $column_name ) {
foreach ( $this->form_items as $form_item ) {
if ( $form_item->get_item_name() === $column_name ) {
$form_item->set_hide_item_init( true );
}
}
}
}
}
/**
* Number of items
*
* @return int
*
* @since 2.0.15
*/
public function count() {
return count( (array) $this->form_items );
}
public function get_row() {
return $this->row;
}
}