table = $wpdb->prefix . 'xfeepro_methods'; } // ── Schema (shared table — CREATE IF NOT EXISTS, so either plugin may make it) ─ public static function create_table() { global $wpdb; $table = $wpdb->prefix . 'xfeepro_methods'; $charset_collate = $wpdb->get_charset_collate(); $sql = "CREATE TABLE IF NOT EXISTS {$table} ( id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, sort_order INT(8) NULL DEFAULT 0, method_data LONGTEXT NULL, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id) ) {$charset_collate};"; require_once ABSPATH . 'wp-admin/includes/upgrade.php'; dbDelta( $sql ); } public static function drop_table() { global $wpdb; $table = $wpdb->prefix . 'xfeepro_methods'; // phpcs:ignore WordPress.DB.DirectDatabaseQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- table name is $wpdb->prefix + a fixed string; identifiers can't be bound via prepare(). $wpdb->query( "DROP TABLE IF EXISTS {$table}" ); } // ── Read ───────────────────────────────────────────────────────────────── public function getData() { global $wpdb; // phpcs:ignore WordPress.DB.DirectDatabaseQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- fixed prefixed table identifier; not bindable via prepare(). $rows = $wpdb->get_results( "SELECT * FROM {$this->table} ORDER BY id ASC", ARRAY_A ); if ( ! $rows ) { return array(); } foreach ( $rows as &$row ) { $row['method_data'] = json_decode( $row['method_data'], true ) ?: array(); $row['method_data']['sort_order'] = (int) $row['sort_order']; } unset( $row ); return $rows; } public function getDataById( $id ) { global $wpdb; // phpcs:ignore WordPress.DB.DirectDatabaseQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- fixed prefixed table identifier; id is bound via prepare(). $row = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$this->table} WHERE id = %d", $id ), ARRAY_A ); if ( ! $row ) { return null; } $row['method_data'] = json_decode( $row['method_data'], true ) ?: array(); $row['method_data']['sort_order'] = (int) $row['sort_order']; return $row; } // ── Write ───────────────────────────────────────────────────────────────── public function addData( array $method_data ) { global $wpdb; $sort_order = isset( $method_data['sort_order'] ) ? (int) $method_data['sort_order'] : 0; unset( $method_data['sort_order'] ); $wpdb->insert( // phpcs:ignore WordPress.DB.DirectDatabaseQuery $this->table, array( 'sort_order' => $sort_order, 'method_data' => wp_json_encode( $method_data ), ), array( '%d', '%s' ) ); return (int) $wpdb->insert_id; } public function updateData( $id, array $method_data ) { global $wpdb; $sort_order = isset( $method_data['sort_order'] ) ? (int) $method_data['sort_order'] : 0; unset( $method_data['sort_order'] ); $wpdb->update( // phpcs:ignore WordPress.DB.DirectDatabaseQuery $this->table, array( 'sort_order' => $sort_order, 'method_data' => wp_json_encode( $method_data ), ), array( 'id' => (int) $id ), array( '%d', '%s' ), array( '%d' ) ); } public function deleteData( $id ) { global $wpdb; $wpdb->delete( $this->table, array( 'id' => (int) $id ), array( '%d' ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery } public function updateSortOrder( $id, $sort_order ) { global $wpdb; $wpdb->update( // phpcs:ignore WordPress.DB.DirectDatabaseQuery $this->table, array( 'sort_order' => (int) $sort_order ), array( 'id' => (int) $id ), array( '%d' ), array( '%d' ) ); } public function copyData( $id ) { $row = $this->getDataById( $id ); if ( ! $row ) { return false; } $method_data = $row['method_data']; $method_data['sort_order'] = $row['sort_order']; if ( isset( $method_data['display'] ) ) { $method_data['display'] = $method_data['display'] . ' (Copy)'; } return $this->addData( $method_data ); } }