Adopt reusable CI standard + PHPUnit conversion (#22)

Squash-merge of PR #22: adopt shared reusable CI workflow, convert PHPUnit to stubs, update branch-protection contexts.

QA-approved at 05d8094a1d. All required CI checks green.

Agent-Session: 2026-06-17-prcore-ci-deploy
This commit is contained in:
peptiderepo
2026-06-17 01:12:00 +07:00
committed by GitHub
parent d0b5875fd8
commit 665d7fa9e1
72 changed files with 4604 additions and 1212 deletions

View File

@@ -1,6 +1,18 @@
<?php
/**
* Candidate Queue Page.
*
* @package Peptide_Repo_Core
*/
declare(strict_types=1);
/**
* Renders a review screen for AI-extracted dosing candidates
*
* @package Peptide_Repo_Core
*/
/**
* Admin page for the AI Candidate Queue.
*
@@ -58,8 +70,8 @@ class PR_Core_Candidate_Queue_Page {
$peptide = $pep_repo->find_by_id( $c->peptide_id );
$name = $peptide ? $peptide->title : '#' . $c->peptide_id;
$dose = $c->dose_min !== null ? number_format( $c->dose_min, 2 ) : '?';
if ( $c->dose_max !== null && $c->dose_max !== $c->dose_min ) {
$dose = null !== $c->dose_min ? number_format( $c->dose_min, 2 ) : '?';
if ( null !== $c->dose_max && $c->dose_max !== $c->dose_min ) {
$dose .= ' – ' . number_format( $c->dose_max, 2 );
}
$dose .= ' ' . esc_html( $c->dose_unit );
@@ -71,11 +83,21 @@ class PR_Core_Candidate_Queue_Page {
$confidence_pct = number_format( $c->extraction_confidence * 100, 0 ) . '%';
$approve_url = wp_nonce_url(
add_query_arg( [ 'action' => 'pr_core_approve', 'candidate_id' => $c->id ] ),
add_query_arg(
array(
'action' => 'pr_core_approve',
'candidate_id' => $c->id,
)
),
'pr_core_queue_action'
);
$reject_url = wp_nonce_url(
add_query_arg( [ 'action' => 'pr_core_reject', 'candidate_id' => $c->id ] ),
add_query_arg(
array(
'action' => 'pr_core_reject',
'candidate_id' => $c->id,
)
),
'pr_core_queue_action'
);
@@ -84,7 +106,7 @@ class PR_Core_Candidate_Queue_Page {
printf( '<td>%s</td>', esc_html( $c->route ) );
printf( '<td>%s</td>', esc_html( $dose ) );
printf( '<td>%s</td>', esc_html( $c->population ) );
printf( '<td>%s</td>', $study ); // Contains escaped HTML + link.
printf( '<td>%s</td>', $study ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- $study is pre-escaped HTML.
printf( '<td>%s</td>', esc_html( $confidence_pct ) );
printf(
'<td><a href="%s" class="button button-primary button-small">%s</a> <a href="%s" class="button button-small">%s</a></td>',
@@ -107,9 +129,9 @@ class PR_Core_Candidate_Queue_Page {
* @return void
*/
private function handle_actions(): void {
$action = sanitize_text_field( $_GET['action'] ?? '' );
$action = sanitize_text_field( wp_unslash( $_GET['action'] ?? '' ) ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated
if ( ! in_array( $action, [ 'pr_core_approve', 'pr_core_reject' ], true ) ) {
if ( ! in_array( $action, array( 'pr_core_approve', 'pr_core_reject' ), true ) ) {
return;
}
@@ -117,7 +139,7 @@ class PR_Core_Candidate_Queue_Page {
return;
}
$candidate_id = absint( $_GET['candidate_id'] ?? 0 );
$candidate_id = absint( wp_unslash( $_GET['candidate_id'] ?? 0 ) );
if ( 0 === $candidate_id ) {
return;
}
@@ -128,15 +150,21 @@ class PR_Core_Candidate_Queue_Page {
if ( 'pr_core_approve' === $action ) {
$dosing_id = $repo->approve( $candidate_id, $reviewer_id );
if ( $dosing_id > 0 ) {
add_action( 'admin_notices', static function () {
echo '<div class="notice notice-success is-dismissible"><p>' . esc_html__( 'Candidate approved and added to dosing data.', 'peptide-repo-core' ) . '</p></div>';
} );
add_action(
'admin_notices',
static function () {
echo '<div class="notice notice-success is-dismissible"><p>' . esc_html__( 'Candidate approved and added to dosing data.', 'peptide-repo-core' ) . '</p></div>';
}
);
}
} else {
$repo->reject( $candidate_id, $reviewer_id );
add_action( 'admin_notices', static function () {
echo '<div class="notice notice-warning is-dismissible"><p>' . esc_html__( 'Candidate rejected.', 'peptide-repo-core' ) . '</p></div>';
} );
add_action(
'admin_notices',
static function () {
echo '<div class="notice notice-warning is-dismissible"><p>' . esc_html__( 'Candidate rejected.', 'peptide-repo-core' ) . '</p></div>';
}
);
}
}
}