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 )}", "{$this->row_actions( $admin_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()) ) { ?>
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