<?php
namespace WPDataAccess\API {
use WPDataAccess\Plugin_Table_Models\WPDA_Media_Model;
use WPDataAccess\Plugin_Table_Models\WPDA_Table_Settings_Model;
use WPDataAccess\Plugin_Table_Models\WPDA_User_Menus_Model;
use WPDataAccess\WPDA;
class WPDA_Settings extends WPDA_API_Core {
const WPDA_SETTINGS = 'wpda_settings';
public function register_rest_routes() {
register_rest_route(
WPDA_API::WPDA_NAMESPACE,
'save-settings',
array(
'methods' => array( 'POST' ),
'callback' => array( $this, 'save_settings' ),
'permission_callback' => '__return_true',
'args' => array(
'action' => array(
'required' => true,
'type' => 'string',
'description' => __( 'Setting type', 'wp-data-access' ),
'sanitize_callback' => 'sanitize_text_field',
'validate_callback' => function ( $param ) {
return in_array(
$param,
array(
'dashboard_menus',
'table_settings',
'column_settings',
'rest_api',
'admin_settings',
'explorer_settings'
)
);
},
),
'dbs' => $this->get_param( 'dbs' ),
'tbl' => $this->get_param( 'tbl' ),
'settings' => array(
'required' => true,
'type' => 'string',
'description' => __( 'Settings JSON as string', 'wp-data-access' ),
'sanitize_callback' => 'sanitize_text_field',
'validate_callback' => 'rest_validate_request_arg',
),
),
)
);
}
/**
* Save plugin settings.
*
* @param WP_REST_Request $request Rest API request.
* @return \WP_Error|\WP_REST_Response
*/
public function save_settings( $request ) {
if ( ! $this->current_user_can_access( true ) ) {
return $this->unauthorized();
}
if ( ! $this->current_user_token_valid( $request ) ) {
return $this->invalid_nonce();
}
$dbs = $request->get_param( 'dbs' );
$tbl = $request->get_param( 'tbl' );
$settings_string = $request->get_param( 'settings' );
if ( ! is_string( $settings_string ) ) {
return $this->bad_request();
}
$settings = json_decode( $settings_string, true );
if ( false === $settings || is_null( $settings ) ) {
return $this->bad_request();
}
switch ( $request->get_param( 'action' ) ) {
case 'dashboard_menus':
return $this->save_dashboard_menus( $dbs, $tbl, $settings );
case 'table_settings':
return $this->save_table_settings( $dbs, $tbl, $settings );
case 'column_settings':
return $this->save_column_settings( $dbs, $tbl, $settings );
case 'rest_api':
return $this->save_rest_api_settings( $dbs, $tbl, $settings );
case 'admin_settings':
$theme = $request->get_param( 'theme' );
return $this->save_admin_settings( $dbs, $tbl, $settings, $theme );
case 'explorer_settings':
return $this->save_explorer_settings( $dbs, $tbl, $settings );
}
return $this->bad_request();
}
private function save_explorer_settings( $schema_name, $table_name, $settings ) {
global $wpdb;
$dml_failed = 0;
// Handle REST API
$rest_api = $settings['rest_api'] ?? null;
$rest_api_settings = get_option( WPDA_API::WPDA_REST_API_TABLE_ACCESS );
if ( false === $rest_api_settings ) {
$rest_api_settings = array();
}
if ( null !== $rest_api ) {
// Add table REST API
$rest_api_settings[ $schema_name ][ $table_name ] = $rest_api;
} else {
// Delete table REST API
unset($rest_api_settings[ $schema_name ][ $table_name ]);
}
update_option( WPDA_API::WPDA_REST_API_TABLE_ACCESS, $rest_api_settings );
unset( $settings['rest_api'] );
// Handle Media columns
$media_columns = $settings['column_media'] ?? null;
if ( is_array( $media_columns ) ) {
foreach ( $media_columns as $column => $value ) {
if ( false === $value || '' === $value ) {
// Delete column media (no error handling)
WPDA_Media_Model::delete( $table_name, $column, $schema_name );
} elseif ( 'string' === gettype( $value) ) {
if ( false === WPDA_Media_Model::get_column_media( $table_name, $column, $schema_name ) ) {
if ( ! WPDA_Media_Model::insert( $table_name, $column, $value, 'Yes', $schema_name ) ) {
$dml_failed++;
}
} else {
if ( false === WPDA_Media_Model::update( $table_name, $column, $value, $schema_name ) ) {
$dml_failed++;
}
}
}
}
}
unset( $settings['column_media'] );
// Handle UPDATE | INSERT table and column settings
$settings_db = WPDA_Table_Settings_Model::query( $table_name, $schema_name );
if ( isset( $settings_db[0]['wpda_table_settings'] ) ) {
// Row found, perform update
$settings_from_db = json_decode( $settings_db[0]['wpda_table_settings'], true );
foreach ( $settings_from_db as $key => $value ) {
if ( ! isset( $settings[ $key ] ) ) {
$settings[ $key ] = $value;
}
}
WPDA_Table_Settings_Model::update( $table_name, json_encode( $settings ), $schema_name );
if ( '' !== $wpdb->last_error ) {
$dml_failed++;
}
} else {
// No row found, insert new
if ( ! WPDA_Table_Settings_Model::insert( $table_name, json_encode( $settings ), $schema_name ) ) {
$dml_failed++;
}
}
if ( 0 === $dml_failed ) {
return $this->WPDA_Rest_Response( __( 'Changes successfully saved', 'wp-data-access' ) );
} else {
if ( '' === $wpdb->last_error ) {
return new \WP_Error(
sprintf( __( 'Failed to save changes [%s]', 'wp-data-access' ), $wpdb->last_error ),
array( 'status' => 420 )
);
} else {
return new \WP_Error(
sprintf( __( 'Failed to save changes [%s]', 'wp-data-access' ), $wpdb->last_error ),
array( 'status' => 420 )
);
}
}
}
/**
* Save table settings.
*
* @param $schema_name
* @param $table_name
* @param $settings
* @return \WP_Error|\WP_REST_Response
*/
private function save_table_settings( $schema_name, $table_name, $settings ) {
if (
isset( $settings['table_settings']['hyperlink_definition'] ) &&
isset( $settings['unused'] )
) {
$sql_dml = $settings['unused'];
unset( $settings['request_type'] );
unset( $settings['unused'] );
global $wpdb;
if ( 'UPDATE' === $sql_dml ) {
$settings_db = WPDA_Table_Settings_Model::query( $table_name, $schema_name );
if ( isset( $settings_db[0]['wpda_table_settings'] ) ) {
$settings_from_db = json_decode( $settings_db[0]['wpda_table_settings'], true );
foreach ( $settings_from_db as $key => $value ) {
if ( ! isset( $settings[ $key ] ) ) {
$settings[ $key ] = $value;
}
}
}
if (
1 === WPDA_Table_Settings_Model::update( $table_name, json_encode( $settings ), $schema_name ) ||
(
'' === $wpdb->last_error &&
0 === WPDA_Table_Settings_Model::update( $table_name, json_encode( $settings ), $schema_name )
)
) {
return $this->WPDA_Rest_Response( __( 'Changes successfully saved', 'wp-data-access' ) );
} else {
return new \WP_Error(
sprintf( __( 'Failed to save changes [%s]', 'wp-data-access' ), $wpdb->last_error ),
array( 'status' => 420 )
);
}
} else {
if ( WPDA_Table_Settings_Model::insert( $table_name, json_encode( $settings ), $schema_name ) ) {
return $this->WPDA_Rest_Response( __( 'Changes successfully saved', 'wp-data-access' ) );
} else {
return new \WP_Error(
sprintf( __( 'Failed to save changes [%s]', 'wp-data-access' ), $wpdb->last_error ),
array( 'status' => 420 )
);
}
}
} else {
// Nothing really to save, just to satisfy the user experience.
return $this->WPDA_Rest_Response( __( 'Changes successfully saved', 'wp-data-access' ) );
}
}
/**
* Save column settings.
*
* @param $schema_name
* @param $table_name
* @param $settings
* @return \WP_Error|\WP_REST_Response
*/
private function save_column_settings( $schema_name, $table_name, $settings ) {
$sql_dml = null;
$dml_succeeded = 0;
$dml_failed = 0;
if ( isset( $settings['column_media'] ) ) {
// Process media columns.
$settings_column_media = $settings['column_media'];
foreach ( $settings_column_media as $column => $value ) {
if ( isset( $value['value'] ) && isset( $value['dml'] ) ) {
if ( 'INSERT' === $value['dml'] ) {
if ( WPDA_Media_Model::insert( $table_name, $column, $value['value'], 'Yes', $schema_name ) ) {
$dml_succeeded ++;
} else {
$dml_failed ++;
}
} elseif ( 'UPDATE' === $value['dml'] ) {
if ( '' === $value['value'] ) {
if ( 1 === WPDA_Media_Model::delete( $table_name, $column, $schema_name ) ) {
$dml_succeeded ++;
} else {
$dml_failed ++;
}
} else {
if ( 1 === WPDA_Media_Model::update( $table_name, $column, $value['value'], $schema_name ) ) {
$dml_succeeded ++;
} else {
$dml_failed ++;
}
}
}
}
}
unset( $settings['column_media'] );
}
if ( isset( $settings['unused'] ) ) {
$settings_unused = $settings['unused'];
if ( isset( $settings_unused['sql_dml'] ) ) {
$sql_dml = $settings_unused['sql_dml'];
}
unset( $settings['unused'] );
}
if ( null === $sql_dml ) {
return new \WP_Error(
sprintf(
__( 'Failed to save changes [%s]', 'wp-data-access' ),
'please contact the plugin development team'
),
array( 'status' => 420 )
);
} else {
// Save settings.
if ( isset( $settings['request_type'] ) ) {
unset( $settings['request_type'] );
}
if ( 'UPDATE' === $sql_dml ) {
$settings_db = WPDA_Table_Settings_Model::query( $table_name, $schema_name );
if ( isset( $settings_db[0]['wpda_table_settings'] ) ) {
$settings_from_db = json_decode( $settings_db[0]['wpda_table_settings'], true );
foreach ( $settings_from_db as $key => $value ) {
if ( ! isset( $settings[ $key ] ) ) {
$settings[ $key ] = $value;
}
}
}
if ( 1 === WPDA_Table_Settings_Model::update( $table_name, json_encode( $settings ), $schema_name ) ) {
$dml_succeeded ++;
}
} else {
if ( WPDA_Table_Settings_Model::insert( $table_name, json_encode( $settings ), $schema_name ) ) {
$dml_succeeded ++;
} else {
$dml_failed ++;
}
}
}
if ( $dml_succeeded >= 0 && $dml_failed === 0 ) {
return $this->WPDA_Rest_Response( __( 'Changes successfully saved', 'wp-data-access' ) );
} else {
global $wpdb;
$msg = '' !== $wpdb->last_error ? " [{$wpdb->last_error}]" : '';
return new \WP_Error(
sprintf( __( 'Failed to save changes [%s]', 'wp-data-access' ), $msg ),
array( 'status' => 420 )
);
}
}
/**
* Save dashboard menu changes.
*
* @param $schema_name
* @param $table_name
* @param $settings
* @return \WP_Error|\WP_REST_Response
*/
private function save_dashboard_menus( $schema_name, $table_name, $settings ) {
$dml_succeeded = 0;
$dml_failed = 0;
$new_menus = array();
if ( isset( $settings['menu'] ) && is_array( $settings['menu'] ) ) {
// Process menu items.
foreach ( $settings['menu'] as $menu ) {
if ( isset( $menu['menu_name'] ) && isset( $menu['menu_slug'] ) ) {
if ( isset( $menu['menu_role'] ) ) {
if ( is_array( $menu['menu_role'] ) ) {
$menu_role = implode( ',', $menu['menu_role'] );
} else {
$menu_role = $menu['menu_role'];
}
} else {
$menu_role = '';
}
if ( isset( $menu['menu_id'] ) && '' === $menu['menu_id'] ) {
// Add new menu
if ( WPDA_User_Menus_Model::insert(
$table_name,
$menu['menu_name'],
$menu['menu_slug'],
$menu_role,
$schema_name
) ) {
$dml_succeeded ++;
global $wpdb;
$new_menus[] = array(
'menu_name' => $menu['menu_name'],
'menu_slug' => $menu['menu_slug'],
'menu_id' => $wpdb->insert_id,
);
} else {
$dml_failed ++;
}
} else {
if ( isset( $menu['menu_id'] ) ) {
// Update existing menu.
$update_result = WPDA_User_Menus_Model::update(
$menu['menu_id'],
$table_name,
$menu['menu_name'],
$menu['menu_slug'],
$menu_role,
$schema_name
);
if ( 1 === $update_result ) {
$dml_succeeded ++;
}
}
}
}
}
unset( $settings['menu'] );
}
if ( isset( $settings['delete'] ) && is_array( $settings['delete'] ) ) {
// Process menu items to be deleted.
foreach ( $settings['delete'] as $menu ) {
if ( 1 === WPDA_User_Menus_Model::delete( $menu ) ) {
$dml_succeeded++;
} else {
$dml_failed++;
}
}
unset( $settings['delete'] );
}
if ( $dml_succeeded >= 0 && $dml_failed === 0 ) {
return $this->WPDA_Rest_Response(
sprintf( __( 'Saved dashboard menus for table `%s`', 'wp-data-access' ), $table_name ),
$new_menus
);
} else {
global $wpdb;
$msg = '' !== $wpdb->last_error ? " [{$wpdb->last_error}]" : '';
return new \WP_Error(
sprintf( __( 'Cannot save dashboard menus for table `%s`%s', 'wp-data-access' ), $table_name, $msg ),
array( 'status' => 420 )
);
}
}
/**
* Save rest api settings.
*
* @param $schema_name
* @param $table_name
* @param $settings
* @return \WP_Error|\WP_REST_Response
*/
private function save_rest_api_settings( $schema_name, $table_name, $settings ) {
if ( ! isset( $settings['enabled'] ) ) {
return $this->bad_request();
}
$rest_api_settings = get_option( WPDA_API::WPDA_REST_API_TABLE_ACCESS );
if ( false === $rest_api_settings ) {
$rest_api_settings = array();
}
if ( true === $settings['enabled'] ) {
// Add new | update existing REST API rule.
$actions = array( 'select', 'insert', 'update', 'delete' );
foreach ( $actions as $action ) {
if (
isset(
$settings[ $action ],
$settings[ $action ]['authorization'],
$settings[ $action ]['methods'],
$settings[ $action ]['authorized_roles'],
$settings[ $action ]['authorized_users']
)
) {
unset( $rest_api_settings[ $schema_name ][ $table_name ][ $action ] ); // Unset previous authorization.
$rest_api_settings[ $schema_name ][ $table_name ][ $action ]['authorization'] = $settings[ $action ]['authorization'];
$rest_api_settings[ $schema_name ][ $table_name ][ $action ]['methods'] = $settings[ $action ]['methods'];
$rest_api_settings[ $schema_name ][ $table_name ][ $action ]['authorized_roles'] = $settings[ $action ]['authorized_roles'];
$rest_api_settings[ $schema_name ][ $table_name ][ $action ]['authorized_users'] = $settings[ $action ]['authorized_users'];
}
else {
return $this->bad_request();
}
}
} elseif ( false === $settings['enabled'] ) {
// Remove existing REST API rule.
if ( isset( $settings['select'] ) ) {
unset( $rest_api_settings[ $schema_name ][ $table_name ]['select'] );
if (
isset( $rest_api_settings[ $schema_name ][ $table_name ] ) &&
0 === count( $rest_api_settings[ $schema_name ][ $table_name ] )//phpcs:ignore - 8.1 proof
) {
unset( $rest_api_settings[ $schema_name ][ $table_name ] );
if (
isset( $rest_api_settings[ $schema_name ] ) &&
0 === count( $rest_api_settings[ $schema_name ] )//phpcs:ignore - 8.1 proof
) {
unset( $rest_api_settings[ $schema_name ] );
}
}
} else {
return $this->bad_request();
}
} else {
return $this->bad_request();
}
update_option( WPDA_API::WPDA_REST_API_TABLE_ACCESS, $rest_api_settings );
return $this->WPDA_Rest_Response(
sprintf( __( 'Saved REST API settings for table `%s`', 'wp-data-access' ), $table_name )
);
}
private function save_admin_settings( $schema_name, $table_name, $settings, $theme ) {
if (
!
(
isset(
$settings['scope'],
$settings['target']
) &&
(
isset(
$settings['data']
) ||
null === $settings['data']
) &&
(
'global' === $settings['scope'] ||
'user' === $settings['scope']
) &&
(
'table' === $settings['target'] ||
'form' === $settings['target'] ||
'theme' === $settings['target']
)
)
) {
return $this->bad_request();
}
$admin_settings = WPDA_Settings::get_admin_settings_key(
$settings['target'],
$schema_name ,
$table_name
);
if ( 'global' === $settings['scope'] ) {
// Store settings globally.
if ( null !== $settings['data'] ) {
update_option( $admin_settings, $settings['data'] );
if ( null !== $theme ) {
$theme_settings = WPDA_Settings::get_admin_settings_key(
'theme',
$schema_name ,
$table_name
);
update_option( $theme_settings, $theme );
}
} else {
delete_option( $admin_settings );
}
} else {
// Store settings for login user.
if ( null !== $settings['data'] ) {
update_user_option( $admin_settings, $settings['data'] );
if ( null !== $theme ) {
$theme_settings = WPDA_Settings::get_admin_settings_key(
'theme',
$schema_name ,
$table_name
);
update_user_option( $theme_settings, $theme );
}
} else {
delete_user_option( $admin_settings );
}
}
return $this->WPDA_Rest_Response( __( 'Successfully saved changes', 'wp-data-access' ) );
}
public static function get_admin_settings( $schema_name, $table_name ) {
return array(
'global' => array(
'table' => get_option(
WPDA_Settings::get_admin_settings_key(
'table',
$schema_name,
$table_name
)
),
'form' => get_option(
WPDA_Settings::get_admin_settings_key(
'form',
$schema_name,
$table_name
)
),
'theme' => get_option(
WPDA_Settings::get_admin_settings_key(
'theme',
$schema_name,
$table_name
)
),
),
'local' => array(
'table' => get_user_option(
WPDA_Settings::get_admin_settings_key(
'table',
$schema_name,
$table_name
)
),
'form' => get_user_option(
WPDA_Settings::get_admin_settings_key(
'form',
$schema_name,
$table_name
)
),
'theme' => get_user_option(
WPDA_Settings::get_admin_settings_key(
'theme',
$schema_name,
$table_name
)
),
),
);
}
private static function get_admin_settings_key( $target, $schema_name, $table_name ) {
return WPDA_Settings::WPDA_SETTINGS .
'-' . $target .
'-' . str_replace( ' ', '*', $schema_name ) .
'-' . str_replace( ' ', '*', $table_name );
}
}
}