split: extract PRV_Settings_Controller from settings-page (300-line fix)
class-prv-settings-page.php was 346 lines — the only file over the 300-line cap. Extract the four POST handlers (handle_save, handle_model_add, handle_model_update, handle_model_remove) into a new PRV_Settings_Controller class (class-prv-settings-controller.php). PRV_Settings_Page::register_hooks() instantiates the controller once, passing a nonce-verification callback (bound to require_admin_nonce()). All four admin_post_* hooks now delegate to the controller. All phpcs:disable/enable WordPress.Security.NonceVerification.Missing wrappers and sanitize_*/wp_unslash() calls traveled with the moved handlers. PHPCS stays green. Result: class-prv-settings-page.php 193 lines class-prv-settings-controller.php 213 lines All other production PHP files ≤300 lines Also: ARCHITECTURE.md file-tree updated; @see cross-refs added to both class docblocks; CHANGELOG 0.2.0 CI section updated. Version: 0.2.0
This commit is contained in:
@@ -39,7 +39,8 @@ pr-vision/
|
||||
│ │ ├── class-prv-probe-runner.php # Orchestrates run: lock + peptide*intent*model loop
|
||||
│ │ ├── class-prv-collector-registry.php # Singleton registry for collectors + panels
|
||||
│ │ ├── class-prv-admin-page.php # Dashboard page: menu, Run now, rendering
|
||||
│ │ ├── class-prv-settings-page.php # [v0.2] Settings page: POST handlers + AJAX dispatch
|
||||
│ │ ├── class-prv-settings-page.php # [v0.2] Settings page: menu, Run-now, AJAX dispatch; delegates POST to PRV_Settings_Controller
|
||||
│ │ ├── class-prv-settings-controller.php # [v0.2] POST handler impl: save config, model CRUD (split from settings-page)
|
||||
│ │ ├── class-prv-settings-renderer.php # [v0.2] Settings HTML renderer (dark Assay theme)
|
||||
│ │ ├── class-prv-model-manager-table.php # [v0.2] Model manager table + Add form renderer
|
||||
│ │ └── class-prv-model-test-ajax.php # [v0.2] Rate-limited AJAX handler for Test button
|
||||
|
||||
@@ -102,3 +102,4 @@ Admin/Settings interface + correctness fixes. All adversarial-QA must-fixes addr
|
||||
- **P1-C:** Added `phpcs:disable/enable WordPress.Security.NonceVerification.Missing` around `$_POST` blocks in all four `handle_*()` methods in `class-prv-settings-page.php`; nonce is verified via `require_admin_nonce()` private helper.
|
||||
- **P1-D/E:** Expanded inline associative arrays to multi-line in `class-prv-config.php`, `class-prv-probe-runner.php`, `class-prv-settings-renderer.php`, `class-prv-model-test-ajax.php`; fixed param-comment spacing in `class-prv-model-registry.php`; capitalised docblock long-description first word.
|
||||
- **PHPCS compliance:** Expanded remaining 5 inline associative arrays in `class-prv-settings-page.php` (`add_query_arg` calls + `PRV_Model_Registry::update` data array) to multi-line with trailing comma; corrected `@param` column alignment in `class-prv-probe-runner.php:update_api_key_status` and `class-prv-model-registry.php:update_health` to match longest-type rule. PHPCS: 0 errors / 0 warnings.
|
||||
- **300-line split:** extracted `handle_save`, `handle_model_add`, `handle_model_update`, `handle_model_remove` from `class-prv-settings-page.php` (346 lines) into new `class-prv-settings-controller.php` (`PRV_Settings_Controller`); settings-page delegates via nonce callback. All `phpcs:disable/enable WordPress.Security.NonceVerification.Missing` wrappers carried with the moved handlers. Both files now ≤213 lines; no file exceeds 300 lines.
|
||||
|
||||
213
includes/core/class-prv-settings-controller.php
Normal file
213
includes/core/class-prv-settings-controller.php
Normal file
@@ -0,0 +1,213 @@
|
||||
<?php
|
||||
/**
|
||||
* PR Vision settings POST-action controller.
|
||||
*
|
||||
* @package PrVision
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Handles the four settings POST actions: save config, and model CRUD.
|
||||
*
|
||||
* Extracted from PRV_Settings_Page to keep each file under the 300-line
|
||||
* limit. PRV_Settings_Page registers all hooks and delegates the four
|
||||
* admin_post_* handlers here.
|
||||
*
|
||||
* All actions require: current_user_can('manage_options') + valid nonce
|
||||
* (enforced by PRV_Settings_Page::require_admin_nonce(), passed in via
|
||||
* the $nonce_cb callable).
|
||||
*
|
||||
* Who triggers: PRV_Settings_Page -- via delegation in register_hooks().
|
||||
* Dependencies: PRV_Config, PRV_Config_Version, PRV_Cron,
|
||||
* PRV_Model_Registry.
|
||||
*
|
||||
* @see class-prv-settings-page.php -- Page registration, dispatch, Run-now, AJAX.
|
||||
* @see class-prv-model-registry.php -- CRUD for prv_models.
|
||||
* @see class-prv-config-version.php -- Config-change versioning.
|
||||
* @see class-prv-cron.php -- Reschedule on cadence change.
|
||||
* @package PrVision
|
||||
*/
|
||||
class PRV_Settings_Controller {
|
||||
|
||||
/** Admin menu slug (shared constant with PRV_Settings_Page). */
|
||||
const MENU_SLUG = 'pr-vision-settings';
|
||||
|
||||
/** @var callable(): void Nonce-verification callback supplied by PRV_Settings_Page. */
|
||||
private $nonce_cb;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param callable $nonce_cb Called with a nonce-action string; wp_die on failure.
|
||||
*/
|
||||
public function __construct( callable $nonce_cb ) {
|
||||
$this->nonce_cb = $nonce_cb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the settings save POST action.
|
||||
*
|
||||
* Validates, sanitizes, saves peptides/intents/cadence/budget. Bumps
|
||||
* config-version if scoring-relevant fields changed. Reschedules cron
|
||||
* if cadence changed.
|
||||
*
|
||||
* Side effects: Updates wp_options, may reschedule cron, redirects.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle_save(): void {
|
||||
( $this->nonce_cb )( PRV_Settings_Page::NONCE_SAVE );
|
||||
$old_cadence = PRV_Config::get_cadence();
|
||||
|
||||
// phpcs:disable WordPress.Security.NonceVerification.Missing -- nonce verified above via require_admin_nonce().
|
||||
$budget = isset( $_POST['prv_monthly_budget_usd'] )
|
||||
? max( 0.01, (float) sanitize_text_field( wp_unslash( (string) $_POST['prv_monthly_budget_usd'] ) ) )
|
||||
: PRV_DEFAULT_MONTHLY_BUDGET_USD;
|
||||
update_option( 'prv_monthly_budget_usd', $budget );
|
||||
|
||||
$cadence_raw = isset( $_POST['prv_cadence'] )
|
||||
? sanitize_text_field( wp_unslash( (string) $_POST['prv_cadence'] ) )
|
||||
: 'weekly';
|
||||
$cadence = in_array( $cadence_raw, array( 'weekly', 'daily', 'twicedaily' ), true ) ? $cadence_raw : 'weekly';
|
||||
update_option( PRV_Config::CADENCE_KEY, $cadence );
|
||||
|
||||
if ( ! empty( $_POST['prv_peptides_json'] ) ) {
|
||||
$raw_json = sanitize_textarea_field( wp_unslash( (string) $_POST['prv_peptides_json'] ) );
|
||||
$decoded = json_decode( $raw_json, true );
|
||||
if ( is_array( $decoded ) ) {
|
||||
$clean = array();
|
||||
foreach ( $decoded as $p ) {
|
||||
if ( isset( $p['slug'], $p['label'] ) ) {
|
||||
$clean[] = array(
|
||||
'slug' => sanitize_text_field( (string) $p['slug'] ),
|
||||
'label' => sanitize_text_field( (string) $p['label'] ),
|
||||
);
|
||||
}
|
||||
}
|
||||
update_option( 'prv_peptides', $clean );
|
||||
}
|
||||
}
|
||||
|
||||
if ( isset( $_POST['prv_prompt_intents_text'] ) ) {
|
||||
$raw_intents = sanitize_textarea_field( wp_unslash( (string) $_POST['prv_prompt_intents_text'] ) );
|
||||
$intent_lines = array_filter( array_map( 'trim', explode( "\n", $raw_intents ) ) );
|
||||
update_option( 'prv_prompt_intents', array_values( $intent_lines ) );
|
||||
}
|
||||
// phpcs:enable WordPress.Security.NonceVerification.Missing
|
||||
|
||||
PRV_Config_Version::bump_version_if_changed();
|
||||
|
||||
if ( $cadence !== $old_cadence ) {
|
||||
PRV_Cron::reschedule( $cadence );
|
||||
}
|
||||
|
||||
wp_safe_redirect(
|
||||
add_query_arg(
|
||||
array(
|
||||
'page' => self::MENU_SLUG,
|
||||
'prv_saved' => 1,
|
||||
),
|
||||
admin_url( 'admin.php' )
|
||||
)
|
||||
);
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Add model POST.
|
||||
*
|
||||
* Side effects: Adds to prv_models; may bump config-version; redirects.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle_model_add(): void {
|
||||
( $this->nonce_cb )( PRV_Settings_Page::NONCE_MODEL );
|
||||
// phpcs:disable WordPress.Security.NonceVerification.Missing -- nonce verified above via require_admin_nonce().
|
||||
$slug = sanitize_text_field( wp_unslash( (string) ( $_POST['prv_model_slug'] ?? '' ) ) );
|
||||
$provider = sanitize_text_field( wp_unslash( (string) ( $_POST['prv_model_provider'] ?? 'openrouter' ) ) );
|
||||
$note = sanitize_text_field( wp_unslash( (string) ( $_POST['prv_model_note'] ?? '' ) ) );
|
||||
$enabled = ! empty( $_POST['prv_model_enabled'] );
|
||||
// phpcs:enable WordPress.Security.NonceVerification.Missing
|
||||
if ( '' !== $slug ) {
|
||||
PRV_Model_Registry::add( $slug, $provider, $enabled, $note );
|
||||
PRV_Config_Version::bump_version_if_changed();
|
||||
}
|
||||
wp_safe_redirect(
|
||||
add_query_arg(
|
||||
array(
|
||||
'page' => self::MENU_SLUG,
|
||||
'prv_model_added' => 1,
|
||||
),
|
||||
admin_url( 'admin.php' )
|
||||
)
|
||||
);
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Update model POST.
|
||||
*
|
||||
* Side effects: Updates prv_models; may bump config-version; redirects.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle_model_update(): void {
|
||||
( $this->nonce_cb )( PRV_Settings_Page::NONCE_MODEL );
|
||||
// phpcs:disable WordPress.Security.NonceVerification.Missing -- nonce verified above via require_admin_nonce().
|
||||
$id = sanitize_text_field( wp_unslash( (string) ( $_POST['prv_model_id'] ?? '' ) ) );
|
||||
$slug = sanitize_text_field( wp_unslash( (string) ( $_POST['prv_model_slug'] ?? '' ) ) );
|
||||
$enabled = ! empty( $_POST['prv_model_enabled'] );
|
||||
$note = sanitize_text_field( wp_unslash( (string) ( $_POST['prv_model_note'] ?? '' ) ) );
|
||||
// phpcs:enable WordPress.Security.NonceVerification.Missing
|
||||
if ( '' !== $id && '' !== $slug ) {
|
||||
PRV_Model_Registry::update(
|
||||
$id,
|
||||
array(
|
||||
'slug' => $slug,
|
||||
'enabled' => $enabled,
|
||||
'note' => $note,
|
||||
)
|
||||
);
|
||||
PRV_Config_Version::bump_version_if_changed();
|
||||
}
|
||||
wp_safe_redirect(
|
||||
add_query_arg(
|
||||
array(
|
||||
'page' => self::MENU_SLUG,
|
||||
'prv_model_updated' => 1,
|
||||
),
|
||||
admin_url( 'admin.php' )
|
||||
)
|
||||
);
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Remove model POST.
|
||||
*
|
||||
* Side effects: Removes from prv_models; may bump config-version; redirects.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle_model_remove(): void {
|
||||
( $this->nonce_cb )( PRV_Settings_Page::NONCE_MODEL );
|
||||
// phpcs:disable WordPress.Security.NonceVerification.Missing -- nonce verified above via require_admin_nonce().
|
||||
$id = sanitize_text_field( wp_unslash( (string) ( $_POST['prv_model_id'] ?? '' ) ) );
|
||||
// phpcs:enable WordPress.Security.NonceVerification.Missing
|
||||
if ( '' !== $id ) {
|
||||
PRV_Model_Registry::remove( $id );
|
||||
PRV_Config_Version::bump_version_if_changed();
|
||||
}
|
||||
wp_safe_redirect(
|
||||
add_query_arg(
|
||||
array(
|
||||
'page' => self::MENU_SLUG,
|
||||
'prv_model_removed' => 1,
|
||||
),
|
||||
admin_url( 'admin.php' )
|
||||
)
|
||||
);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
@@ -10,21 +10,22 @@ declare(strict_types=1);
|
||||
/**
|
||||
* PR Vision Settings admin page.
|
||||
*
|
||||
* Registers "PR Vision > Settings" sub-menu, handles POST actions (save config,
|
||||
* model CRUD, Run now) and the test-model AJAX hook. Rendering is delegated
|
||||
* to PRV_Settings_Renderer; test AJAX to PRV_Model_Test_Ajax.
|
||||
* Registers "PR Vision > Settings" sub-menu, dispatches POST actions to
|
||||
* PRV_Settings_Controller, handles Run-now and AJAX test-model, and
|
||||
* delegates all HTML rendering to PRV_Settings_Renderer.
|
||||
*
|
||||
* All actions require: current_user_can('manage_options') + valid nonce.
|
||||
*
|
||||
* Who triggers: PRV_Plugin::init() -- is_admin() guard.
|
||||
* Dependencies: PRV_Model_Registry, PRV_Config, PRV_Cron, PRV_Run_Lock,
|
||||
* PRV_Config_Version, PRV_Settings_Renderer, PRV_Model_Test_Ajax.
|
||||
* Dependencies: PRV_Settings_Controller, PRV_Settings_Renderer,
|
||||
* PRV_Model_Test_Ajax, PRV_Probe_Runner, PRV_Run_Lock.
|
||||
*
|
||||
* @see class-prv-settings-renderer.php -- Renders the HTML.
|
||||
* @see class-prv-model-test-ajax.php -- AJAX test handler.
|
||||
* @see class-prv-model-registry.php -- CRUD for prv_models.
|
||||
* @see class-prv-config-version.php -- Config-change versioning.
|
||||
* @see class-prv-cron.php -- Reschedule on cadence change.
|
||||
* @see class-prv-settings-controller.php -- POST handler implementations.
|
||||
* @see class-prv-settings-renderer.php -- Renders the HTML.
|
||||
* @see class-prv-model-test-ajax.php -- AJAX test handler.
|
||||
* @see class-prv-model-registry.php -- CRUD for prv_models.
|
||||
* @see class-prv-config-version.php -- Config-change versioning.
|
||||
* @see class-prv-cron.php -- Reschedule on cadence change.
|
||||
* @package PrVision
|
||||
*/
|
||||
class PRV_Settings_Page {
|
||||
@@ -47,16 +48,25 @@ class PRV_Settings_Page {
|
||||
/**
|
||||
* Register WordPress admin hooks.
|
||||
*
|
||||
* POST handlers for save/model-CRUD are delegated to PRV_Settings_Controller,
|
||||
* which receives a nonce-verification callback bound to this page.
|
||||
*
|
||||
* Side effects: Adds admin_menu, admin_post, and wp_ajax actions.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register_hooks(): void {
|
||||
$ctrl = new PRV_Settings_Controller(
|
||||
function ( string $action ): void {
|
||||
$this->require_admin_nonce( $action );
|
||||
}
|
||||
);
|
||||
|
||||
add_action( 'admin_menu', array( $this, 'add_settings_menu' ) );
|
||||
add_action( 'admin_post_prv_settings_save', array( $this, 'handle_save' ) );
|
||||
add_action( 'admin_post_prv_model_add', array( $this, 'handle_model_add' ) );
|
||||
add_action( 'admin_post_prv_model_update', array( $this, 'handle_model_update' ) );
|
||||
add_action( 'admin_post_prv_model_remove', array( $this, 'handle_model_remove' ) );
|
||||
add_action( 'admin_post_prv_settings_save', array( $ctrl, 'handle_save' ) );
|
||||
add_action( 'admin_post_prv_model_add', array( $ctrl, 'handle_model_add' ) );
|
||||
add_action( 'admin_post_prv_model_update', array( $ctrl, 'handle_model_update' ) );
|
||||
add_action( 'admin_post_prv_model_remove', array( $ctrl, 'handle_model_remove' ) );
|
||||
add_action( 'admin_post_prv_settings_run_now', array( $this, 'handle_run_now' ) );
|
||||
add_action( 'wp_ajax_prv_test_model', array( $this, 'handle_test_model' ) );
|
||||
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) );
|
||||
@@ -100,172 +110,6 @@ class PRV_Settings_Page {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the settings save POST action.
|
||||
*
|
||||
* Validates, sanitizes, saves peptides/intents/cadence/budget. Bumps
|
||||
* config-version if scoring-relevant fields changed. Reschedules cron
|
||||
* if cadence changed.
|
||||
*
|
||||
* Side effects: Updates wp_options, may reschedule cron, redirects.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle_save(): void {
|
||||
$this->require_admin_nonce( self::NONCE_SAVE );
|
||||
$old_cadence = PRV_Config::get_cadence();
|
||||
|
||||
// phpcs:disable WordPress.Security.NonceVerification.Missing -- nonce verified above via require_admin_nonce().
|
||||
$budget = isset( $_POST['prv_monthly_budget_usd'] )
|
||||
? max( 0.01, (float) sanitize_text_field( wp_unslash( (string) $_POST['prv_monthly_budget_usd'] ) ) )
|
||||
: PRV_DEFAULT_MONTHLY_BUDGET_USD;
|
||||
update_option( 'prv_monthly_budget_usd', $budget );
|
||||
|
||||
$cadence_raw = isset( $_POST['prv_cadence'] )
|
||||
? sanitize_text_field( wp_unslash( (string) $_POST['prv_cadence'] ) )
|
||||
: 'weekly';
|
||||
$cadence = in_array( $cadence_raw, array( 'weekly', 'daily', 'twicedaily' ), true ) ? $cadence_raw : 'weekly';
|
||||
update_option( PRV_Config::CADENCE_KEY, $cadence );
|
||||
|
||||
if ( ! empty( $_POST['prv_peptides_json'] ) ) {
|
||||
$raw_json = sanitize_textarea_field( wp_unslash( (string) $_POST['prv_peptides_json'] ) );
|
||||
$decoded = json_decode( $raw_json, true );
|
||||
if ( is_array( $decoded ) ) {
|
||||
$clean = array();
|
||||
foreach ( $decoded as $p ) {
|
||||
if ( isset( $p['slug'], $p['label'] ) ) {
|
||||
$clean[] = array(
|
||||
'slug' => sanitize_text_field( (string) $p['slug'] ),
|
||||
'label' => sanitize_text_field( (string) $p['label'] ),
|
||||
);
|
||||
}
|
||||
}
|
||||
update_option( 'prv_peptides', $clean );
|
||||
}
|
||||
}
|
||||
|
||||
if ( isset( $_POST['prv_prompt_intents_text'] ) ) {
|
||||
$raw_intents = sanitize_textarea_field( wp_unslash( (string) $_POST['prv_prompt_intents_text'] ) );
|
||||
$intent_lines = array_filter( array_map( 'trim', explode( "\n", $raw_intents ) ) );
|
||||
update_option( 'prv_prompt_intents', array_values( $intent_lines ) );
|
||||
}
|
||||
// phpcs:enable WordPress.Security.NonceVerification.Missing
|
||||
|
||||
PRV_Config_Version::bump_version_if_changed();
|
||||
|
||||
if ( $cadence !== $old_cadence ) {
|
||||
PRV_Cron::reschedule( $cadence );
|
||||
}
|
||||
|
||||
wp_safe_redirect(
|
||||
add_query_arg(
|
||||
array(
|
||||
'page' => self::MENU_SLUG,
|
||||
'prv_saved' => 1,
|
||||
),
|
||||
admin_url( 'admin.php' )
|
||||
)
|
||||
);
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Add model POST.
|
||||
*
|
||||
* Side effects: Adds to prv_models; may bump config-version; redirects.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle_model_add(): void {
|
||||
$this->require_admin_nonce( self::NONCE_MODEL );
|
||||
// phpcs:disable WordPress.Security.NonceVerification.Missing -- nonce verified above via require_admin_nonce().
|
||||
$slug = sanitize_text_field( wp_unslash( (string) ( $_POST['prv_model_slug'] ?? '' ) ) );
|
||||
$provider = sanitize_text_field( wp_unslash( (string) ( $_POST['prv_model_provider'] ?? 'openrouter' ) ) );
|
||||
$note = sanitize_text_field( wp_unslash( (string) ( $_POST['prv_model_note'] ?? '' ) ) );
|
||||
$enabled = ! empty( $_POST['prv_model_enabled'] );
|
||||
// phpcs:enable WordPress.Security.NonceVerification.Missing
|
||||
if ( '' !== $slug ) {
|
||||
PRV_Model_Registry::add( $slug, $provider, $enabled, $note );
|
||||
PRV_Config_Version::bump_version_if_changed();
|
||||
}
|
||||
wp_safe_redirect(
|
||||
add_query_arg(
|
||||
array(
|
||||
'page' => self::MENU_SLUG,
|
||||
'prv_model_added' => 1,
|
||||
),
|
||||
admin_url( 'admin.php' )
|
||||
)
|
||||
);
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Update model POST.
|
||||
*
|
||||
* Side effects: Updates prv_models; may bump config-version; redirects.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle_model_update(): void {
|
||||
$this->require_admin_nonce( self::NONCE_MODEL );
|
||||
// phpcs:disable WordPress.Security.NonceVerification.Missing -- nonce verified above via require_admin_nonce().
|
||||
$id = sanitize_text_field( wp_unslash( (string) ( $_POST['prv_model_id'] ?? '' ) ) );
|
||||
$slug = sanitize_text_field( wp_unslash( (string) ( $_POST['prv_model_slug'] ?? '' ) ) );
|
||||
$enabled = ! empty( $_POST['prv_model_enabled'] );
|
||||
$note = sanitize_text_field( wp_unslash( (string) ( $_POST['prv_model_note'] ?? '' ) ) );
|
||||
// phpcs:enable WordPress.Security.NonceVerification.Missing
|
||||
if ( '' !== $id && '' !== $slug ) {
|
||||
PRV_Model_Registry::update(
|
||||
$id,
|
||||
array(
|
||||
'slug' => $slug,
|
||||
'enabled' => $enabled,
|
||||
'note' => $note,
|
||||
)
|
||||
);
|
||||
PRV_Config_Version::bump_version_if_changed();
|
||||
}
|
||||
wp_safe_redirect(
|
||||
add_query_arg(
|
||||
array(
|
||||
'page' => self::MENU_SLUG,
|
||||
'prv_model_updated' => 1,
|
||||
),
|
||||
admin_url( 'admin.php' )
|
||||
)
|
||||
);
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Remove model POST.
|
||||
*
|
||||
* Side effects: Removes from prv_models; may bump config-version; redirects.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle_model_remove(): void {
|
||||
$this->require_admin_nonce( self::NONCE_MODEL );
|
||||
// phpcs:disable WordPress.Security.NonceVerification.Missing -- nonce verified above via require_admin_nonce().
|
||||
$id = sanitize_text_field( wp_unslash( (string) ( $_POST['prv_model_id'] ?? '' ) ) );
|
||||
// phpcs:enable WordPress.Security.NonceVerification.Missing
|
||||
if ( '' !== $id ) {
|
||||
PRV_Model_Registry::remove( $id );
|
||||
PRV_Config_Version::bump_version_if_changed();
|
||||
}
|
||||
wp_safe_redirect(
|
||||
add_query_arg(
|
||||
array(
|
||||
'page' => self::MENU_SLUG,
|
||||
'prv_model_removed' => 1,
|
||||
),
|
||||
admin_url( 'admin.php' )
|
||||
)
|
||||
);
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Run now POST from the settings page.
|
||||
*
|
||||
@@ -330,11 +174,14 @@ class PRV_Settings_Page {
|
||||
/**
|
||||
* Verify admin capability and nonce; wp_die on failure.
|
||||
*
|
||||
* Called directly for Run-now, and passed as a callback to
|
||||
* PRV_Settings_Controller for the four POST handlers.
|
||||
*
|
||||
* @param string $action Nonce action.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function require_admin_nonce( string $action ): void {
|
||||
public function require_admin_nonce( string $action ): void {
|
||||
if ( ! current_user_can( 'manage_options' ) ) {
|
||||
wp_die( esc_html__( 'Insufficient permissions.', 'pr-vision' ), 403 );
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user