- All 49 PHP includes files: expand minimal file docblocks to include a short description (satisfies Generic.Commenting.DocComment.MissingShort) Format: <?php\n/**\n * Filename-derived description.\n *\n * @package ...\n */ - settings.php delegation stubs: add compact docblocks to all 8 render_* methods (Squiz.Commenting.FunctionComment.Missing, lines 93-231) - settings.php: compress mirrored @var constant docblocks to single-line; remove redundant intermediate class docblock → 273 lines (was 315) - rest-controller.php: compress 1 mirrored @var docblock → 298 lines - migration-0004: compress 4 property docblocks → 288 lines - verification-widget.php line 111: cast days_since to int + phpcs:ignore - verification-metabox.php line 80: phpcs:ignore on hardcoded badge_class - peptide-metaboxes.php line 86: phpcs:ignore EscapeOutput (esc_attr'd above) - peptide-metaboxes.php lines 147/148: Yoda null !== dose_min/dose_max - peptide-metaboxes.php line 248: phpcs:ignore InputNotSanitized (isset only) - peptide-metaboxes.php line 259: wrap pr_core_editorial_review_status in wp_unslash() - peptide-metaboxes.php line 262: Yoda 'published' !== old_status Agent-Session: claude-adopt-ci-20260616
129 lines
4.1 KiB
PHP
129 lines
4.1 KiB
PHP
<?php
|
|
/**
|
|
* Verification Widget.
|
|
*
|
|
* @package Peptide_Repo_Core
|
|
*/
|
|
|
|
declare(strict_types=1);
|
|
|
|
/**
|
|
* WordPress dashboard widget showing peptides needing review (due/overdue)
|
|
*
|
|
* @package Peptide_Repo_Core
|
|
*/
|
|
|
|
/**
|
|
* Dashboard widget for verification status overview.
|
|
*
|
|
* What: WordPress dashboard widget showing peptides needing review (due/overdue).
|
|
* Who calls it: PR_Core::init() hooks wp_dashboard_setup.
|
|
* Dependencies: PR_Core_Peptide_Repository.
|
|
*
|
|
* @see scanner/class-pr-core-verification-scanner.php — Computes status via run_scan().
|
|
*/
|
|
class PR_Core_Verification_Widget {
|
|
|
|
/**
|
|
* Register the dashboard widget.
|
|
*
|
|
* Side effects: Registers WP dashboard widget.
|
|
*
|
|
* @return void
|
|
*/
|
|
public static function register(): void {
|
|
wp_add_dashboard_widget(
|
|
'pr_core_verification_status',
|
|
__( 'Monographs Needing Review', 'peptide-repo-core' ),
|
|
array( __CLASS__, 'render' )
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Render the widget content.
|
|
*
|
|
* @return void
|
|
*/
|
|
public static function render(): void {
|
|
$repo = new PR_Core_Peptide_Repository();
|
|
$peptides = $repo->find_all( array( 'status' => 'publish' ) );
|
|
|
|
$due_overdue = array();
|
|
|
|
foreach ( $peptides as $dto ) {
|
|
$status = get_post_meta( $dto->id, '_pr_verification_status', true ) ?: 'current'; // phpcs:ignore Universal.Operators.DisallowShortTernary.Found
|
|
|
|
if ( in_array( $status, array( 'due', 'overdue' ), true ) ) {
|
|
$last_verified = get_post_meta( $dto->id, '_pr_last_source_verified', true );
|
|
$days_since = $last_verified
|
|
? (int) ( ( time() - strtotime( $last_verified ) ) / DAY_IN_SECONDS )
|
|
: 999;
|
|
|
|
$due_overdue[] = array(
|
|
'id' => $dto->id,
|
|
'title' => $dto->title,
|
|
'status' => $status,
|
|
'velocity' => get_post_meta( $dto->id, '_pr_verification_velocity', true ) ?: 'medium', // phpcs:ignore Universal.Operators.DisallowShortTernary.Found
|
|
'last_verified' => $last_verified,
|
|
'days_since' => $days_since,
|
|
);
|
|
}
|
|
}
|
|
|
|
// Sort by days_since descending (most overdue first).
|
|
usort(
|
|
$due_overdue,
|
|
static function ( $a, $b ) {
|
|
return $b['days_since'] <=> $a['days_since'];
|
|
}
|
|
);
|
|
|
|
if ( empty( $due_overdue ) ) {
|
|
echo '<p>' . esc_html__( 'All monographs are current. ', 'peptide-repo-core' );
|
|
echo esc_html__( 'Next scan: ', 'peptide-repo-core' );
|
|
$next = wp_next_scheduled( 'pr_core_verification_scan' );
|
|
if ( $next ) {
|
|
echo esc_html( wp_date( 'Y-m-d H:i:s', $next ) );
|
|
} else {
|
|
echo esc_html__( '(not scheduled)', 'peptide-repo-core' );
|
|
}
|
|
echo '</p>';
|
|
} else {
|
|
echo '<table class="widefat striped"><thead><tr>';
|
|
echo '<th>' . esc_html__( 'Title', 'peptide-repo-core' ) . '</th>';
|
|
echo '<th>' . esc_html__( 'Verdict', 'peptide-repo-core' ) . '</th>';
|
|
echo '<th>' . esc_html__( 'Velocity', 'peptide-repo-core' ) . '</th>';
|
|
echo '<th>' . esc_html__( 'Last Verified', 'peptide-repo-core' ) . '</th>';
|
|
echo '<th>' . esc_html__( 'Days Overdue', 'peptide-repo-core' ) . '</th>';
|
|
echo '<th></th>';
|
|
echo '</tr></thead><tbody>';
|
|
|
|
foreach ( $due_overdue as $item ) {
|
|
$edit_url = get_edit_post_link( $item['id'] );
|
|
printf(
|
|
'<tr><td><a href="%s">%s</a></td><td><span class="badge badge-%s">%s</span></td><td>%s</td><td>%s</td><td>%d</td><td><a href="%s" class="button button-small">Edit</a></td></tr>',
|
|
esc_url( get_permalink( $item['id'] ) ),
|
|
esc_html( $item['title'] ),
|
|
esc_attr( $item['status'] ),
|
|
esc_html( ucfirst( $item['status'] ) ),
|
|
esc_html( ucfirst( $item['velocity'] ) ),
|
|
esc_html( $item['last_verified'] ?? '—' ),
|
|
(int) $item['days_since'], // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- cast to int, safe
|
|
esc_url( $edit_url )
|
|
);
|
|
}
|
|
|
|
echo '</tbody></table>';
|
|
}
|
|
|
|
echo '<p>';
|
|
$nonce = wp_create_nonce( 'pr_core_scan_now' );
|
|
printf(
|
|
'<form method="post" style="display:inline;"><input type="hidden" name="action" value="pr_core_scan_now" /><input type="hidden" name="nonce" value="%s" /><button type="submit" class="button button-primary">%s</button></form>',
|
|
esc_attr( $nonce ),
|
|
esc_html__( 'Scan Now', 'peptide-repo-core' )
|
|
);
|
|
echo '</p>';
|
|
}
|
|
}
|