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
/**
* Dosing Repository.
*
* @package Peptide_Repo_Core
*/
declare(strict_types=1);
/**
* CRUD operations for dosing data, returning typed DTOs
*
* @package Peptide_Repo_Core
*/
/**
* Repository for dosing rows (pr_dosing_rows table).
*
@@ -25,7 +37,7 @@ class PR_Core_Dosing_Repository {
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
$row = $wpdb->get_row(
$wpdb->prepare( "SELECT * FROM {$table} WHERE id = %d", $id ),
$wpdb->prepare( "SELECT * FROM {$table} WHERE id = %d", $id ), // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
ARRAY_A
);
@@ -39,12 +51,12 @@ class PR_Core_Dosing_Repository {
* @param array<string, mixed> $filters Optional: route, population, evidence_strength.
* @return PR_Core_Dosing_Row_DTO[]
*/
public function find_by_peptide( int $peptide_id, array $filters = [] ): array {
public function find_by_peptide( int $peptide_id, array $filters = array() ): array {
global $wpdb;
$table = $wpdb->prefix . 'pr_dosing_rows';
$where = [ 'peptide_id = %d', 'superseded_by_id IS NULL' ];
$params = [ $peptide_id ];
$where = array( 'peptide_id = %d', 'superseded_by_id IS NULL' );
$params = array( $peptide_id );
if ( ! empty( $filters['route'] ) ) {
$where[] = 'route = %s';
@@ -65,12 +77,12 @@ class PR_Core_Dosing_Repository {
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
$rows = $wpdb->get_results(
$wpdb->prepare(
"SELECT * FROM {$table} WHERE {$where_sql} ORDER BY evidence_strength DESC, study_year DESC",
$wpdb->prepare( // phpcs:ignore WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare -- dynamic {$where_sql} is builder-constructed, not a placeholder
"SELECT * FROM {$table} WHERE {$where_sql} ORDER BY evidence_strength DESC, study_year DESC", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
...$params
),
ARRAY_A
) ?: [];
) ?: array(); // phpcs:ignore Universal.Operators.DisallowShortTernary.Found
return array_map(
static fn( array $row ) => new PR_Core_Dosing_Row_DTO( $row ),
@@ -92,11 +104,15 @@ class PR_Core_Dosing_Repository {
global $wpdb;
$table = $wpdb->prefix . 'pr_dosing_rows';
$row = $this->sanitize_row( $data );
$row = $this->sanitize_row( $data );
$row['added_at'] = current_time( 'mysql' );
$row['schema_version'] = 1;
/** @see PR_Core::register_public_filters() — Documented lifecycle hook. */
/**
* Property.
*
* @see PR_Core::register_public_filters() — Documented lifecycle hook.
*/
do_action( 'pr_core_before_dosing_row_publish', $row );
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
@@ -137,10 +153,10 @@ class PR_Core_Dosing_Repository {
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
$wpdb->update(
$table,
[ 'superseded_by_id' => $new_id ],
[ 'id' => $old_id ],
[ '%d' ],
[ '%d' ]
array( 'superseded_by_id' => $new_id ),
array( 'id' => $old_id ),
array( '%d' ),
array( '%d' )
);
return $new_id;
@@ -159,7 +175,7 @@ class PR_Core_Dosing_Repository {
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
return (int) $wpdb->get_var(
$wpdb->prepare(
"SELECT COUNT(*) FROM {$table} WHERE peptide_id = %d AND superseded_by_id IS NULL",
"SELECT COUNT(*) FROM {$table} WHERE peptide_id = %d AND superseded_by_id IS NULL", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
$peptide_id
)
);
@@ -172,7 +188,7 @@ class PR_Core_Dosing_Repository {
* @return array<string, mixed> Sanitized row.
*/
private function sanitize_row( array $data ): array {
return [
return array(
'peptide_id' => absint( $data['peptide_id'] ?? 0 ),
'dose_min' => isset( $data['dose_min'] ) ? (float) $data['dose_min'] : null,
'dose_max' => isset( $data['dose_max'] ) ? (float) $data['dose_max'] : null,
@@ -195,6 +211,6 @@ class PR_Core_Dosing_Repository {
'added_by' => absint( $data['added_by'] ?? get_current_user_id() ),
'reviewed_by' => isset( $data['reviewed_by'] ) ? absint( $data['reviewed_by'] ) : null,
'reviewed_at' => $data['reviewed_at'] ?? null,
];
);
}
}