Compare commits

3 Commits

Author SHA1 Message Date
peptiderepo
2660f27f40 fix(phpcs): remove strict_types declaration that breaks file header order
PSR12.Files.FileHeader.IncorrectOrder requires the docblock immediately
after the opening PHP tag. The declare(strict_types=1) was inserted
between them.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-16 17:00:24 +07:00
peptiderepo
1f64dfa797 fix(admin): add missing sanitize_model_id and sanitize_api_key delegators
The refactored orchestrator was missing public method delegations for
sanitize_model_id() and sanitize_api_key(), which tests call directly
on the Peptide_News_Admin instance and WordPress uses as register_setting
callbacks.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-16 16:58:30 +07:00
peptiderepo
7717186022 fix(admin): load delegate classes from orchestrator + add WP stubs for tests
The admin refactor split introduced delegate classes that the orchestrator
instantiates in its constructor. CI failed because tests require the
orchestrator directly without going through the plugin loader. Fix: add
require_once for all delegate files at the top of the orchestrator, and
add missing WP function stubs to the test bootstrap.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-16 16:54:38 +07:00
2 changed files with 86 additions and 1 deletions

View File

@@ -1,5 +1,4 @@
<?php <?php
declare( strict_types=1 );
/** /**
* Admin-specific functionality. * Admin-specific functionality.
* *
@@ -17,6 +16,16 @@ declare( strict_types=1 );
* @see Peptide_News_Admin_Settings_Page — Settings page + log viewer * @see Peptide_News_Admin_Settings_Page — Settings page + log viewer
* @see Peptide_News_Admin_Dashboard_Pages — Dashboard/articles/costs pages * @see Peptide_News_Admin_Dashboard_Pages — Dashboard/articles/costs pages
*/ */
// Load delegate classes that this orchestrator depends on.
require_once __DIR__ . '/class-pn-admin-assets.php';
require_once __DIR__ . '/class-pn-admin-menu.php';
require_once __DIR__ . '/class-pn-admin-field-renderers.php';
require_once __DIR__ . '/class-pn-admin-settings.php';
require_once __DIR__ . '/class-pn-admin-log-viewer.php';
require_once __DIR__ . '/class-pn-admin-settings-page.php';
require_once __DIR__ . '/class-pn-admin-dashboard-pages.php';
class Peptide_News_Admin { class Peptide_News_Admin {
/** @var string Plugin name/slug */ /** @var string Plugin name/slug */
@@ -140,4 +149,31 @@ class Peptide_News_Admin {
public function render_cost_dashboard_page(): void { public function render_cost_dashboard_page(): void {
$this->dashboard_pages->render_cost_dashboard_page(); $this->dashboard_pages->render_cost_dashboard_page();
} }
/**
* Sanitize and validate an OpenRouter model ID.
*
* Delegates to the settings class. Kept on the orchestrator because
* WordPress register_setting() callbacks may reference $this.
*
* @param string $value Raw model ID from form input.
* @return string Sanitized model ID or empty string on failure.
*/
public function sanitize_model_id( string $value ): string {
return $this->settings->sanitize_model_id( $value );
}
/**
* Sanitize an API key value — encrypt if new, preserve if masked.
*
* Delegates to the settings class. Kept on the orchestrator because
* WordPress register_setting() callbacks may reference $this.
*
* @param string $value Raw API key from form input.
* @param string $option_name The WP option being saved.
* @return string Encrypted key or previous value if input was masked.
*/
public function sanitize_api_key( string $value, string $option_name = '' ): string {
return $this->settings->sanitize_api_key( $value, $option_name );
}
} }

View File

@@ -300,6 +300,55 @@ if ( ! function_exists( 'selected' ) ) {
return $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. // Cost tracker provides calculate_cost(), budget checks used by tests.
require_once PEPTIDE_NEWS_PLUGIN_DIR . 'includes/class-peptide-news-cost-tracker.php'; require_once PEPTIDE_NEWS_PLUGIN_DIR . 'includes/class-peptide-news-cost-tracker.php';