errors[ $code ][] = $message; if ( $data ) { $this->error_data[ $code ] = $data; } } } public function get_error_code() { $codes = array_keys( $this->errors ); return $codes ? $codes[0] : ''; } public function get_error_message( $code = '' ) { if ( ! $code ) { $code = $this->get_error_code(); } return isset( $this->errors[ $code ] ) ? $this->errors[ $code ][0] : ''; } } } // ── Load plugin classes for testing ─────────────────────────────────── // Content filter can be loaded standalone (no WordPress runtime needed). require_once PEPTIDE_NEWS_PLUGIN_DIR . 'includes/class-peptide-news-content-filter.php'; // LLM subsystem: client and prompt-builder must load before the orchestrator. require_once PEPTIDE_NEWS_PLUGIN_DIR . 'includes/class-peptide-news-llm-client.php'; require_once PEPTIDE_NEWS_PLUGIN_DIR . 'includes/class-peptide-news-llm-prompt-builder.php'; require_once PEPTIDE_NEWS_PLUGIN_DIR . 'includes/class-peptide-news-llm-ajax.php'; require_once PEPTIDE_NEWS_PLUGIN_DIR . 'includes/class-peptide-news-llm.php'; // Stub AJAX-related functions used by cost tracker and other modules. if ( ! function_exists( 'wp_send_json_success' ) ) { function wp_send_json_success( $data = null, $status_code = null ) { global $_test_json_response; $_test_json_response = array( 'success' => true, 'data' => $data ); } } if ( ! function_exists( 'wp_send_json_error' ) ) { function wp_send_json_error( $data = null, $status_code = null ) { global $_test_json_response; $_test_json_response = array( 'success' => false, 'data' => $data ); } } if ( ! function_exists( 'check_ajax_referer' ) ) { function check_ajax_referer( $action = -1, $query_arg = false, $die = true ) { return true; } } if ( ! function_exists( 'wp_unslash' ) ) { function wp_unslash( $value ) { return is_string( $value ) ? stripslashes( $value ) : $value; } } if ( ! function_exists( 'wp_json_encode' ) ) { function wp_json_encode( $data, $options = 0, $depth = 512 ) { return json_encode( $data, $options, $depth ); } } if ( ! function_exists( 'home_url' ) ) { function home_url( $path = '' ) { return 'https://example.com' . $path; } } if ( ! function_exists( 'wp_remote_post' ) ) { function wp_remote_post( $url, $args = array() ) { return new WP_Error( 'http_request_not_available', 'HTTP requests not available in tests' ); } } if ( ! function_exists( 'wp_remote_retrieve_response_code' ) ) { function wp_remote_retrieve_response_code( $response ) { return 200; } } if ( ! function_exists( 'wp_remote_retrieve_body' ) ) { function wp_remote_retrieve_body( $response ) { return ''; } } if ( ! function_exists( 'wp_remote_retrieve_header' ) ) { function wp_remote_retrieve_header( $response, $header ) { return ''; } } if ( ! function_exists( 'selected' ) ) { function selected( $selected, $current = true, $echo = true ) { $result = (string) $selected === (string) $current ? ' selected="selected"' : ''; if ( $echo ) { echo $result; } return $result; } } if ( ! function_exists( 'checked' ) ) { function checked( $checked, $current = true, $echo = true ) { $result = (string) $checked === (string) $current ? ' checked="checked"' : ''; if ( $echo ) { echo $result; } return $result; } } if ( ! function_exists( 'wp_enqueue_style' ) ) { function wp_enqueue_style( $handle, $src = '', $deps = array(), $ver = false, $media = 'all' ) { return true; } } if ( ! function_exists( 'wp_enqueue_script' ) ) { function wp_enqueue_script( $handle, $src = '', $deps = array(), $ver = false, $args = array() ) { return true; } } if ( ! function_exists( 'wp_localize_script' ) ) { function wp_localize_script( $handle, $object_name, $l10n ) { return true; } } if ( ! function_exists( 'add_menu_page' ) ) { function add_menu_page( $page_title, $menu_title, $capability, $menu_slug, $callback = '', $icon_url = '', $position = null ) { return $menu_slug; } } if ( ! function_exists( 'add_submenu_page' ) ) { function add_submenu_page( $parent_slug, $page_title, $menu_title, $capability, $menu_slug, $callback = '', $position = null ) { return $menu_slug; } } if ( ! function_exists( 'register_setting' ) ) { function register_setting( $option_group, $option_name, $args = array() ) { return true; } } if ( ! function_exists( 'add_settings_section' ) ) { function add_settings_section( $id, $title, $callback, $page, $args = array() ) { return true; } } if ( ! function_exists( 'add_settings_field' ) ) { function add_settings_field( $id, $title, $callback, $page, $section = 'default', $args = array() ) { return true; } } // Cost tracker provides calculate_cost(), budget checks used by tests. require_once PEPTIDE_NEWS_PLUGIN_DIR . 'includes/class-peptide-news-cost-tracker.php'; // Stub WP_REST_Request for REST API tests. if ( ! class_exists( 'WP_REST_Request' ) ) { class WP_REST_Request { private $params = array(); private $method = 'GET'; public function __construct( $method = 'GET', $route = '' ) { $this->method = $method; } public function set_param( $key, $value ) { $this->params[ $key ] = $value; } public function get_param( $key ) { return isset( $this->params[ $key ] ) ? $this->params[ $key ] : null; } public function get_params() { return $this->params; } } }