process_bulk_action_create_db();
} elseif ( 'drop_db' === $_REQUEST['action'] ) {
$this->process_bulk_action_drop_db();
} elseif ( 'edit_db' === $_REQUEST['action'] ) {
$this->process_bulk_action_edit_db();
}
}
parent::__construct( $args );
$this->set_columns_queried( array(
'table_name AS table_name',
'if (find_in_set(table_name,\'' . implode( ',', WPDA::get_wp_tables() ) . '\')
, \'' . WPDA::get_table_type_text( WPDA::TABLE_TYPE_WP ) . '\'
, if (find_in_set(table_name,\'' . implode( ',', WPDA::get_wpda_tables() ) . '\')
, \'' . WPDA::get_table_type_text( WPDA::TABLE_TYPE_WPDA ) . '\'
, lower(table_type)
)
) AS table_type',
'create_time AS create_time',
'table_rows AS table_rows',
'auto_increment AS auto_increment',
'engine AS engine',
'data_length+index_length AS total_size',
'data_length AS data_size',
'index_length AS index_size',
'data_free AS overhead',
'table_collation AS table_collation',
'table_type AS table_type_db'
) );
$this->favourites = get_option( WPDA_Favourites::FAVOURITES_OPTION_NAME );
if ( null === $this->switch_schema_name ) {
$this->schema_name = $this->get_schema_name();
} else {
$this->schema_name = $this->switch_schema_name;
}
$this->wpda_main_favourites = $this->get_favourites();
// Instantiate WPDA_Import.
$this->wpda_import = new WPDA_Import_Multi("?page={$this->page}", $this->schema_name);
$wpdadb = WPDADB::get_db_connection( $this->schema_name );
if ( null === $wpdadb ) {
/* translators: %s = remote database name */
wp_die( esc_attr( sprintf( __( 'ERROR - Remote database %s not available', 'wp-data-access' ), $this->schema_name ) ) );
}
$result = $wpdadb->get_row( "show session variables like 'innodb_file_per_table'" );
if ( !empty( $result ) ) {
$this->innodb_file_per_table = 'ON' === $result->Value;
}
// Can user create/drop databases?
$this->user_can_create_db = WPDA_Dictionary_Access::can_create_db();
if ( $this->user_can_create_db ) {
$this->user_create_db_hint = __( 'Create local database/add remote database connection', 'wp-data-access' );
} else {
$this->user_create_db_hint = __( 'Add remote database connection (not authorized to create local database)', 'wp-data-access' );
}
$this->user_can_drop_db = WPDA_Dictionary_Access::can_drop_db();
if ( $this->user_can_drop_db ) {
if ( $wpdb->dbname === $this->schema_name ) {
$this->user_can_drop_db = false;
$this->user_drop_db_hint = __( 'Cannot drop WordPress database', 'wp-data-access' );
} elseif ( 'sys' === $this->schema_name || 'mysql' === $this->schema_name || 'information_schema' === $this->schema_name || 'performance_schema' === $this->schema_name || '' === $this->schema_name ) {
$this->user_can_drop_db = false;
$this->user_drop_db_hint = __( 'Cannot drop MySQL database', 'wp-data-access' );
} else {
if ( 'rdb:' === substr( $this->schema_name, 0, 4 ) ) {
$this->user_drop_db_hint = __( "Delete remote database connection.\nDoes not drop the database! Just deletes the connection definition.", 'wp-data-access' );
} else {
$this->user_drop_db_hint = __( 'Drop selected database', 'wp-data-access' );
}
}
} else {
if ( 'rdb:' === substr( $this->schema_name, 0, 4 ) ) {
$this->user_can_drop_db = true;
$this->user_drop_db_hint = __( "Delete remote database connection.\nDoes not drop the database! Just deletes the connection definition.", 'wp-data-access' );
} else {
$this->user_drop_db_hint = __( 'Cannot drop selected database [not authorized]', 'wp-data-access' );
}
}
}
/**
* Overwrite method to add structure to the row below.
*
* @param object $item Item info.
*
* @since 1.5.0
*/
public function single_row( $item ) {
list( $columns, $hidden, $sortable, $primary ) = $this->get_column_info();
$columns_not_shown = count( (array) $hidden );
echo '
';
$this->single_row_columns( $item );
echo '
';
if ( $this->bulk_actions_enabled ) {
echo ' |
';
// Fake! Maintain odd/even colors.
echo ' | ';
} else {
echo ' |
|
';
// Fake! Maintain odd/even colors.
echo '| ';
}
echo '';
echo ' |
';
}
/**
* Override column_default
*
* We need to override this method as our table is in fact a view and has no real columns:
* $this->wpda_list_columns->get_table_columns() returns no results
*
* We'll use jquery to write html forms to a container to make them accessible inside our list table.
* See WPDA_List_Table->column_default for further explanation.
*
* @param array $item Item info.
* @param string $column_name Column name.
*
* @return mixed Actions for the current row.
* @see WPDA_List_Table::column_default()
*
* @since 1.0.0
*/
public function column_default( $item, $column_name ) {
if ( 'icons' === $column_name ) {
// Dummy column where icons are shown (favourites and row admin menu).
$table_name = $item['table_name'];
$favourite_class = 'dashicons-star-empty';
$favourite_title = 'Add to favourites';
if ( null !== $this->favourites && false !== $this->favourites ) {
$favourites_array = $this->favourites;
if ( isset( $favourites_array[$table_name] ) ) {
$favourite_class = 'dashicons-star-filled';
$favourite_title = 'Remove from favourites';
}
}
$favourites_menu = "schema_name}', '{$table_name}' )\">\n\t\t\t\t\t\t\n\t\t\t\t\t";
return $favourites_menu;
}
if ( 'table_rows' === $column_name ) {
if ( is_scalar( $item['engine'] ) && is_scalar( $item['table_type'] ) && ('federated' === strtolower( $item['engine'] ) || 'connect' === strtolower( $item['engine'] ) || 'innodb' === strtolower( $item['engine'] ) || stripos( strtolower( $item['table_type'] ), 'view' ) !== false) ) {
$settings_db = WPDA_Table_Settings_Model::query( $item['table_name'], $this->schema_name );
if ( isset( $settings_db[0]['wpda_table_settings'] ) && '' !== $settings_db[0]['wpda_table_settings'] ) {
$settings = json_decode( $settings_db[0]['wpda_table_settings'] );
} else {
$settings = (object) null;
}
$row_count_estimate = WPDA::get_row_count_estimate( $this->schema_name, $item['table_name'], $settings );
if ( !$row_count_estimate['do_real_count'] ) {
if ( $row_count_estimate['is_estimate'] ) {
return stripslashes( '~' . $row_count_estimate['row_count'] );
} else {
return stripslashes( $row_count_estimate['row_count'] );
}
} else {
return stripslashes( $this->count_rows( $item['table_name'] ) );
}
} else {
return stripslashes( (string) $item[$column_name] );
}
}
if ( 'total_size' === $column_name || 'data_size' === $column_name || 'index_size' === $column_name ) {
if ( '' === stripslashes( (string) $item[$column_name] ) ) {
return stripslashes( (string) $item[$column_name] );
} else {
if ( $item[$column_name] / (1024 * 1024) > 1 ) {
return number_format(
stripslashes( $item[$column_name] / (1024 * 1024) ),
2,
'.',
','
) . ' MB';
} elseif ( $item[$column_name] / 1024 > 1 ) {
return number_format(
$item[$column_name] / 1024,
2,
'.',
','
) . ' KB';
}
return number_format(
stripslashes( $item[$column_name] ),
2,
'.',
','
) . ' bytes';
}
}
if ( 'overhead' === $column_name ) {
if ( 'InnoDB' === $item['engine'] && !$this->innodb_file_per_table ) {
return '-';
} else {
if ( '' === stripslashes( (string) $item[$column_name] ) ) {
return '';
} else {
if ( $item[$column_name] > 0 && $item['data_size'] > 0 && $item[$column_name] / $item['data_size'] > 0.2 ) {
$msg = __( "Fragmentation for this table is high.\nConsider: Manage>Actions>Optimize", 'wp-data-access' );
$approx = " ";
} else {
$approx = '';
}
if ( $item[$column_name] / (1024 * 1024) > 1 ) {
return number_format(
stripslashes( $item[$column_name] / (1024 * 1024) ),
2,
'.',
','
) . ' MB' . $approx;
} elseif ( $item[$column_name] / 1024 > 1 ) {
return number_format(
stripslashes( $item[$column_name] / 1024 ),
2,
'.',
','
) . ' KB' . $approx;
}
return number_format(
stripslashes( $item[$column_name] ),
2,
'.',
','
) . ' bytes' . $approx;
}
}
}
if ( 'table_name' === $column_name ) {
// Get table name of the current row (= key).
$table_name = $item[$column_name];
$admin_actions = array();
// Array containing admin actions.
if ( WPDA::can_manage() ) {
// Add manage table/view line.
$wp_nonce_action_table_actions = "wpda-actions-{$table_name}";
$wp_nonce_table_actions = wp_create_nonce( $wp_nonce_action_table_actions );
/* translators: %s = table name */
$table_actions_title = sprintf( __( 'Table %s settings', 'wp-data-access' ), $table_name );
$actions['wpda_manage'] = "schema_name}', '{$table_name}', '" . self::$list_number . "', '{$wp_nonce_table_actions}', '{$item['table_type_db']}', '" . self::LOADING . "' ); this.blur();\">" . ' ' . __( 'Manage', 'wp-data-access' ) . '';
}
self::$list_number++;
// Prepare type checking for editing.
$check_view_access = 'true';
if ( 'on' === WPDA::get_option( WPDA::OPTION_BE_CONFIRM_VIEW ) ) {
if ( 'VIEW' !== strtoupper( $item['table_type_db'] ) && 'SYSTEM VIEW' !== strtoupper( $item['table_type_db'] ) ) {
if ( strtolower( WPDA::TABLE_TYPE_WP ) === strtolower( $item['table_type'] ) ) {
// WordPress table.
$msg = __( 'You are about to edit a WordPress table! Changing this table might result in corrupting the WordPress database. Are you sure you want to continue?', 'wp-data-access' );
} elseif ( strtolower( WPDA::TABLE_TYPE_WPDA ) === strtolower( $item['table_type'] ) ) {
// Plugin table.
$msg = __( 'You are about to edit a plugin table! Changing this table might result in corrupting the WP Data Access database. Are you sure you want to continue?', 'wp-data-access' );
} else {
// User table (other than WordPress or plugin).
$msg = __( 'You are about to edit a table of an external application! Changing this table might result in corrupting the external database. Are you sure you want to continue?', 'wp-data-access' );
}
$check_view_access = 'confirm(\'' . $msg . '\')';
}
}
$esc_attr = 'esc_attr';
$form_name = 'explore_' . self::$list_number;
$url = "?page={$this->page}";
// phpcs:ignore PluginCheck.CodeAnalysis.Heredoc.NotAllowed
$form = <<
\t\t\t\t\t
\t\t\t\t\t
\t\t\t\t\t
\t\t\t\t
EOT;
$explore = str_replace( array("\n", "\r"), '', $form );
?>
' . __( 'Explore', 'wp-data-access' );
/* translators: %s = tablename */
$table_view_title = sprintf( __( 'Explore %s table', 'wp-data-access' ), $table_name );
$actions['wpda_listtable'] = sprintf(
'
%s
',
$table_view_title,
$check_view_access,
$form_name,
$action_view
);
if ( strtolower( WPDA::TABLE_TYPE_WP ) === strtolower( $item['table_type'] ) ) {
?>
schema_name, $table_name );
} else {
$warning = '';
}
/* translators: 1: warning; 2: row action; 3: admin action */
return sprintf(
'%1$s %2$s %3$s',
$table_name . $warning,
"{$this->row_actions( $actions )}",
""
);
}
if ( 'create_time' === $column_name ) {
if ( null !== $item[$column_name] ) {
return date_i18n( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), strtotime( $item[$column_name] ) );
} else {
return '';
}
}
return stripslashes( (string) $item[$column_name] );
}
/**
* Count the number of rows in a table.
*
* This method is used to get the number of rows in an InnoDB table as the table_rows column of
* information_schema.tables only return an estimate.
*
* @param string $table_name Database table name.
*
* @return integer|null Number of rows in $table_name.
* @since 1.5.1
*/
protected function count_rows( $table_name ) {
$wpdadb = WPDADB::get_db_connection( $this->schema_name );
if ( null === $wpdadb ) {
/* translators: %s = remote database name */
wp_die( esc_attr( sprintf( __( 'ERROR - Remote database %s not available', 'wp-data-access' ), $this->schema_name ) ) );
}
if ( '' === $this->schema_name ) {
$query = "\n\t\t\t\t\tselect count(*)\n\t\t\t\t\tfrom `{$table_name}`\n\t\t\t\t";
} else {
$query = "\n\t\t\t\t\tselect count(*)\n\t\t\t\t\tfrom `{$wpdadb->dbname}`.`{$table_name}`\n\t\t\t\t";
}
$suppress = $wpdadb->suppress_errors( true );
$count = @$wpdadb->get_var( $query );
if ( !is_numeric( $count ) ) {
$count = 'last_error ) . '">';
}
$wpdadb->suppress_errors( $suppress );
return $count;
}
/**
* Override get_columns
*
* @return array
* @see WPDA_List_Table::get_columns()
*
* @since 1.0.0
*/
public function get_columns() {
$columns = array();
if ( $this->bulk_actions_enabled ) {
$columns = array(
'cb' => '',
);
}
return array_merge( $columns, $this->column_headers );
}
/**
* Override get_sortable_columns()
*
* Type is not sortable as it is not in the view.
*
* @return array
* @see WPDA_List_Table::get_sortable_columns()
*
* @since 1.0.0
*/
public function get_sortable_columns() {
$columns = array();
$columns['table_name'] = array('table_name', false);
$columns['table_type'] = array('table_type', false);
$columns['engine'] = array('engine', false);
$columns['create_time'] = array('create_time', false);
$columns['table_rows'] = array('table_rows', false);
$columns['auto_increment'] = array('auto_increment', false);
$columns['total_size'] = array('total_size', false);
$columns['data_size'] = array('data_size', false);
$columns['index_size'] = array('index_size', false);
$columns['overhead'] = array('overhead', false);
$columns['table_collation'] = array('table_collation', false);
return $columns;
}
/**
* Override column_cb
*
* @param array $item Column info.
*
* @return string
* @since 1.0.0
*
* @see WPDA_List_Table::column_cb()
*/
public function column_cb( $item ) {
if ( !$this->bulk_actions_enabled ) {
// Bulk actions disabled.
return '';
}
if ( 'VIEW' === $item['table_type_db'] ) {
$title = 'title="Performs only drop actions on views"';
$class = 'class="wpda_tooltip"';
} else {
$title = '';
$class = '';
}
return "";
}
/**
* Override get_bulk_actions
*
* @return array
* @see WPDA_List_Table::get_bulk_actions()
*
* @since 1.0.0
*/
public function get_bulk_actions() {
if ( !$this->bulk_actions_enabled ) {
// Bulk actions disabled.
return '';
}
$actions = array();
$actions['bulk-export'] = __( 'Export Table(s)', 'wp-data-access' );
$actions['bulk-drop'] = __( 'Drop Table(s)/View(s) (does not drop WordPress tables)', 'wp-data-access' );
$actions['bulk-truncate'] = __( 'Truncate Table(s) (does not truncate WordPress tables)', 'wp-data-access' );
return $actions;
}
/**
* Override process_bulk_action()
*
* @since 1.0.0
*
* @see WPDA_List_Table::process_bulk_action()
*/
public function process_bulk_action() {
switch ( $this->current_action() ) {
case 'bulk-export':
$this->process_bulk_action_bulk_export();
break;
case 'bulk-drop':
$this->process_bulk_action_bulk_drop();
break;
case 'bulk-truncate':
$this->process_bulk_action_bulk_truncate();
break;
case 'drop':
$this->process_bulk_action_drop();
break;
case 'truncate':
$this->process_bulk_action_truncate();
break;
case 'rename-table':
$this->process_bulk_action_rename_table();
break;
case 'copy-table':
$this->process_bulk_action_copy_table();
break;
case 'optimize-table':
$this->process_bulk_action_optimize_table();
break;
case 'refresh-table':
$this->process_bulk_action_refresh_table();
break;
case 'c2wp-table':
$this->process_bulk_action_c2wp_table();
break;
}
}
protected function process_bulk_action_refresh_table() {
}
protected function process_bulk_action_drop_db() {
if ( !$this->process_bulk_action_check_wpnonce( 'wpda-drop-db-from-data-explorer-' . WPDA::get_current_user_login(), '_wpnoncedropdb' ) ) {
return;
}
if ( !isset( $_REQUEST['database'] ) ) {
$msg = new WPDA_Message_Box(array(
'message_text' => __( 'Cannot drop database [missing argument]', 'wp-data-access' ),
'message_type' => 'error',
'message_is_dismissible' => false,
));
$msg->box();
return;
}
global $wpdb;
$database = str_replace( '`', '', sanitize_text_field( wp_unslash( $_REQUEST['database'] ) ) );
if ( 'rdb:' === substr( $database, 0, 4 ) ) {
// Delete remote database
// phpcs:disable WordPress.WP.I18n.MissingTranslatorsComment
if ( false === WPDADB::get_remote_database( $database ) ) {
$msg = new WPDA_Message_Box(array(
'message_text' => sprintf( __( 'Cannot delete remote database connection `%s` [remote database connection not found]', 'wp-data-access' ), $database ),
'message_type' => 'error',
'message_is_dismissible' => false,
));
$msg->box();
} else {
if ( false === WPDADB::del_remote_database( $database ) ) {
// phpcs:disable WordPress.WP.I18n.MissingTranslatorsComment
$msg = new WPDA_Message_Box(array(
'message_text' => sprintf( __( 'Cannot delete remote database connection `%s`', 'wp-data-access' ), $database ),
'message_type' => 'error',
'message_is_dismissible' => false,
));
$msg->box();
} else {
$msg = new WPDA_Message_Box(array(
'message_text' => sprintf( __( 'Remove database `%s` deleted', 'wp-data-access' ), $database ),
));
$msg->box();
$this->switch_schema_name = $wpdb->dbname;
}
}
// phpcs:enable WordPress.WP.I18n.MissingTranslatorsComment
} else {
// Drop local database
if ( $wpdb->dbname === $database ) {
$msg = new WPDA_Message_Box(array(
'message_text' => __( 'Cannot drop WordPress database', 'wp-data-access' ),
'message_type' => 'error',
'message_is_dismissible' => false,
));
$msg->box();
return;
}
if ( 'sys' === $database || 'mysql' === $database || 'information_schema' === $database || 'performance_schema' === $database || '' === $database ) {
$msg = new WPDA_Message_Box(array(
'message_text' => __( 'Cannot drop MySQL database', 'wp-data-access' ),
'message_type' => 'error',
'message_is_dismissible' => false,
));
$msg->box();
return;
}
// phpcs:disable WordPress.WP.I18n.MissingTranslatorsComment
// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQLPlaceholders, WordPress.DB.DirectDatabaseQuery.SchemaChange
if ( false === $wpdb->query( $wpdb->prepare(
/* translators: %s = database name */
'drop database `%1s`',
array(WPDA::remove_backticks( $database ))
) ) ) {
// db call ok; no-cache ok.
$msg = new WPDA_Message_Box(array(
'message_text' => sprintf( __( 'Error dropping database `%s`', 'wp-data-access' ), $database ),
'message_type' => 'error',
'message_is_dismissible' => false,
));
$msg->box();
} else {
$msg = new WPDA_Message_Box(array(
'message_text' => sprintf( __( 'Database `%s` dropped', 'wp-data-access' ), $database ),
));
$msg->box();
$this->switch_schema_name = $wpdb->dbname;
}
// phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQLPlaceholders, WordPress.DB.DirectDatabaseQuery.SchemaChange
// phpcs:enable WordPress.WP.I18n.MissingTranslatorsComment
}
}
protected function process_bulk_action_edit_db() {
if ( !$this->process_bulk_action_check_wpnonce( 'wpda-edit-db-from-data-explorer-' . WPDA::get_current_user_login(), '_wpnonceeditdb' ) ) {
return;
}
if ( !isset( $_REQUEST['edit_remote_database'] ) ) {
$msg = new WPDA_Message_Box(array(
'message_text' => __( 'Cannot update remote database connection [missing argument]', 'wp-data-access' ),
'message_type' => 'error',
'message_is_dismissible' => false,
));
$msg->box();
return;
}
$database = sanitize_text_field( wp_unslash( $_REQUEST['edit_remote_database'] ) );
// phpcs:disable WordPress.Security.ValidatedSanitizedInput
$database_old = sanitize_text_field( wp_unslash( $_REQUEST['edit_remote_database_old'] ) );
// phpcs:enable WordPress.Security.ValidatedSanitizedInput
if ( $database !== $database_old ) {
// Update database connection name
if ( false === WPDADB::get_remote_database( $database_old ) ) {
// phpcs:disable WordPress.Security.ValidatedSanitizedInput
$msg = new WPDA_Message_Box(array(
'message_text' => __( 'Cannot update remote database connection [remote database connection not found]', 'wp-data-access' ),
'message_type' => 'error',
'message_is_dismissible' => false,
));
$msg->box();
// phpcs:enable WordPress.Security.ValidatedSanitizedInput
return;
}
} else {
// Update database connection information
if ( false === WPDADB::get_remote_database( $database ) ) {
$msg = new WPDA_Message_Box(array(
'message_text' => __( 'Cannot update remote database connection [remote database connection not found]', 'wp-data-access' ),
'message_type' => 'error',
'message_is_dismissible' => false,
));
$msg->box();
return;
}
}
$host = ( isset( $_REQUEST['edit_remote_host'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['edit_remote_host'] ) ) : '' );
$user = ( isset( $_REQUEST['edit_remote_user'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['edit_remote_user'] ) ) : '' );
// Cannot use sanitize_text_field on password field!
// phpcs:disable WordPress.Security.ValidatedSanitizedInput
$passwd = ( isset( $_REQUEST['edit_remote_passwd'] ) ? wp_unslash( $_REQUEST['edit_remote_passwd'] ) : '' );
// phpcs:enable WordPress.Security.ValidatedSanitizedInput
$port = ( isset( $_REQUEST['edit_remote_port'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['edit_remote_port'] ) ) : '' );
$schema = ( isset( $_REQUEST['edit_remote_schema'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['edit_remote_schema'] ) ) : '' );
$ssl = ( isset( $_REQUEST['edit_remote_ssl'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['edit_remote_ssl'] ) ) : 'off' );
$ssl_key = ( isset( $_REQUEST['edit_remote_client_key'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['edit_remote_client_key'] ) ) : '' );
$ssl_cert = ( isset( $_REQUEST['edit_remote_client_certificate'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['edit_remote_client_certificate'] ) ) : '' );
$ssl_ca = ( isset( $_REQUEST['edit_remote_ca_certificate'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['edit_remote_ca_certificate'] ) ) : '' );
$ssl_path = ( isset( $_REQUEST['edit_remote_certificate_path'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['edit_remote_certificate_path'] ) ) : '' );
$ssl_cipher = ( isset( $_REQUEST['edit_remote_specified_cipher'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['edit_remote_specified_cipher'] ) ) : '' );
if ( '' === $database || '' === $host || '' === $user || '' === $schema ) {
$msg = new WPDA_Message_Box(array(
'message_text' => __( 'Cannot edit remote database connection [missing arguments]', 'wp-data-access' ),
'message_type' => 'error',
'message_is_dismissible' => false,
));
$msg->box();
return;
}
// phpcs:disable WordPress.WP.I18n.MissingTranslatorsComment
if ( !WPDADB::upd_remote_database(
$database,
$host,
$user,
$passwd,
$port,
$schema,
false,
$database_old,
$ssl,
$ssl_key,
$ssl_cert,
$ssl_ca,
$ssl_path,
$ssl_cipher
) ) {
$msg = new WPDA_Message_Box(array(
'message_text' => sprintf( __( 'Cannot update remote database connection `%s`', 'wp-data-access' ), $database ),
'message_type' => 'error',
'message_is_dismissible' => false,
));
$msg->box();
} else {
$msg = new WPDA_Message_Box(array(
'message_text' => sprintf( __( 'Remote database connection `%s` updated', 'wp-data-access' ), $database ),
));
$msg->box();
if ( $database !== $database_old ) {
$this->switch_schema_name = $database;
}
}
// phpcs:enable WordPress.WP.I18n.MissingTranslatorsComment
}
protected function process_bulk_action_create_db() {
if ( !$this->process_bulk_action_check_wpnonce( 'wpda-create-db-from-data-explorer-' . WPDA::get_current_user_login(), '_wpnoncecreatedb' ) ) {
return;
}
if ( isset( $_REQUEST['database_location'] ) && 'local' === $_REQUEST['database_location'] ) {
// Add local database
if ( !isset( $_REQUEST['local_database'] ) ) {
$msg = new WPDA_Message_Box(array(
'message_text' => __( 'Cannot create database [missing argument]', 'wp-data-access' ),
'message_type' => 'error',
'message_is_dismissible' => false,
));
$msg->box();
return;
}
$database = str_replace( '`', '', sanitize_text_field( wp_unslash( $_REQUEST['local_database'] ) ) );
global $wpdb;
// phpcs:disable WordPress.WP.I18n.MissingTranslatorsComment
// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQLPlaceholders, WordPress.DB.DirectDatabaseQuery.SchemaChange
if ( false === $wpdb->query( $wpdb->prepare( 'create database `%1s`', array(WPDA::remove_backticks( $database )) ) ) ) {
// db call ok; no-cache ok.
$msg = new WPDA_Message_Box(array(
'message_text' => sprintf( __( 'Error creating database `%s`', 'wp-data-access' ), $database ),
'message_type' => 'error',
'message_is_dismissible' => false,
));
$msg->box();
} else {
$msg = new WPDA_Message_Box(array(
'message_text' => sprintf( __( 'Database `%s` created', 'wp-data-access' ), $database ),
));
$msg->box();
$this->switch_schema_name = $database;
}
// phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQLPlaceholders, WordPress.DB.DirectDatabaseQuery.SchemaChange
// phpcs:enable WordPress.WP.I18n.MissingTranslatorsComment
} else {
// Add remote database
$database = ( isset( $_REQUEST['remote_database'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['remote_database'] ) ) : '' );
if ( false !== WPDADB::get_remote_database( $database ) ) {
$msg = new WPDA_Message_Box(array(
'message_text' => __( 'Remote database connection already exists', 'wp-data-access' ),
'message_type' => 'error',
'message_is_dismissible' => false,
));
$msg->box();
return;
}
$host = ( isset( $_REQUEST['remote_host'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['remote_host'] ) ) : '' );
$user = ( isset( $_REQUEST['remote_user'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['remote_user'] ) ) : '' );
// phpcs:disable WordPress.Security.ValidatedSanitizedInput
$passwd = ( isset( $_REQUEST['remote_passwd'] ) ? wp_unslash( $_REQUEST['remote_passwd'] ) : '' );
// Cannot use sanitize_text_field on password field!
// phpcs:enable WordPress.Security.ValidatedSanitizedInput
$port = ( isset( $_REQUEST['remote_port'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['remote_port'] ) ) : '' );
$schema = ( isset( $_REQUEST['remote_schema'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['remote_schema'] ) ) : '' );
$ssl = ( isset( $_REQUEST['remote_ssl'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['remote_ssl'] ) ) : 'off' );
$ssl_key = ( isset( $_REQUEST['remote_client_key'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['remote_client_key'] ) ) : '' );
$ssl_cert = ( isset( $_REQUEST['remote_client_certificate'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['remote_client_certificate'] ) ) : '' );
$ssl_ca = ( isset( $_REQUEST['remote_ca_certificate'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['remote_ca_certificate'] ) ) : '' );
$ssl_path = ( isset( $_REQUEST['remote_certificate_path'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['remote_certificate_path'] ) ) : '' );
$ssl_cipher = ( isset( $_REQUEST['remote_specified_cipher'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['remote_specified_cipher'] ) ) : '' );
if ( '' === $database || '' === $host || '' === $user || '' === $schema ) {
$msg = new WPDA_Message_Box(array(
'message_text' => __( 'Cannot add remote database connection [missing argument]', 'wp-data-access' ),
'message_type' => 'error',
'message_is_dismissible' => false,
));
$msg->box();
return;
}
if ( 'rdb:' === $database ) {
$msg = new WPDA_Message_Box(array(
'message_text' => __( 'Invalid database name [enter a valid database name, for example rdb:remotedb]', 'wp-data-access' ),
'message_type' => 'error',
'message_is_dismissible' => false,
));
$msg->box();
return;
}
if ( !WPDADB::add_remote_database(
$database,
$host,
$user,
$passwd,
$port,
$schema,
$ssl,
$ssl_key,
$ssl_cert,
$ssl_ca,
$ssl_path,
$ssl_cipher
) ) {
$msg = new WPDA_Message_Box(array(
'message_text' => __( 'Cannot add remote database connection', 'wp-data-access' ),
'message_type' => 'error',
'message_is_dismissible' => false,
));
$msg->box();
} else {
// phpcs:disable WordPress.WP.I18n.MissingTranslatorsComment
$msg = new WPDA_Message_Box(array(
'message_text' => sprintf( __( 'Remote database connection `%s` added', 'wp-data-access' ), $database ),
));
// phpcs:enable WordPress.WP.I18n.MissingTranslatorsComment
$msg->box();
$this->switch_schema_name = $database;
}
}
}
/**
* Performs optimize table.
*/
protected function process_bulk_action_optimize_table() {
if ( isset( $_REQUEST['optimize_table_name'] ) ) {
$optimize_table_name = str_replace( '`', '', sanitize_text_field( wp_unslash( $_REQUEST['optimize_table_name'] ) ) );
if ( $this->process_bulk_action_check_wpnonce( "wpda-optimize-{$optimize_table_name}", '_wpnonce' ) ) {
$dbo_type = $this->get_dbo_type( $optimize_table_name );
// phpcs:disable WordPress.WP.I18n.MissingTranslatorsComment
if ( false === $dbo_type || 'BASE TABLE' !== $dbo_type ) {
$msg = new WPDA_Message_Box(array(
'message_text' => sprintf( __( 'Cannot optimize `%s`', 'wp-data-access' ), $optimize_table_name ),
'message_type' => 'error',
'message_is_dismissible' => false,
));
$msg->box();
} else {
// Optimize table.
$wpdadb = WPDADB::get_db_connection( $this->schema_name );
if ( null === $wpdadb ) {
/* translators: %s = remote database name */
wp_die( esc_attr( sprintf( __( 'ERROR - Remote database %s not available', 'wp-data-access' ), $this->schema_name ) ) );
}
$wpdadb->query( "optimize table `{$optimize_table_name}`" );
// db call ok; no-cache ok.
$msg = new WPDA_Message_Box(array(
'message_text' => sprintf( __( 'Table `%s` optimized', 'wp-data-access' ), $optimize_table_name ),
));
$msg->box();
}
// phpcs:enable WordPress.WP.I18n.MissingTranslatorsComment
}
}
}
/**
* Performs rename table/view.
*
* @since 1.6.6
*/
protected function process_bulk_action_rename_table() {
// Check arguments.
if ( !$this->process_bulk_action_check_action( 'rename_table_name_old', __( 'Missing old table name', 'wp-data-access' ) ) ) {
return;
}
if ( $this->process_bulk_action_check_action( 'rename_table_name_new', __( 'Missing new table name', 'wp-data-access' ) ) ) {
// Rename table is not allowed for WordPress tables (double check).
// phpcs:disable WordPress.Security.ValidatedSanitizedInput
$rename_table_name_old = sanitize_text_field( wp_unslash( $_REQUEST['rename_table_name_old'] ) );
$rename_table_name_new = sanitize_text_field( wp_unslash( $_REQUEST['rename_table_name_new'] ) );
// phpcs:enable WordPress.Security.ValidatedSanitizedInput
/* translators: %s = table name */
$err_txt = ' ' . sprintf( __( '[cannot rename WordPress table `%s`]', 'wp-data-access' ), $rename_table_name_old );
if ( '' === $rename_table_name_old ) {
$msg = new WPDA_Message_Box(array(
'message_text' => __( 'Missing old table name value', 'wp-data-access' ),
));
$msg->box();
return;
}
if ( '' === $rename_table_name_new ) {
$msg = new WPDA_Message_Box(array(
'message_text' => __( 'Missing new table name value', 'wp-data-access' ),
));
$msg->box();
return;
}
if ( $this->process_bulk_action_check_is_wp_table( $rename_table_name_old, $err_txt ) ) {
// Check if table exists.
if ( $this->process_bulk_action_check_table_exists( $rename_table_name_old ) ) {
// Check if rename is allowed.
if ( $this->process_bulk_action_check_wpnonce( "wpda-rename-{$rename_table_name_old}", '_wpnonce' ) ) {
$dbo_type = $this->get_dbo_type( $rename_table_name_old );
if ( false === $dbo_type || 'SYSTEM VIEW' === $dbo_type ) {
// phpcs:disable WordPress.WP.I18n.MissingTranslatorsComment
$msg = new WPDA_Message_Box(array(
'message_text' => sprintf( __( 'Cannot rename `%s`', 'wp-data-access' ), $rename_table_name_old ),
'message_type' => 'error',
'message_is_dismissible' => false,
));
// phpcs:enable WordPress.WP.I18n.MissingTranslatorsComment
$msg->box();
} else {
// Rename table/view.
if ( false === $this->rename_table( $rename_table_name_old, $rename_table_name_new ) ) {
$msg = new WPDA_Message_Box(array(
'message_text' => __( 'Cannot rename', 'wp-data-access' ) . ' ' . strtolower( $dbo_type ) . ' `' . $rename_table_name_old . '`',
'message_type' => 'error',
'message_is_dismissible' => false,
));
$msg->box();
} else {
$msg = new WPDA_Message_Box(array(
'message_text' => strtoupper( substr( $dbo_type, 0, 1 ) ) . strtolower( substr( $dbo_type, 1 ) ) . ' `' . $rename_table_name_old . '` ' . __( 'renamed to', 'wp-data-access' ) . ' `' . $rename_table_name_new . '` ',
));
$msg->box();
}
}
}
}
}
}
}
/**
* Rename table/view.
*
* @param string $rename_table_name_old Old table name.
* @param string $rename_table_name_new New table name.
*
* @return false|int
* @since 1.6.6
*/
protected function rename_table( $rename_table_name_old, $rename_table_name_new ) {
if ( WPDA::is_wp_table( $rename_table_name_old ) ) {
// Never ever allow renaming a WordPress table!
$msg = new WPDA_Message_Box(array(
'message_text' => __( 'Not authorized [cannot rename WordPress tables]', 'wp-data-access' ),
'message_type' => 'error',
'message_is_dismissible' => false,
));
$msg->box();
return false;
}
$wpdadb = WPDADB::get_db_connection( $this->schema_name );
if ( null === $wpdadb ) {
/* translators: %s = remote database name */
wp_die( esc_attr( sprintf( __( 'ERROR - Remote database %s not available', 'wp-data-access' ), $this->schema_name ) ) );
}
return $wpdadb->query( 'rename table `' . str_replace( '`', '', $rename_table_name_old ) . '` to `' . str_replace( '`', '', $rename_table_name_new ) . '`' );
// db call ok; no-cache ok.
}
/**
* Performs copying a table.
*
* @since 1.6.6
*/
protected function process_bulk_action_copy_table() {
// Check arguments.
if ( !$this->process_bulk_action_check_action( 'copy_table_name_src', __( 'Missing source table name', 'wp-data-access' ) ) ) {
return;
}
if ( $this->process_bulk_action_check_action( 'copy_table_name_dst', __( 'Missing destination table name', 'wp-data-access' ) ) ) {
// copy table is not allowed for WordPress tables (double check).
// phpcs:disable WordPress.Security.ValidatedSanitizedInput
$copy_schema_name_src = sanitize_text_field( wp_unslash( $_REQUEST['copy_schema_name_src'] ) );
$copy_table_name_src = sanitize_text_field( wp_unslash( $_REQUEST['copy_table_name_src'] ) );
$copy_schema_name_dst = sanitize_text_field( wp_unslash( $_REQUEST['copy_schema_name_dst'] ) );
$copy_table_name_dst = sanitize_text_field( wp_unslash( $_REQUEST['copy_table_name_dst'] ) );
// phpcs:enable WordPress.Security.ValidatedSanitizedInput
if ( '' === $copy_schema_name_src ) {
$msg = new WPDA_Message_Box(array(
'message_text' => __( 'Missing source schema name', 'wp-data-access' ),
));
$msg->box();
return;
}
if ( '' === $copy_table_name_src ) {
$msg = new WPDA_Message_Box(array(
'message_text' => __( 'Missing source table name', 'wp-data-access' ),
));
$msg->box();
return;
}
if ( '' === $copy_schema_name_dst ) {
$msg = new WPDA_Message_Box(array(
'message_text' => __( 'Missing destination schema name', 'wp-data-access' ),
));
$msg->box();
return;
}
if ( '' === $copy_table_name_dst ) {
$msg = new WPDA_Message_Box(array(
'message_text' => __( 'Missing destination table name', 'wp-data-access' ),
));
$msg->box();
return;
}
// Check if table exists.
if ( $this->process_bulk_action_check_table_exists( $copy_table_name_src ) ) {
// Check if copy is allowed.
if ( $this->process_bulk_action_check_wpnonce( "wpda-copy-{$copy_table_name_src}", '_wpnonce' ) ) {
$dbo_type = $this->get_dbo_type( $copy_table_name_src );
if ( false === $dbo_type || 'SYSTEM VIEW' === $dbo_type ) {
// phpcs:disable WordPress.WP.I18n.MissingTranslatorsComment
$msg = new WPDA_Message_Box(array(
'message_text' => sprintf( __( 'Cannot copy `%s`', 'wp-data-access' ), $copy_table_name_src ),
'message_type' => 'error',
'message_is_dismissible' => false,
));
// phpcs:enable WordPress.WP.I18n.MissingTranslatorsComment
$msg->box();
} else {
$include_data = ( isset( $_REQUEST['copy-table-data'] ) ? 'on' : 'off' );
// Copy table/view.
if ( false === $this->copy_table(
$copy_schema_name_src,
$copy_table_name_src,
$copy_schema_name_dst,
$copy_table_name_dst,
$include_data
) ) {
$msg = new WPDA_Message_Box(array(
'message_text' => __( 'Cannot copy', 'wp-data-access' ) . ' ' . strtolower( $dbo_type ) . ' ' . $copy_table_name_src,
'message_type' => 'error',
'message_is_dismissible' => false,
));
$msg->box();
} else {
$msg = new WPDA_Message_Box(array(
'message_text' => strtoupper( substr( $dbo_type, 0, 1 ) ) . strtolower( substr( $dbo_type, 1 ) ) . " `{$copy_schema_name_src}`.`{$copy_table_name_src}` " . __( 'copied to', 'wp-data-access' ) . " `{$copy_schema_name_dst}`.`{$copy_table_name_dst}` ",
));
$msg->box();
}
}
}
}
}
}
/**
* Copy table.
*
* @param string $copy_schema_name_src Source schema name.
* @param string $copy_table_name_src Source table name.
* @param string $copy_schema_name_dst Destination schema name.
* @param string $copy_table_name_dst Destination table name.
* @param string $include_data 'on' = include data.
*
* @return false|int
* @since 1.6.6
*/
protected function copy_table(
$copy_schema_name_src,
$copy_table_name_src,
$copy_schema_name_dst,
$copy_table_name_dst,
$include_data
) {
$copy_schema_name_src = WPDA::remove_backticks( $copy_schema_name_src );
$copy_table_name_src = WPDA::remove_backticks( $copy_table_name_src );
$copy_schema_name_dst = WPDA::remove_backticks( $copy_schema_name_dst );
$copy_table_name_dst = WPDA::remove_backticks( $copy_table_name_dst );
$wpdadb_src = WPDADB::get_db_connection( $copy_schema_name_src );
if ( null === $wpdadb_src ) {
return false;
}
$wpdadb_dst = WPDADB::get_db_connection( $copy_schema_name_dst );
if ( null === $wpdadb_dst ) {
return false;
}
$suppress_wpdadb_src = $wpdadb_src->suppress_errors;
$wpdadb_src->suppress_errors = true;
$suppress_wpdadb_dst = $wpdadb_dst->suppress_errors;
$wpdadb_dst->suppress_errors = true;
// Get create table statement from $wpdadb_src.
// NO_TABLE_OPTIONS is deprecated in V8
// $wpdadb_src->query( "SET sql_mode = 'NO_TABLE_OPTIONS'" );
$query = "show create table `{$copy_table_name_src}`";
$ctcmd = $wpdadb_src->get_results( $query, 'ARRAY_A' );
if ( '' !== $wpdadb_src->last_error || !isset( $ctcmd[0]['Create Table'] ) ) {
$wpdadb_src->suppress_errors( $suppress_wpdadb_src );
$wpdadb_dst->suppress_errors( $suppress_wpdadb_dst );
return false;
}
$create_table_statement = $ctcmd[0]['Create Table'];
if ( $copy_table_name_src !== $copy_table_name_dst ) {
// Modify create table statement
$pos = strpos( $create_table_statement, $copy_table_name_src );
if ( $pos !== false ) {
$create_table_statement = substr_replace(
$create_table_statement,
$copy_table_name_dst,
$pos,
strlen( $copy_table_name_src )
);
}
}
// Create new table in $wpdadb_dst
$wpdadb_dst->query( $create_table_statement );
if ( '' !== $wpdadb_dst->last_error ) {
$wpdadb_src->suppress_errors( $suppress_wpdadb_src );
$wpdadb_dst->suppress_errors( $suppress_wpdadb_dst );
return false;
}
if ( 'on' !== $include_data ) {
return true;
}
if ( $copy_schema_name_src === $copy_schema_name_dst ) {
// No need for buffering if source database === destination database
$result = $wpdadb_dst->query( "insert `{$copy_table_name_dst}` select * from `{$copy_table_name_src}`" );
// db call ok; no-cache ok.
$wpdadb_src->suppress_errors( $suppress_wpdadb_src );
$wpdadb_dst->suppress_errors( $suppress_wpdadb_dst );
return $result;
}
// Check if buffering is needed for this table
$settings_db = WPDA_Table_Settings_Model::query( $copy_table_name_src, $copy_schema_name_src );
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->query_buffer_size ) ) {
$query_buffer_size = $settings_db_custom->table_settings->query_buffer_size;
} else {
$query_buffer_size = 0;
}
} else {
$query_buffer_size = 0;
}
// Copy table data from $wpdadb to $wpdb
$query = "select * from `{$copy_table_name_src}`";
if ( is_numeric( $query_buffer_size ) && $query_buffer_size > 0 ) {
// phpcs:disable Squiz.PHP.DiscouragedFunctions.Discouraged
set_time_limit( 0 );
// phpcs:enable Squiz.PHP.DiscouragedFunctions.Discouraged
?>
Copy table ``.``
To ``.``
Hang on...
Table `` created...
Copying data...
get_table_columns();
$column_data_types = array();
foreach ( $table_columns as $column_value ) {
$column_data_types[$column_value['column_name']] = $column_value['data_type'];
}
$i = 0;
$total = 0;
$sql = $query . ' limit ' . $query_buffer_size;
$rows = $wpdadb_src->get_results( $sql, 'ARRAY_A' );
while ( $wpdadb_src->num_rows > 0 ) {
$total += $wpdadb_src->num_rows;
foreach ( $rows as $row ) {
$wpdadb_dst->insert( $copy_table_name_dst, $row );
$wpdadb_dst->flush();
$wpdadb_dst->queries = null;
}
echo '';
echo 'Copied ' . number_format( $total ) . ' rows...
';
ob_flush();
flush();
$i++;
$wpdadb_src->flush();
$wpdadb_src->queries = null;
$sql = $query . ' limit ' . $query_buffer_size . ' offset ' . $i * $query_buffer_size;
$rows = $wpdadb_src->get_results( $sql, 'ARRAY_A' );
}
echo '';
} else {
$rows = $wpdadb_src->get_results( $query, 'ARRAY_A' );
foreach ( $rows as $row ) {
$wpdadb_dst->insert( $copy_table_name_dst, $row );
}
}
$wpdadb_src->suppress_errors( $suppress_wpdadb_src );
$wpdadb_dst->suppress_errors( $suppress_wpdadb_dst );
return true;
}
/**
* Performs bulk export.
*
* @since 1.5.0
*/
protected function process_bulk_action_bulk_export() {
// Check is there is anything to export.
if ( $this->process_bulk_action_check_action( 'bulk-selected', __( 'Empty bulk selected', 'wp-data-access' ) ) ) {
// Check if export is allowed.
if ( $this->process_bulk_action_check_wpnonce( 'wpda-export-' . json_encode( $this->table_name ), '_wpnonce' ) ) {
// Get arguments.
// phpcs:disable WordPress.Security.ValidatedSanitizedInput
$bulk_tabs = ( isset( $_REQUEST['bulk-selected'] ) ? $_REQUEST['bulk-selected'] : '' );
// phpcs:enable WordPress.Security.ValidatedSanitizedInput
$wp_nonce = wp_create_nonce( 'wpda-export-' . WPDA::get_current_user_login() );
$cnt = 0;
$selected_tables = array();
foreach ( $bulk_tabs as $table_name ) {
$export_table_name = sanitize_text_field( wp_unslash( $table_name ) );
// input var okay.
/* translators: %s = table name */
$err_txt = ' ' . sprintf( __( '[table `%s`]', 'wp-data-access' ), $export_table_name );
if ( $this->process_bulk_action_check_table_exists( $export_table_name, $err_txt ) ) {
$dbo_type = $this->get_dbo_type( $export_table_name );
if ( false === $dbo_type || 'VIEW' === $dbo_type || 'SYSTEM VIEW' === $dbo_type ) {
// phpcs:disable WordPress.WP.I18n.MissingTranslatorsComment
$msg = new WPDA_Message_Box(array(
'message_text' => sprintf( __( 'Cannot export `%s`', 'wp-data-access' ), $export_table_name ),
'message_type' => 'error',
'message_is_dismissible' => false,
));
// phpcs:enable WordPress.WP.I18n.MissingTranslatorsComment
$msg->box();
} else {
$selected_tables[] = $export_table_name;
$cnt++;
}
}
}
if ( 0 < $cnt ) {
?>
$msg,
));
$msg->box();
return false;
}
return true;
}
/**
* Checks wpnonce against a specific action.
*
* @param string $wp_nonce_action Nonce action.
* @param string $wp_nonce_arg Nonce argument.
*
* @return bool TRUE = action allowed.
* @since 1.5.0
*/
protected function process_bulk_action_check_wpnonce( $wp_nonce_action, $wp_nonce_arg ) {
$wp_nonce = ( isset( $_REQUEST[$wp_nonce_arg] ) ? sanitize_text_field( wp_unslash( $_REQUEST[$wp_nonce_arg] ) ) : '' );
// input var okay.
if ( !wp_verify_nonce( $wp_nonce, $wp_nonce_action ) ) {
$msg = new WPDA_Message_Box(array(
'message_text' => __( 'Not authorized', 'wp-data-access' ),
'message_type' => 'error',
'message_is_dismissible' => false,
));
$msg->box();
return false;
}
return true;
}
/**
* Checks if table exists.
*
* @param string $table_name Database table name.
* @param string $err_txt Additional error text/info.
*
* @return bool TRUE = table exists.
* @since 1.5.0
*/
protected function process_bulk_action_check_table_exists( $table_name, $err_txt = '' ) {
$wpda_dictionary = new WPDA_Dictionary_Exist($this->schema_name, $table_name);
if ( !$wpda_dictionary->table_exists() ) {
$msg = new WPDA_Message_Box(array(
'message_text' => __( 'Not authorized [table not found]', 'wp-data-access' ) . $err_txt,
'message_type' => 'error',
'message_is_dismissible' => false,
));
$msg->box();
return false;
}
return true;
}
/**
* Get database object type (VIEW, BASE_TABLE, SYSTEM VIEW).
*
* @param string $dbo_name Table or view name.
*
* @return string|boolean Database object type or false.
* @since 1.5.0
*/
protected function get_dbo_type( $dbo_name ) {
$wpdadb = WPDADB::get_db_connection( $this->schema_name );
if ( null === $wpdadb ) {
return false;
}
$query = $wpdadb->prepare( '
SELECT table_type AS table_type
FROM information_schema.tables
WHERE table_schema = %s
AND table_name = %s
', array($wpdadb->dbname, $dbo_name) );
// db call ok; no-cache ok.
$result = $wpdadb->get_results( $query, 'ARRAY_A' );
if ( 1 === $wpdadb->num_rows ) {
return $result[0]['table_type'];
} else {
return false;
}
}
/**
* Performs a drop table or view
*
* Method does not drop WordPress tables.
*/
protected function process_bulk_action_bulk_drop() {
// Check is there is anything to drop.
if ( $this->process_bulk_action_check_action( 'bulk-selected', __( 'Empty bulk selected', 'wp-data-access' ) ) ) {
// Check if drop is allowed.
if ( $this->process_bulk_action_check_wpnonce( 'wpda-drop-' . WPDA::get_current_user_login(), '_wpnonce3' ) ) {
// phpcs:disable WordPress.Security.ValidatedSanitizedInput
$bulk_tabs = ( isset( $_REQUEST['bulk-selected'] ) ? $_REQUEST['bulk-selected'] : '' );
// phpcs:enable WordPress.Security.ValidatedSanitizedInput
foreach ( $bulk_tabs as $table_name ) {
// Drop table is not allowed for WordPress tables (double check).
$drop_table_name = sanitize_text_field( wp_unslash( $table_name ) );
// input var okay.
/* translators: %s = table name */
$err_txt = ' ' . sprintf( __( '[cannot drop WordPress table `%s`]', 'wp-data-access' ), $drop_table_name );
if ( $this->process_bulk_action_check_is_wp_table( $drop_table_name, $err_txt ) ) {
// Check if table exists.
/* translators: %s = table name */
$err_txt = ' ' . sprintf( __( '[table `%s`]', 'wp-data-access' ), $drop_table_name );
if ( $this->process_bulk_action_check_table_exists( $drop_table_name, $err_txt ) ) {
$dbo_type = $this->get_dbo_type( $drop_table_name );
// phpcs:disable WordPress.WP.I18n.MissingTranslatorsComment
if ( false === $dbo_type || 'SYSTEM VIEW' === $dbo_type ) {
$msg = new WPDA_Message_Box(array(
'message_text' => sprintf( __( 'Cannot drop `%s`', 'wp-data-access' ), $drop_table_name ),
'message_type' => 'error',
'message_is_dismissible' => false,
));
$msg->box();
} else {
if ( 'VIEW' === $dbo_type ) {
// Drop view.
if ( $this->drop_view( $drop_table_name ) ) {
$msg = new WPDA_Message_Box(array(
'message_text' => sprintf( __( 'View `%s` dropped', 'wp-data-access' ), $drop_table_name ),
));
$msg->box();
}
} else {
// Drop table.
if ( $this->drop_table( $drop_table_name ) ) {
$msg = new WPDA_Message_Box(array(
'message_text' => sprintf( __( 'Table `%s` dropped', 'wp-data-access' ), $drop_table_name ),
));
$msg->box();
$this->post_drop_table( $drop_table_name );
}
}
}
// phpcs:enable WordPress.WP.I18n.MissingTranslatorsComment
}
}
}
}
}
}
/**
* Silently delete table related info from repository (called after drop table)
*
* @param string $drop_table_name Database table name
*/
protected function post_drop_table( $drop_table_name ) {
global $wpdb;
$suppress = $wpdb->suppress_errors( true );
// Table settings...
// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQLPlaceholders, WordPress.DB.DirectDatabaseQuery.SchemaChange
$wpdb->query( $wpdb->prepare( 'delete from `%1s` where wpda_schema_name = %s and wpda_table_name = %s ', array(WPDA::remove_backticks( WPDA_Table_Settings_Model::get_base_table_name() ), $this->schema_name, $drop_table_name) ) );
// WordPress media library columns...
$wpdb->query( $wpdb->prepare( 'delete from `%1s` where media_schema_name = %s and media_table_name = %s ', array(WPDA::remove_backticks( WPDA_Media_Model::get_base_table_name() ), $this->schema_name, $drop_table_name) ) );
// Data menus...
$wpdb->query( $wpdb->prepare( 'delete from `%1s` where menu_schema_name = %s and menu_table_name = %s ', array(WPDA::remove_backticks( WPDA_User_Menus_Model::get_base_table_name() ), $this->schema_name, $drop_table_name) ) );
$wpdb->suppress_errors( $suppress );
}
/**
* Checks if table is a WordPress table.
*
* @param string $table_name Database table name.
* @param string $err_txt Additional error text/info.
*
* @return bool TRUE = table is WordPress table.
* @since 1.5.0
*/
protected function process_bulk_action_check_is_wp_table( $table_name, $err_txt = '' ) {
if ( WPDA::is_wp_table( $table_name ) ) {
$msg = new WPDA_Message_Box(array(
'message_text' => __( 'Not authorized', 'wp-data-access' ) . $err_txt,
'message_type' => 'error',
'message_is_dismissible' => false,
));
$msg->box();
return false;
}
return true;
}
/**
* Performs drop view.
*
* @param string $view_name Database view name.
*
* @return bool TRUE = view dropped.
* @since 1.5.0
*/
protected function drop_view( $view_name ) {
$wpdadb = WPDADB::get_db_connection( $this->schema_name );
if ( null === $wpdadb ) {
/* translators: %s = remote database name */
wp_die( esc_attr( sprintf( __( 'ERROR - Remote database %s not available', 'wp-data-access' ), $this->schema_name ) ) );
}
return $wpdadb->query( 'drop view `' . str_replace( '`', '', $view_name ) . '`' );
// db call ok; no-cache ok.
}
/**
* Performs drop table.
*
* @param string $table_name Database table name.
*
* @return bool TRUE = table dropped.
* @since 1.5.0
*/
protected function drop_table( $table_name ) {
$wpdadb = WPDADB::get_db_connection( $this->schema_name );
if ( null === $wpdadb ) {
/* translators: %s = remote database name */
wp_die( esc_attr( sprintf( __( 'ERROR - Remote database %s not available', 'wp-data-access' ), $this->schema_name ) ) );
}
if ( WPDA::is_wp_table( $table_name ) ) {
// Never ever allow dropping a WordPress table!
$msg = new WPDA_Message_Box(array(
'message_text' => __( 'Not authorized [cannot drop WordPress tables]', 'wp-data-access' ),
'message_type' => 'error',
'message_is_dismissible' => false,
));
$msg->box();
return false;
}
return $wpdadb->query( 'drop table `' . str_replace( '`', '', $table_name ) . '`' );
// db call ok; no-cache ok.
}
/**
* Performs a truncate table
*
* Method does not truncate WordPress tables.
*/
protected function process_bulk_action_bulk_truncate() {
// Check is there is anything to truncate.
if ( $this->process_bulk_action_check_action( 'bulk-selected', __( 'No table defined', 'wp-data-access' ) ) ) {
// Check if truncate is allowed.
if ( $this->process_bulk_action_check_wpnonce( 'wpda-truncate-' . WPDA::get_current_user_login(), '_wpnonce4' ) ) {
// phpcs:disable WordPress.Security.ValidatedSanitizedInput
$bulk_tabs = ( isset( $_REQUEST['bulk-selected'] ) ? $_REQUEST['bulk-selected'] : '' );
// phpcs:enable WordPress.Security.ValidatedSanitizedInput
foreach ( $bulk_tabs as $table_name ) {
// Truncate table is not allowed for WordPress tables (double check).
$truncate_table_name = sanitize_text_field( wp_unslash( $table_name ) );
// input var okay.
/* translators: %s = table name */
$err_txt = ' ' . sprintf( __( '[cannot truncate WordPress table `%s`]', 'wp-data-access' ), $truncate_table_name );
if ( $this->process_bulk_action_check_is_wp_table( $truncate_table_name, $err_txt ) ) {
// Check if table exists.
/* translators: %s = table name */
$err_txt = ' ' . sprintf( __( '[table `%s`]', 'wp-data-access' ), $truncate_table_name );
if ( $this->process_bulk_action_check_table_exists( $truncate_table_name, $err_txt ) ) {
$dbo_type = $this->get_dbo_type( $truncate_table_name );
// phpcs:disable WordPress.WP.I18n.MissingTranslatorsComment
if ( false === $dbo_type || 'VIEW' === $dbo_type || 'SYSTEM VIEW' === $dbo_type ) {
$msg = new WPDA_Message_Box(array(
'message_text' => sprintf( __( 'Cannot truncate `%s`', 'wp-data-access' ), $truncate_table_name ),
'message_type' => 'error',
'message_is_dismissible' => false,
));
$msg->box();
} else {
// Truncate table.
if ( $this->truncate_table( $truncate_table_name ) ) {
$msg = new WPDA_Message_Box(array(
'message_text' => sprintf( __( 'Table `%s` truncated', 'wp-data-access' ), $truncate_table_name ),
));
$msg->box();
}
}
// phpcs:enable WordPress.WP.I18n.MissingTranslatorsComment
}
}
}
}
}
}
/**
* Performs truncate table.
*
* @param string $table_name Database table name.
*
* @return bool TRUE = table truncated.
* @since 1.5.0
*/
protected function truncate_table( $table_name ) {
$wpdadb = WPDADB::get_db_connection( $this->schema_name );
if ( null === $wpdadb ) {
/* translators: %s = remote database name */
wp_die( esc_attr( sprintf( __( 'ERROR - Remote database %s not available', 'wp-data-access' ), $this->schema_name ) ) );
}
if ( WPDA::is_wp_table( $table_name ) ) {
// Never ever allow truncating a WordPress table!
$msg = new WPDA_Message_Box(array(
'message_text' => __( 'Not authorized [cannot truncate WordPress tables]', 'wp-data-access' ),
'message_type' => 'error',
'message_is_dismissible' => false,
));
$msg->box();
return false;
}
// phpcs:disable WordPress.DB.PreparedSQLPlaceholders
$qry = $wpdadb->query( $wpdadb->prepare( 'truncate table `%1s`', [WPDA::remove_backticks( $table_name )] ) );
// db call ok; no-cache ok.
// phpcs:enable WordPress.DB.PreparedSQLPlaceholders
return $qry;
}
/**
* Processes drop table request.
*
* @since 1.5.0
*/
protected function process_bulk_action_drop() {
// Check is there is anything to drop.
if ( $this->process_bulk_action_check_action( 'drop_table_name', __( 'No table defined', 'wp-data-access' ) ) ) {
// Drop table is not allowed for WordPress tables (double check).
// phpcs:disable WordPress.Security.ValidatedSanitizedInput
$drop_table_name = sanitize_text_field( wp_unslash( $_REQUEST['drop_table_name'] ) );
// phpcs:enable WordPress.Security.ValidatedSanitizedInput
/* translators: %s = table name */
$err_txt = ' ' . sprintf( __( '[cannot drop WordPress table `%s`]', 'wp-data-access' ), $drop_table_name );
if ( $this->process_bulk_action_check_is_wp_table( $drop_table_name, $err_txt ) ) {
// Check if table exists.
if ( $this->process_bulk_action_check_table_exists( $drop_table_name ) ) {
// Check if drop is allowed.
if ( $this->process_bulk_action_check_wpnonce( "wpda-drop-{$drop_table_name}", '_wpnonce' ) ) {
$dbo_type = $this->get_dbo_type( $drop_table_name );
// phpcs:disable WordPress.WP.I18n.MissingTranslatorsComment
if ( false === $dbo_type || 'SYSTEM VIEW' === $dbo_type ) {
$msg = new WPDA_Message_Box(array(
'message_text' => sprintf( __( 'Cannot drop `%s`', 'wp-data-access' ), $drop_table_name ),
'message_type' => 'error',
'message_is_dismissible' => false,
));
$msg->box();
} else {
if ( 'VIEW' === $dbo_type ) {
// Drop view.
if ( $this->drop_view( $drop_table_name ) ) {
$msg = new WPDA_Message_Box(array(
'message_text' => sprintf( __( 'View `%s` dropped', 'wp-data-access' ), $drop_table_name ),
));
$msg->box();
}
} else {
// Drop table.
if ( $this->drop_table( $drop_table_name ) ) {
$msg = new WPDA_Message_Box(array(
'message_text' => sprintf( __( 'Table `%s` dropped', 'wp-data-access' ), $drop_table_name ),
));
$msg->box();
$this->post_drop_table( $drop_table_name );
}
}
}
// phpcs:enable WordPress.WP.I18n.MissingTranslatorsComment
}
}
}
}
}
/**
* Processes truncate table request.
*
* @since 1.5.0
*/
protected function process_bulk_action_truncate() {
// Check is there is anything to truncate.
if ( $this->process_bulk_action_check_action( 'truncate_table_name', __( 'No table defined', 'wp-data-access' ) ) ) {
// Truncate table is not allowed for WordPress tables (double check).
// phpcs:disable WordPress.Security.ValidatedSanitizedInput
$truncate_table_name = sanitize_text_field( wp_unslash( $_REQUEST['truncate_table_name'] ) );
// phpcs:enable WordPress.Security.ValidatedSanitizedInput
/* translators: %s = table name */
$err_txt = ' ' . sprintf( __( '[cannot truncate WordPress table `%s`]', 'wp-data-access' ), $truncate_table_name );
if ( $this->process_bulk_action_check_is_wp_table( $truncate_table_name, $err_txt ) ) {
// Check if table exists.
if ( $this->process_bulk_action_check_table_exists( $truncate_table_name ) ) {
// Check if truncate is allowed.
if ( $this->process_bulk_action_check_wpnonce( "wpda-truncate-{$truncate_table_name}", '_wpnonce' ) ) {
// Truncate table.
if ( $this->truncate_table( $truncate_table_name ) ) {
// phpcs:disable WordPress.WP.I18n.MissingTranslatorsComment
$msg = new WPDA_Message_Box(array(
'message_text' => sprintf( __( 'Table `%s` truncated', 'wp-data-access' ), $truncate_table_name ),
));
// phpcs:enable WordPress.WP.I18n.MissingTranslatorsComment
$msg->box();
}
}
}
}
}
}
protected function add_header_actions() {
$this->add_db_containers();
}
/**
* Overwrite method: add bulk array to check ddl allowed
*/
public function show() {
?>
schema_name );
if ( null === $wpdadb ) {
/* translators: %s = remote database name */
wp_die( esc_attr( sprintf( __( 'ERROR - Remote database %s not available', 'wp-data-access' ), $this->schema_name ) ) );
}
global $wpdb;
// Make sure we're selecting only tables that are in the WordPress database.
$where_or_and = ( '' === $this->where ? ' where ' : ' and ' );
$this->where .= $wpdadb->prepare( " {$where_or_and} table_schema = %s ", $wpdadb->dbname );
// Since we are using a view, the default behaviour of the parent will not work for us. We have to
// define our where clause manually.
$cols = array(array(
'column_name' => 'table_name',
'data_type' => 'varchar',
'extra' => '',
'column_type' => 'varchar(64)',
'is_nullable' => 'NO',
'column_default' => null,
));
$where = WPDA::construct_where_clause(
$this->schema_name,
$this->table_name,
$cols,
$this->search_value
);
if ( '' !== $where ) {
$this->where .= ' and ' . $where;
}
if ( $wpdb->dbname === $this->schema_name || '' === $this->schema_name ) {
$table_access = WPDA::get_option( WPDA::OPTION_BE_TABLE_ACCESS );
} else {
$table_access = get_option( WPDA::BACKEND_OPTIONNAME_DATABASE_ACCESS . $this->schema_name );
if ( false === $table_access ) {
$table_access = 'show';
}
}
if ( 'hide' === $table_access ) {
// No access to WordPress tables: filter WordPress table.
$this->where .= " and table_name not in ('" . implode( "','", $wpdb->tables( 'all', true ) ) . "')";
} elseif ( 'select' === $table_access ) {
if ( $wpdb->dbname === $this->schema_name || '' === $this->schema_name ) {
$option = WPDA::get_option( WPDA::OPTION_BE_TABLE_ACCESS_SELECTED );
} else {
$option = get_option( WPDA::BACKEND_OPTIONNAME_DATABASE_SELECTED . $this->schema_name );
if ( false === $option ) {
$option = '';
}
}
if ( '' !== $option ) {
// Allow only access to selected tables.
$this->where .= " and table_name in ('" . implode( "','", $option ) . "')";
} else {
// No tables selected: no access.
$this->where .= ' and 1=2';
}
}
if ( null != $this->wpda_main_favourites ) {
if ( false === $this->favourites && 'show' === $this->wpda_main_favourites ) {
$where_or_and = ( '' === $this->where ? ' where ' : ' and ' );
$this->where .= " {$where_or_and} 1=2 ";
} elseif ( is_array( $this->favourites ) ) {
if ( 0 < count( $this->favourites ) ) {
$where_or_and = ( '' === $this->where ? ' where ' : ' and ' );
$in_or_not_in = ( 'show' === $this->wpda_main_favourites ? 'in' : 'not in' );
$this->where .= " {$where_or_and} table_name {$in_or_not_in} ('" . implode( "','", $this->favourites ) . "') ";
}
}
}
}
protected function get_order_by() {
$orderby = parent::get_order_by();
if ( '' !== $orderby ) {
return $orderby;
} else {
return ' order by table_name asc ';
}
}
/**
* Overwrite method: add button to design a table
*/
protected function add_header_button() {
?>
wpda_import->add_button();
}
/**
* Add container to create new database
*/
protected function add_db_containers() {
if ( 'rdb:' === substr( $this->schema_name, 0, 4 ) ) {
$rdb = WPDADB::get_remote_database( $this->schema_name );
}
$host = ( isset( $rdb['host'] ) ? $rdb['host'] : '' );
$user = ( isset( $rdb['username'] ) ? $rdb['username'] : '' );
$passwd = ( isset( $rdb['password'] ) ? $rdb['password'] : '' );
$port = ( isset( $rdb['port'] ) ? $rdb['port'] : '' );
$schema = ( isset( $rdb['database'] ) ? $rdb['database'] : '' );
$ssl = ( isset( $rdb['ssl'] ) ? $rdb['ssl'] : '' );
$ssl_key = ( isset( $rdb['ssl_key'] ) ? $rdb['ssl_key'] : '' );
$ssl_cert = ( isset( $rdb['ssl_cert'] ) ? $rdb['ssl_cert'] : '' );
$ssl_ca = ( isset( $rdb['ssl_ca'] ) ? $rdb['ssl_ca'] : '' );
$ssl_path = ( isset( $rdb['ssl_path'] ) ? $rdb['ssl_path'] : '' );
$ssl_cipher = ( isset( $rdb['ssl_cipher'] ) ? $rdb['ssl_cipher'] : '' );
$readonly = '';
?>
:
schema_name, 0, 4 ) ) {
?>
onclick="jQuery('#wpda_db_edit').show();"
style="schema_name, 0, 4 ) ? '' : 'color:grey;cursor:default;' );
?>vertical-align:middle;"
title="schema_name, 0, 4 ) ? esc_attr__( 'Edit remote database connection', 'wp-data-access' ) : esc_attr__( 'Not available for local database', 'wp-data-access' ) );
?>">
user_can_drop_db ) {
if ( 'rdb:' === substr( $this->schema_name, 0, 4 ) ) {
$msg = esc_html__( 'Delete remote database connection?\\nDoes not drop the database! Only deletes the remote database connection definition.', 'wp-data-access' );
} else {
$msg = esc_html__( 'Drop selected database?', 'wp-data-access' );
}
?>
onclick="if (confirm('')) { jQuery('#drop_database').val(jQuery('#wpda_main_db_schema_list').val()); jQuery('#wpda_form_drop_db').submit(); }"
style="user_can_drop_db ? 'color:#a00;' : 'color:grey;cursor:default;' );
?>vertical-align:middle;"
title="user_drop_db_hint );
?>">
">
:
search_value && !$this->has_items()) ) {
?>
'search-submit',
)
);
?>
page . '_schema_name';
$wpda_main_db_schema = null;
if ( isset( $_REQUEST['wpda_main_db_schema'] ) && '' !== $_REQUEST['wpda_main_db_schema'] ) {
$wpda_main_db_schema = sanitize_text_field( wp_unslash( $_REQUEST['wpda_main_db_schema'] ) );
} elseif ( isset( $_COOKIE[$cookie_name] ) ) {
$wpda_main_db_schema = sanitize_text_field( wp_unslash( $_COOKIE[$cookie_name] ) );
// input var okay.
}
if ( null !== $wpda_main_db_schema ) {
if ( '' !== $wpda_main_db_schema && 'rdb:' !== substr( $wpda_main_db_schema, 0, 4 ) ) {
if ( !WPDA_Dictionary_Exist::schema_exists( $wpda_main_db_schema ) ) {
return WPDA::get_user_default_scheme();
}
}
if ( WPDA::schema_disabled( $wpda_main_db_schema ) ) {
return WPDA::get_user_default_scheme();
}
if ( WPDA::schema_exists( $wpda_main_db_schema ) ) {
return $wpda_main_db_schema;
}
/* translators: %s = remote database name */
echo '' . esc_attr( sprintf( __( 'ERROR - Remote database %s not available', 'wp-data-access' ), $wpda_main_db_schema ) ) . '
';
}
return WPDA::get_user_default_scheme();
}
/**
* Get favourite selection from cookie or list
*
* @return null|string
* @since 1.6.0
*/
protected function get_favourites() {
$cookie_name = $this->page . '_favourites';
if ( isset( $_REQUEST['wpda_main_favourites'] ) ) {
return sanitize_text_field( wp_unslash( $_REQUEST['wpda_main_favourites'] ) );
} elseif ( isset( $_COOKIE[$cookie_name] ) ) {
return sanitize_text_field( wp_unslash( $_COOKIE[$cookie_name] ) );
} else {
return null;
}
}
/**
* Add labels to static function to make it available to class WPDA_List _View. Allowing to hide columns in
* Data Explorer main page.
*
* @return array
* @since 2.0.3
*/
public static function column_headers_labels() {
return array(
'table_name' => __( 'Name', 'wp-data-access' ),
'icons' => '',
'table_type' => __( 'Type', 'wp-data-access' ),
'create_time' => __( 'Creation Date', 'wp-data-access' ),
'table_rows' => __( '#Rows', 'wp-data-access' ),
'auto_increment' => __( 'Increment', 'wp-data-access' ),
'engine' => __( 'Engine', 'wp-data-access' ),
'total_size' => __( 'Size', 'wp-data-access' ),
'data_size' => __( 'Data Size', 'wp-data-access' ),
'index_size' => __( 'Index Size', 'wp-data-access' ),
'overhead' => __( 'Overhead', 'wp-data-access' ),
'table_collation' => __( 'Collation', 'wp-data-access' ),
);
}
}
// phpcs:enable WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing