style: auto-fix PHPCS violations via phpcbf
This commit is contained in:
@@ -19,7 +19,7 @@ class PR_Core_Admin_Columns {
|
|||||||
* @return array<string, string> Modified columns.
|
* @return array<string, string> Modified columns.
|
||||||
*/
|
*/
|
||||||
public function add_columns( array $columns ): array {
|
public function add_columns( array $columns ): array {
|
||||||
$new = [];
|
$new = array();
|
||||||
foreach ( $columns as $key => $label ) {
|
foreach ( $columns as $key => $label ) {
|
||||||
$new[ $key ] = $label;
|
$new[ $key ] = $label;
|
||||||
|
|
||||||
|
|||||||
@@ -25,22 +25,22 @@ class PR_Core_Admin {
|
|||||||
*/
|
*/
|
||||||
public function register_hooks(): void {
|
public function register_hooks(): void {
|
||||||
$metaboxes = new PR_Core_Peptide_Metaboxes();
|
$metaboxes = new PR_Core_Peptide_Metaboxes();
|
||||||
add_action( 'add_meta_boxes', [ $metaboxes, 'add_meta_boxes' ] );
|
add_action( 'add_meta_boxes', array( $metaboxes, 'add_meta_boxes' ) );
|
||||||
add_action( 'save_post_' . PR_Core_Peptide_CPT::POST_TYPE, [ $metaboxes, 'save_meta' ], 10, 2 );
|
add_action( 'save_post_' . PR_Core_Peptide_CPT::POST_TYPE, array( $metaboxes, 'save_meta' ), 10, 2 );
|
||||||
|
|
||||||
add_action( 'add_meta_boxes', [ PR_Core_Verification_Metabox::class, 'register' ] );
|
add_action( 'add_meta_boxes', array( PR_Core_Verification_Metabox::class, 'register' ) );
|
||||||
|
|
||||||
$columns = new PR_Core_Admin_Columns();
|
$columns = new PR_Core_Admin_Columns();
|
||||||
add_filter( 'manage_' . PR_Core_Peptide_CPT::POST_TYPE . '_posts_columns', [ $columns, 'add_columns' ] );
|
add_filter( 'manage_' . PR_Core_Peptide_CPT::POST_TYPE . '_posts_columns', array( $columns, 'add_columns' ) );
|
||||||
add_action( 'manage_' . PR_Core_Peptide_CPT::POST_TYPE . '_posts_custom_column', [ $columns, 'render_column' ], 10, 2 );
|
add_action( 'manage_' . PR_Core_Peptide_CPT::POST_TYPE . '_posts_custom_column', array( $columns, 'render_column' ), 10, 2 );
|
||||||
|
|
||||||
// Repo Daily meta boxes.
|
// Repo Daily meta boxes.
|
||||||
$repo_daily_metaboxes = new PR_Core_Repo_Daily_Metaboxes();
|
$repo_daily_metaboxes = new PR_Core_Repo_Daily_Metaboxes();
|
||||||
add_action( 'add_meta_boxes', [ $repo_daily_metaboxes, 'add_meta_boxes' ] );
|
add_action( 'add_meta_boxes', array( $repo_daily_metaboxes, 'add_meta_boxes' ) );
|
||||||
add_action( 'save_post_' . PR_Core_Repo_Daily_CPT::POST_TYPE, [ $repo_daily_metaboxes, 'save_meta' ], 10, 2 );
|
add_action( 'save_post_' . PR_Core_Repo_Daily_CPT::POST_TYPE, array( $repo_daily_metaboxes, 'save_meta' ), 10, 2 );
|
||||||
|
|
||||||
add_action( 'admin_menu', [ $this, 'add_admin_pages' ] );
|
add_action( 'admin_menu', array( $this, 'add_admin_pages' ) );
|
||||||
add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_admin_styles' ] );
|
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_styles' ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -60,7 +60,7 @@ class PR_Core_Admin {
|
|||||||
__( 'Candidate Queue', 'peptide-repo-core' ) . $badge,
|
__( 'Candidate Queue', 'peptide-repo-core' ) . $badge,
|
||||||
PR_Core_Peptide_CPT::CAPABILITY,
|
PR_Core_Peptide_CPT::CAPABILITY,
|
||||||
'pr-core-candidates',
|
'pr-core-candidates',
|
||||||
[ new PR_Core_Candidate_Queue_Page(), 'render' ]
|
array( new PR_Core_Candidate_Queue_Page(), 'render' )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,7 +79,7 @@ class PR_Core_Admin {
|
|||||||
wp_enqueue_style(
|
wp_enqueue_style(
|
||||||
'pr-core-admin',
|
'pr-core-admin',
|
||||||
PR_CORE_PLUGIN_URL . 'assets/css/admin.css',
|
PR_CORE_PLUGIN_URL . 'assets/css/admin.css',
|
||||||
[],
|
array(),
|
||||||
PR_CORE_VERSION
|
PR_CORE_VERSION
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ class PR_Core_Ajax_Handlers {
|
|||||||
// Recompute status to 'current'.
|
// Recompute status to 'current'.
|
||||||
update_post_meta( $post_id, '_pr_verification_status', 'current' );
|
update_post_meta( $post_id, '_pr_verification_status', 'current' );
|
||||||
|
|
||||||
wp_send_json_success( [ 'message' => 'Marked verified' ] );
|
wp_send_json_success( array( 'message' => 'Marked verified' ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -74,6 +74,6 @@ class PR_Core_Ajax_Handlers {
|
|||||||
// Run scan.
|
// Run scan.
|
||||||
PR_Core_Verification_Scanner::run_scan();
|
PR_Core_Verification_Scanner::run_scan();
|
||||||
|
|
||||||
wp_send_json_success( [ 'message' => 'Scan complete' ] );
|
wp_send_json_success( array( 'message' => 'Scan complete' ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,11 +71,21 @@ class PR_Core_Candidate_Queue_Page {
|
|||||||
|
|
||||||
$confidence_pct = number_format( $c->extraction_confidence * 100, 0 ) . '%';
|
$confidence_pct = number_format( $c->extraction_confidence * 100, 0 ) . '%';
|
||||||
$approve_url = wp_nonce_url(
|
$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'
|
'pr_core_queue_action'
|
||||||
);
|
);
|
||||||
$reject_url = wp_nonce_url(
|
$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'
|
'pr_core_queue_action'
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -109,7 +119,7 @@ class PR_Core_Candidate_Queue_Page {
|
|||||||
private function handle_actions(): void {
|
private function handle_actions(): void {
|
||||||
$action = sanitize_text_field( $_GET['action'] ?? '' );
|
$action = sanitize_text_field( $_GET['action'] ?? '' );
|
||||||
|
|
||||||
if ( ! in_array( $action, [ 'pr_core_approve', 'pr_core_reject' ], true ) ) {
|
if ( ! in_array( $action, array( 'pr_core_approve', 'pr_core_reject' ), true ) ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,15 +138,21 @@ class PR_Core_Candidate_Queue_Page {
|
|||||||
if ( 'pr_core_approve' === $action ) {
|
if ( 'pr_core_approve' === $action ) {
|
||||||
$dosing_id = $repo->approve( $candidate_id, $reviewer_id );
|
$dosing_id = $repo->approve( $candidate_id, $reviewer_id );
|
||||||
if ( $dosing_id > 0 ) {
|
if ( $dosing_id > 0 ) {
|
||||||
add_action( 'admin_notices', static function () {
|
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>';
|
echo '<div class="notice notice-success is-dismissible"><p>' . esc_html__( 'Candidate approved and added to dosing data.', 'peptide-repo-core' ) . '</p></div>';
|
||||||
} );
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$repo->reject( $candidate_id, $reviewer_id );
|
$repo->reject( $candidate_id, $reviewer_id );
|
||||||
add_action( 'admin_notices', static function () {
|
add_action(
|
||||||
|
'admin_notices',
|
||||||
|
static function () {
|
||||||
echo '<div class="notice notice-warning is-dismissible"><p>' . esc_html__( 'Candidate rejected.', 'peptide-repo-core' ) . '</p></div>';
|
echo '<div class="notice notice-warning is-dismissible"><p>' . esc_html__( 'Candidate rejected.', 'peptide-repo-core' ) . '</p></div>';
|
||||||
} );
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ class PR_Core_Peptide_Metaboxes {
|
|||||||
add_meta_box(
|
add_meta_box(
|
||||||
'pr-core-identifiers',
|
'pr-core-identifiers',
|
||||||
__( 'Scientific Identifiers', 'peptide-repo-core' ),
|
__( 'Scientific Identifiers', 'peptide-repo-core' ),
|
||||||
[ $this, 'render_identifiers_box' ],
|
array( $this, 'render_identifiers_box' ),
|
||||||
PR_Core_Peptide_CPT::POST_TYPE,
|
PR_Core_Peptide_CPT::POST_TYPE,
|
||||||
'normal',
|
'normal',
|
||||||
'high'
|
'high'
|
||||||
@@ -31,7 +31,7 @@ class PR_Core_Peptide_Metaboxes {
|
|||||||
add_meta_box(
|
add_meta_box(
|
||||||
'pr-core-dosing',
|
'pr-core-dosing',
|
||||||
__( 'Dosing Data', 'peptide-repo-core' ),
|
__( 'Dosing Data', 'peptide-repo-core' ),
|
||||||
[ $this, 'render_dosing_box' ],
|
array( $this, 'render_dosing_box' ),
|
||||||
PR_Core_Peptide_CPT::POST_TYPE,
|
PR_Core_Peptide_CPT::POST_TYPE,
|
||||||
'normal',
|
'normal',
|
||||||
'default'
|
'default'
|
||||||
@@ -40,7 +40,7 @@ class PR_Core_Peptide_Metaboxes {
|
|||||||
add_meta_box(
|
add_meta_box(
|
||||||
'pr-core-legal',
|
'pr-core-legal',
|
||||||
__( 'Legal Status by Country', 'peptide-repo-core' ),
|
__( 'Legal Status by Country', 'peptide-repo-core' ),
|
||||||
[ $this, 'render_legal_box' ],
|
array( $this, 'render_legal_box' ),
|
||||||
PR_Core_Peptide_CPT::POST_TYPE,
|
PR_Core_Peptide_CPT::POST_TYPE,
|
||||||
'normal',
|
'normal',
|
||||||
'default'
|
'default'
|
||||||
@@ -56,7 +56,7 @@ class PR_Core_Peptide_Metaboxes {
|
|||||||
public function render_identifiers_box( \WP_Post $post ): void {
|
public function render_identifiers_box( \WP_Post $post ): void {
|
||||||
wp_nonce_field( 'pr_core_save_meta', 'pr_core_meta_nonce' );
|
wp_nonce_field( 'pr_core_save_meta', 'pr_core_meta_nonce' );
|
||||||
|
|
||||||
$fields = [
|
$fields = array(
|
||||||
'display_name' => __( 'Display Name', 'peptide-repo-core' ),
|
'display_name' => __( 'Display Name', 'peptide-repo-core' ),
|
||||||
'aliases' => __( 'Aliases (JSON array)', 'peptide-repo-core' ),
|
'aliases' => __( 'Aliases (JSON array)', 'peptide-repo-core' ),
|
||||||
'molecular_formula' => __( 'Molecular Formula', 'peptide-repo-core' ),
|
'molecular_formula' => __( 'Molecular Formula', 'peptide-repo-core' ),
|
||||||
@@ -64,7 +64,7 @@ class PR_Core_Peptide_Metaboxes {
|
|||||||
'cas_number' => __( 'CAS Number', 'peptide-repo-core' ),
|
'cas_number' => __( 'CAS Number', 'peptide-repo-core' ),
|
||||||
'drugbank_id' => __( 'DrugBank ID', 'peptide-repo-core' ),
|
'drugbank_id' => __( 'DrugBank ID', 'peptide-repo-core' ),
|
||||||
'chembl_id' => __( 'ChEMBL ID', 'peptide-repo-core' ),
|
'chembl_id' => __( 'ChEMBL ID', 'peptide-repo-core' ),
|
||||||
];
|
);
|
||||||
|
|
||||||
echo '<table class="form-table pr-core-meta-table">';
|
echo '<table class="form-table pr-core-meta-table">';
|
||||||
foreach ( $fields as $key => $label ) {
|
foreach ( $fields as $key => $label ) {
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ class PR_Core_Repo_Daily_Metaboxes {
|
|||||||
add_meta_box(
|
add_meta_box(
|
||||||
'pr-core-repo-daily-meta',
|
'pr-core-repo-daily-meta',
|
||||||
__( 'Article Settings', 'peptide-repo-core' ),
|
__( 'Article Settings', 'peptide-repo-core' ),
|
||||||
[ $this, 'render_meta_box' ],
|
array( $this, 'render_meta_box' ),
|
||||||
PR_Core_Repo_Daily_CPT::POST_TYPE,
|
PR_Core_Repo_Daily_CPT::POST_TYPE,
|
||||||
'normal',
|
'normal',
|
||||||
'default'
|
'default'
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ class PR_Core_Settings {
|
|||||||
__( 'Settings', 'peptide-repo-core' ),
|
__( 'Settings', 'peptide-repo-core' ),
|
||||||
'manage_options',
|
'manage_options',
|
||||||
'pr-core-settings',
|
'pr-core-settings',
|
||||||
[ __CLASS__, 'render_page' ]
|
array( __CLASS__, 'render_page' )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,7 +83,7 @@ class PR_Core_Settings {
|
|||||||
public static function register_settings(): void {
|
public static function register_settings(): void {
|
||||||
self::register_related_articles_section();
|
self::register_related_articles_section();
|
||||||
self::register_verification_section();
|
self::register_verification_section();
|
||||||
add_action( 'update_option_' . self::SCAN_CADENCE, [ __CLASS__, 'reschedule_cron' ], 10, 2 );
|
add_action( 'update_option_' . self::SCAN_CADENCE, array( __CLASS__, 'reschedule_cron' ), 10, 2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Related Articles ─────────────────────────────────────────────────
|
// ── Related Articles ─────────────────────────────────────────────────
|
||||||
@@ -94,12 +94,28 @@ class PR_Core_Settings {
|
|||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
private static function register_related_articles_section(): void {
|
private static function register_related_articles_section(): void {
|
||||||
register_setting( self::OPTION_GROUP, self::RELATED_ENABLED, [ 'type' => 'boolean', 'default' => true, 'sanitize_callback' => 'rest_sanitize_boolean' ] );
|
register_setting(
|
||||||
register_setting( self::OPTION_GROUP, self::RELATED_LIMIT, [ 'type' => 'integer', 'default' => 3, 'sanitize_callback' => [ __CLASS__, 'sanitize_limit' ] ] );
|
self::OPTION_GROUP,
|
||||||
|
self::RELATED_ENABLED,
|
||||||
|
array(
|
||||||
|
'type' => 'boolean',
|
||||||
|
'default' => true,
|
||||||
|
'sanitize_callback' => 'rest_sanitize_boolean',
|
||||||
|
)
|
||||||
|
);
|
||||||
|
register_setting(
|
||||||
|
self::OPTION_GROUP,
|
||||||
|
self::RELATED_LIMIT,
|
||||||
|
array(
|
||||||
|
'type' => 'integer',
|
||||||
|
'default' => 3,
|
||||||
|
'sanitize_callback' => array( __CLASS__, 'sanitize_limit' ),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
add_settings_section( 'pr_core_related_articles', __( 'Related Articles', 'peptide-repo-core' ), '__return_false', self::OPTION_GROUP );
|
add_settings_section( 'pr_core_related_articles', __( 'Related Articles', 'peptide-repo-core' ), '__return_false', self::OPTION_GROUP );
|
||||||
add_settings_field( self::RELATED_ENABLED, __( 'Enable Related Articles', 'peptide-repo-core' ), [ __CLASS__, 'render_enabled_field' ], self::OPTION_GROUP, 'pr_core_related_articles' );
|
add_settings_field( self::RELATED_ENABLED, __( 'Enable Related Articles', 'peptide-repo-core' ), array( __CLASS__, 'render_enabled_field' ), self::OPTION_GROUP, 'pr_core_related_articles' );
|
||||||
add_settings_field( self::RELATED_LIMIT, __( 'Number of Articles', 'peptide-repo-core' ), [ __CLASS__, 'render_limit_field' ], self::OPTION_GROUP, 'pr_core_related_articles' );
|
add_settings_field( self::RELATED_LIMIT, __( 'Number of Articles', 'peptide-repo-core' ), array( __CLASS__, 'render_limit_field' ), self::OPTION_GROUP, 'pr_core_related_articles' );
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return void */
|
/** @return void */
|
||||||
@@ -141,16 +157,48 @@ class PR_Core_Settings {
|
|||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
private static function register_verification_section(): void {
|
private static function register_verification_section(): void {
|
||||||
register_setting( self::OPTION_GROUP, self::SCAN_CADENCE, [ 'type' => 'string', 'default' => 'weekly', 'sanitize_callback' => [ __CLASS__, 'sanitize_cadence' ] ] );
|
register_setting(
|
||||||
register_setting( self::OPTION_GROUP, self::DEFAULT_THRESHOLD, [ 'type' => 'integer', 'default' => 180, 'sanitize_callback' => 'absint' ] );
|
self::OPTION_GROUP,
|
||||||
register_setting( self::OPTION_GROUP, self::HIGH_VELOCITY_THRESHOLD, [ 'type' => 'integer', 'default' => 60, 'sanitize_callback' => 'absint' ] );
|
self::SCAN_CADENCE,
|
||||||
register_setting( self::OPTION_GROUP, self::VERIFICATION_EMAIL, [ 'type' => 'string', 'default' => '', 'sanitize_callback' => [ __CLASS__, 'sanitize_emails' ] ] );
|
array(
|
||||||
|
'type' => 'string',
|
||||||
|
'default' => 'weekly',
|
||||||
|
'sanitize_callback' => array( __CLASS__, 'sanitize_cadence' ),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
register_setting(
|
||||||
|
self::OPTION_GROUP,
|
||||||
|
self::DEFAULT_THRESHOLD,
|
||||||
|
array(
|
||||||
|
'type' => 'integer',
|
||||||
|
'default' => 180,
|
||||||
|
'sanitize_callback' => 'absint',
|
||||||
|
)
|
||||||
|
);
|
||||||
|
register_setting(
|
||||||
|
self::OPTION_GROUP,
|
||||||
|
self::HIGH_VELOCITY_THRESHOLD,
|
||||||
|
array(
|
||||||
|
'type' => 'integer',
|
||||||
|
'default' => 60,
|
||||||
|
'sanitize_callback' => 'absint',
|
||||||
|
)
|
||||||
|
);
|
||||||
|
register_setting(
|
||||||
|
self::OPTION_GROUP,
|
||||||
|
self::VERIFICATION_EMAIL,
|
||||||
|
array(
|
||||||
|
'type' => 'string',
|
||||||
|
'default' => '',
|
||||||
|
'sanitize_callback' => array( __CLASS__, 'sanitize_emails' ),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
add_settings_section( 'pr_core_verification', __( 'Verification', 'peptide-repo-core' ), [ __CLASS__, 'render_verification_section' ], self::OPTION_GROUP );
|
add_settings_section( 'pr_core_verification', __( 'Verification', 'peptide-repo-core' ), array( __CLASS__, 'render_verification_section' ), self::OPTION_GROUP );
|
||||||
add_settings_field( self::SCAN_CADENCE, __( 'Scan cadence', 'peptide-repo-core' ), [ __CLASS__, 'render_cadence_field' ], self::OPTION_GROUP, 'pr_core_verification' );
|
add_settings_field( self::SCAN_CADENCE, __( 'Scan cadence', 'peptide-repo-core' ), array( __CLASS__, 'render_cadence_field' ), self::OPTION_GROUP, 'pr_core_verification' );
|
||||||
add_settings_field( self::DEFAULT_THRESHOLD, __( 'Default staleness threshold (days)', 'peptide-repo-core' ), [ __CLASS__, 'render_threshold_field' ], self::OPTION_GROUP, 'pr_core_verification' );
|
add_settings_field( self::DEFAULT_THRESHOLD, __( 'Default staleness threshold (days)', 'peptide-repo-core' ), array( __CLASS__, 'render_threshold_field' ), self::OPTION_GROUP, 'pr_core_verification' );
|
||||||
add_settings_field( self::HIGH_VELOCITY_THRESHOLD, __( 'High-velocity threshold (days)', 'peptide-repo-core' ), [ __CLASS__, 'render_high_velocity_field' ], self::OPTION_GROUP, 'pr_core_verification' );
|
add_settings_field( self::HIGH_VELOCITY_THRESHOLD, __( 'High-velocity threshold (days)', 'peptide-repo-core' ), array( __CLASS__, 'render_high_velocity_field' ), self::OPTION_GROUP, 'pr_core_verification' );
|
||||||
add_settings_field( self::VERIFICATION_EMAIL, __( 'Notification email(s)', 'peptide-repo-core' ), [ __CLASS__, 'render_email_field' ], self::OPTION_GROUP, 'pr_core_verification' );
|
add_settings_field( self::VERIFICATION_EMAIL, __( 'Notification email(s)', 'peptide-repo-core' ), array( __CLASS__, 'render_email_field' ), self::OPTION_GROUP, 'pr_core_verification' );
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return void */
|
/** @return void */
|
||||||
@@ -162,7 +210,11 @@ class PR_Core_Settings {
|
|||||||
public static function render_cadence_field(): void {
|
public static function render_cadence_field(): void {
|
||||||
$current = get_option( self::SCAN_CADENCE, 'weekly' );
|
$current = get_option( self::SCAN_CADENCE, 'weekly' );
|
||||||
echo '<select name="' . esc_attr( self::SCAN_CADENCE ) . '">';
|
echo '<select name="' . esc_attr( self::SCAN_CADENCE ) . '">';
|
||||||
foreach ( [ 'daily' => 'Daily', 'weekly' => 'Weekly', 'monthly' => 'Monthly' ] as $val => $label ) {
|
foreach ( array(
|
||||||
|
'daily' => 'Daily',
|
||||||
|
'weekly' => 'Weekly',
|
||||||
|
'monthly' => 'Monthly',
|
||||||
|
) as $val => $label ) {
|
||||||
printf( '<option value="%s"%s>%s</option>', esc_attr( $val ), selected( $current, $val, false ), esc_html( $label ) );
|
printf( '<option value="%s"%s>%s</option>', esc_attr( $val ), selected( $current, $val, false ), esc_html( $label ) );
|
||||||
}
|
}
|
||||||
echo '</select>';
|
echo '</select>';
|
||||||
@@ -195,7 +247,7 @@ class PR_Core_Settings {
|
|||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public static function sanitize_cadence( string $value ): string {
|
public static function sanitize_cadence( string $value ): string {
|
||||||
return in_array( $value, [ 'daily', 'weekly', 'monthly' ], true ) ? $value : 'weekly';
|
return in_array( $value, array( 'daily', 'weekly', 'monthly' ), true ) ? $value : 'weekly';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ class PR_Core_Verification_Metabox {
|
|||||||
add_meta_box(
|
add_meta_box(
|
||||||
'pr-core-verification',
|
'pr-core-verification',
|
||||||
__( 'Verification Status', 'peptide-repo-core' ),
|
__( 'Verification Status', 'peptide-repo-core' ),
|
||||||
[ __CLASS__, 'render' ],
|
array( __CLASS__, 'render' ),
|
||||||
PR_Core_Peptide_CPT::POST_TYPE,
|
PR_Core_Peptide_CPT::POST_TYPE,
|
||||||
'side',
|
'side',
|
||||||
'default'
|
'default'
|
||||||
@@ -47,7 +47,11 @@ class PR_Core_Verification_Metabox {
|
|||||||
|
|
||||||
echo '<p><strong>' . esc_html__( 'Verification Velocity', 'peptide-repo-core' ) . ':</strong><br />';
|
echo '<p><strong>' . esc_html__( 'Verification Velocity', 'peptide-repo-core' ) . ':</strong><br />';
|
||||||
echo '<select name="pr_core__pr_verification_velocity" style="width:100%;">';
|
echo '<select name="pr_core__pr_verification_velocity" style="width:100%;">';
|
||||||
foreach ( [ 'low' => 'Low', 'medium' => 'Medium', 'high' => 'High' ] as $val => $label ) {
|
foreach ( array(
|
||||||
|
'low' => 'Low',
|
||||||
|
'medium' => 'Medium',
|
||||||
|
'high' => 'High',
|
||||||
|
) as $val => $label ) {
|
||||||
printf(
|
printf(
|
||||||
'<option value="%s"%s>%s</option>',
|
'<option value="%s"%s>%s</option>',
|
||||||
esc_attr( $val ),
|
esc_attr( $val ),
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ class PR_Core_Verification_Widget {
|
|||||||
wp_add_dashboard_widget(
|
wp_add_dashboard_widget(
|
||||||
'pr_core_verification_status',
|
'pr_core_verification_status',
|
||||||
__( 'Monographs Needing Review', 'peptide-repo-core' ),
|
__( 'Monographs Needing Review', 'peptide-repo-core' ),
|
||||||
[ __CLASS__, 'render' ]
|
array( __CLASS__, 'render' )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,34 +34,37 @@ class PR_Core_Verification_Widget {
|
|||||||
*/
|
*/
|
||||||
public static function render(): void {
|
public static function render(): void {
|
||||||
$repo = new PR_Core_Peptide_Repository();
|
$repo = new PR_Core_Peptide_Repository();
|
||||||
$peptides = $repo->find_all( [ 'status' => 'publish' ] );
|
$peptides = $repo->find_all( array( 'status' => 'publish' ) );
|
||||||
|
|
||||||
$due_overdue = [];
|
$due_overdue = array();
|
||||||
|
|
||||||
foreach ( $peptides as $dto ) {
|
foreach ( $peptides as $dto ) {
|
||||||
$status = get_post_meta( $dto->id, '_pr_verification_status', true ) ?: 'current';
|
$status = get_post_meta( $dto->id, '_pr_verification_status', true ) ?: 'current';
|
||||||
|
|
||||||
if ( in_array( $status, [ 'due', 'overdue' ], true ) ) {
|
if ( in_array( $status, array( 'due', 'overdue' ), true ) ) {
|
||||||
$last_verified = get_post_meta( $dto->id, '_pr_last_source_verified', true );
|
$last_verified = get_post_meta( $dto->id, '_pr_last_source_verified', true );
|
||||||
$days_since = $last_verified
|
$days_since = $last_verified
|
||||||
? (int) ( ( time() - strtotime( $last_verified ) ) / DAY_IN_SECONDS )
|
? (int) ( ( time() - strtotime( $last_verified ) ) / DAY_IN_SECONDS )
|
||||||
: 999;
|
: 999;
|
||||||
|
|
||||||
$due_overdue[] = [
|
$due_overdue[] = array(
|
||||||
'id' => $dto->id,
|
'id' => $dto->id,
|
||||||
'title' => $dto->title,
|
'title' => $dto->title,
|
||||||
'status' => $status,
|
'status' => $status,
|
||||||
'velocity' => get_post_meta( $dto->id, '_pr_verification_velocity', true ) ?: 'medium',
|
'velocity' => get_post_meta( $dto->id, '_pr_verification_velocity', true ) ?: 'medium',
|
||||||
'last_verified' => $last_verified,
|
'last_verified' => $last_verified,
|
||||||
'days_since' => $days_since,
|
'days_since' => $days_since,
|
||||||
];
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort by days_since descending (most overdue first).
|
// Sort by days_since descending (most overdue first).
|
||||||
usort( $due_overdue, static function ( $a, $b ) {
|
usort(
|
||||||
|
$due_overdue,
|
||||||
|
static function ( $a, $b ) {
|
||||||
return $b['days_since'] <=> $a['days_since'];
|
return $b['days_since'] <=> $a['days_since'];
|
||||||
} );
|
}
|
||||||
|
);
|
||||||
|
|
||||||
if ( empty( $due_overdue ) ) {
|
if ( empty( $due_overdue ) ) {
|
||||||
echo '<p>' . esc_html__( 'All monographs are current. ', 'peptide-repo-core' );
|
echo '<p>' . esc_html__( 'All monographs are current. ', 'peptide-repo-core' );
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ class PR_Core_Rest_Controller {
|
|||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function register_hooks(): void {
|
public function register_hooks(): void {
|
||||||
add_action( 'rest_api_init', [ $this, 'register_routes' ] );
|
add_action( 'rest_api_init', array( $this, 'register_routes' ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -43,57 +43,105 @@ class PR_Core_Rest_Controller {
|
|||||||
*/
|
*/
|
||||||
public function register_routes(): void {
|
public function register_routes(): void {
|
||||||
// GET /peptides
|
// GET /peptides
|
||||||
register_rest_route( self::REST_NAMESPACE, '/peptides', [
|
register_rest_route(
|
||||||
|
self::REST_NAMESPACE,
|
||||||
|
'/peptides',
|
||||||
|
array(
|
||||||
'methods' => 'GET',
|
'methods' => 'GET',
|
||||||
'callback' => [ $this, 'list_peptides' ],
|
'callback' => array( $this, 'list_peptides' ),
|
||||||
'permission_callback' => '__return_true',
|
'permission_callback' => '__return_true',
|
||||||
'args' => [
|
'args' => array(
|
||||||
'category' => [ 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field' ],
|
'category' => array(
|
||||||
'evidence_strength' => [ 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field' ],
|
'type' => 'string',
|
||||||
'search' => [ 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field' ],
|
'sanitize_callback' => 'sanitize_text_field',
|
||||||
'per_page' => [ 'type' => 'integer', 'default' => 25, 'minimum' => 1, 'maximum' => 100 ],
|
),
|
||||||
'page' => [ 'type' => 'integer', 'default' => 1, 'minimum' => 1 ],
|
'evidence_strength' => array(
|
||||||
],
|
'type' => 'string',
|
||||||
] );
|
'sanitize_callback' => 'sanitize_text_field',
|
||||||
|
),
|
||||||
|
'search' => array(
|
||||||
|
'type' => 'string',
|
||||||
|
'sanitize_callback' => 'sanitize_text_field',
|
||||||
|
),
|
||||||
|
'per_page' => array(
|
||||||
|
'type' => 'integer',
|
||||||
|
'default' => 25,
|
||||||
|
'minimum' => 1,
|
||||||
|
'maximum' => 100,
|
||||||
|
),
|
||||||
|
'page' => array(
|
||||||
|
'type' => 'integer',
|
||||||
|
'default' => 1,
|
||||||
|
'minimum' => 1,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
// GET /peptides/{id}
|
// GET /peptides/{id}
|
||||||
register_rest_route( self::REST_NAMESPACE, '/peptides/(?P<id>\d+)', [
|
register_rest_route(
|
||||||
|
self::REST_NAMESPACE,
|
||||||
|
'/peptides/(?P<id>\d+)',
|
||||||
|
array(
|
||||||
'methods' => 'GET',
|
'methods' => 'GET',
|
||||||
'callback' => [ $this, 'get_peptide' ],
|
'callback' => array( $this, 'get_peptide' ),
|
||||||
'permission_callback' => '__return_true',
|
'permission_callback' => '__return_true',
|
||||||
] );
|
)
|
||||||
|
);
|
||||||
|
|
||||||
// GET /peptides/{id}/dosing
|
// GET /peptides/{id}/dosing
|
||||||
register_rest_route( self::REST_NAMESPACE, '/peptides/(?P<id>\d+)/dosing', [
|
register_rest_route(
|
||||||
|
self::REST_NAMESPACE,
|
||||||
|
'/peptides/(?P<id>\d+)/dosing',
|
||||||
|
array(
|
||||||
'methods' => 'GET',
|
'methods' => 'GET',
|
||||||
'callback' => [ $this, 'list_dosing' ],
|
'callback' => array( $this, 'list_dosing' ),
|
||||||
'permission_callback' => '__return_true',
|
'permission_callback' => '__return_true',
|
||||||
'args' => [
|
'args' => array(
|
||||||
'route' => [ 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field' ],
|
'route' => array(
|
||||||
'population' => [ 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field' ],
|
'type' => 'string',
|
||||||
],
|
'sanitize_callback' => 'sanitize_text_field',
|
||||||
] );
|
),
|
||||||
|
'population' => array(
|
||||||
|
'type' => 'string',
|
||||||
|
'sanitize_callback' => 'sanitize_text_field',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
// POST /peptides/{id}/dosing (auth required)
|
// POST /peptides/{id}/dosing (auth required)
|
||||||
register_rest_route( self::REST_NAMESPACE, '/peptides/(?P<id>\d+)/dosing', [
|
register_rest_route(
|
||||||
|
self::REST_NAMESPACE,
|
||||||
|
'/peptides/(?P<id>\d+)/dosing',
|
||||||
|
array(
|
||||||
'methods' => 'POST',
|
'methods' => 'POST',
|
||||||
'callback' => [ $this, 'create_dosing' ],
|
'callback' => array( $this, 'create_dosing' ),
|
||||||
'permission_callback' => [ $this, 'check_write_permission' ],
|
'permission_callback' => array( $this, 'check_write_permission' ),
|
||||||
] );
|
)
|
||||||
|
);
|
||||||
|
|
||||||
// GET /peptides/{id}/legal
|
// GET /peptides/{id}/legal
|
||||||
register_rest_route( self::REST_NAMESPACE, '/peptides/(?P<id>\d+)/legal', [
|
register_rest_route(
|
||||||
|
self::REST_NAMESPACE,
|
||||||
|
'/peptides/(?P<id>\d+)/legal',
|
||||||
|
array(
|
||||||
'methods' => 'GET',
|
'methods' => 'GET',
|
||||||
'callback' => [ $this, 'list_legal' ],
|
'callback' => array( $this, 'list_legal' ),
|
||||||
'permission_callback' => '__return_true',
|
'permission_callback' => '__return_true',
|
||||||
] );
|
)
|
||||||
|
);
|
||||||
|
|
||||||
// POST /peptides/{id}/legal (auth required)
|
// POST /peptides/{id}/legal (auth required)
|
||||||
register_rest_route( self::REST_NAMESPACE, '/peptides/(?P<id>\d+)/legal', [
|
register_rest_route(
|
||||||
|
self::REST_NAMESPACE,
|
||||||
|
'/peptides/(?P<id>\d+)/legal',
|
||||||
|
array(
|
||||||
'methods' => 'POST',
|
'methods' => 'POST',
|
||||||
'callback' => [ $this, 'create_legal' ],
|
'callback' => array( $this, 'create_legal' ),
|
||||||
'permission_callback' => [ $this, 'check_write_permission' ],
|
'permission_callback' => array( $this, 'check_write_permission' ),
|
||||||
] );
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -109,12 +157,14 @@ class PR_Core_Rest_Controller {
|
|||||||
if ( $search ) {
|
if ( $search ) {
|
||||||
$peptides = $repo->search( $search, (int) $request->get_param( 'per_page' ) );
|
$peptides = $repo->search( $search, (int) $request->get_param( 'per_page' ) );
|
||||||
} else {
|
} else {
|
||||||
$peptides = $repo->find_all( [
|
$peptides = $repo->find_all(
|
||||||
|
array(
|
||||||
'category' => $request->get_param( 'category' ),
|
'category' => $request->get_param( 'category' ),
|
||||||
'evidence_strength' => $request->get_param( 'evidence_strength' ),
|
'evidence_strength' => $request->get_param( 'evidence_strength' ),
|
||||||
'per_page' => $request->get_param( 'per_page' ),
|
'per_page' => $request->get_param( 'per_page' ),
|
||||||
'page' => $request->get_param( 'page' ),
|
'page' => $request->get_param( 'page' ),
|
||||||
] );
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = array_map( static fn( PR_Core_Peptide_DTO $p ) => $p->to_array(), $peptides );
|
$data = array_map( static fn( PR_Core_Peptide_DTO $p ) => $p->to_array(), $peptides );
|
||||||
@@ -133,7 +183,7 @@ class PR_Core_Rest_Controller {
|
|||||||
$peptide = $repo->find_by_id( (int) $request->get_param( 'id' ) );
|
$peptide = $repo->find_by_id( (int) $request->get_param( 'id' ) );
|
||||||
|
|
||||||
if ( ! $peptide ) {
|
if ( ! $peptide ) {
|
||||||
return new \WP_Error( 'not_found', __( 'Peptide not found.', 'peptide-repo-core' ), [ 'status' => 404 ] );
|
return new \WP_Error( 'not_found', __( 'Peptide not found.', 'peptide-repo-core' ), array( 'status' => 404 ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
return new \WP_REST_Response( $peptide->to_array(), 200 );
|
return new \WP_REST_Response( $peptide->to_array(), 200 );
|
||||||
@@ -149,10 +199,12 @@ class PR_Core_Rest_Controller {
|
|||||||
$repo = new PR_Core_Dosing_Repository();
|
$repo = new PR_Core_Dosing_Repository();
|
||||||
$rows = $repo->find_by_peptide(
|
$rows = $repo->find_by_peptide(
|
||||||
(int) $request->get_param( 'id' ),
|
(int) $request->get_param( 'id' ),
|
||||||
array_filter( [
|
array_filter(
|
||||||
|
array(
|
||||||
'route' => $request->get_param( 'route' ),
|
'route' => $request->get_param( 'route' ),
|
||||||
'population' => $request->get_param( 'population' ),
|
'population' => $request->get_param( 'population' ),
|
||||||
] )
|
)
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
$data = array_map( static fn( PR_Core_Dosing_Row_DTO $r ) => $r->to_array(), $rows );
|
$data = array_map( static fn( PR_Core_Dosing_Row_DTO $r ) => $r->to_array(), $rows );
|
||||||
@@ -176,12 +228,12 @@ class PR_Core_Rest_Controller {
|
|||||||
$id = $repo->insert( $data );
|
$id = $repo->insert( $data );
|
||||||
|
|
||||||
if ( 0 === $id ) {
|
if ( 0 === $id ) {
|
||||||
return new \WP_Error( 'insert_failed', __( 'Failed to insert dosing row.', 'peptide-repo-core' ), [ 'status' => 500 ] );
|
return new \WP_Error( 'insert_failed', __( 'Failed to insert dosing row.', 'peptide-repo-core' ), array( 'status' => 500 ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
$row = $repo->find_by_id( $id );
|
$row = $repo->find_by_id( $id );
|
||||||
|
|
||||||
return new \WP_REST_Response( $row ? $row->to_array() : [ 'id' => $id ], 201 );
|
return new \WP_REST_Response( $row ? $row->to_array() : array( 'id' => $id ), 201 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -215,12 +267,12 @@ class PR_Core_Rest_Controller {
|
|||||||
$id = $repo->insert( $data );
|
$id = $repo->insert( $data );
|
||||||
|
|
||||||
if ( 0 === $id ) {
|
if ( 0 === $id ) {
|
||||||
return new \WP_Error( 'insert_failed', __( 'Failed to insert legal cell.', 'peptide-repo-core' ), [ 'status' => 500 ] );
|
return new \WP_Error( 'insert_failed', __( 'Failed to insert legal cell.', 'peptide-repo-core' ), array( 'status' => 500 ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
$cell = $repo->find_by_id( $id );
|
$cell = $repo->find_by_id( $id );
|
||||||
|
|
||||||
return new \WP_REST_Response( $cell ? $cell->to_array() : [ 'id' => $id ], 201 );
|
return new \WP_REST_Response( $cell ? $cell->to_array() : array( 'id' => $id ), 201 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ class PR_Core_Activator {
|
|||||||
*/
|
*/
|
||||||
private static function add_capabilities(): void {
|
private static function add_capabilities(): void {
|
||||||
$cap = 'manage_peptide_content';
|
$cap = 'manage_peptide_content';
|
||||||
$roles = [ 'administrator', 'editor' ];
|
$roles = array( 'administrator', 'editor' );
|
||||||
|
|
||||||
foreach ( $roles as $role_name ) {
|
foreach ( $roles as $role_name ) {
|
||||||
$role = get_role( $role_name );
|
$role = get_role( $role_name );
|
||||||
@@ -156,4 +156,3 @@ class PR_Core_Activator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ declare(strict_types=1);
|
|||||||
class PR_Core_Autoloader {
|
class PR_Core_Autoloader {
|
||||||
|
|
||||||
/** @var string[] Directories to scan for class files. */
|
/** @var string[] Directories to scan for class files. */
|
||||||
private static array $dirs = [];
|
private static array $dirs = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register the autoloader with SPL.
|
* Register the autoloader with SPL.
|
||||||
@@ -35,7 +35,7 @@ class PR_Core_Autoloader {
|
|||||||
self::$dirs[] = trailingslashit( $dir );
|
self::$dirs[] = trailingslashit( $dir );
|
||||||
}
|
}
|
||||||
|
|
||||||
spl_autoload_register( [ __CLASS__, 'load' ] );
|
spl_autoload_register( array( __CLASS__, 'load' ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -24,11 +24,11 @@ class PR_Core_Seed_Data {
|
|||||||
$dosing = self::seed_dosing_rows( $peptide_ids );
|
$dosing = self::seed_dosing_rows( $peptide_ids );
|
||||||
$legal = self::seed_legal_cells( $peptide_ids );
|
$legal = self::seed_legal_cells( $peptide_ids );
|
||||||
|
|
||||||
return [
|
return array(
|
||||||
'peptides' => count( $peptide_ids ),
|
'peptides' => count( $peptide_ids ),
|
||||||
'dosing_rows' => $dosing,
|
'dosing_rows' => $dosing,
|
||||||
'legal_cells' => $legal,
|
'legal_cells' => $legal,
|
||||||
];
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -37,8 +37,8 @@ class PR_Core_Seed_Data {
|
|||||||
* @return array<string, int> Map of slug => post ID.
|
* @return array<string, int> Map of slug => post ID.
|
||||||
*/
|
*/
|
||||||
private static function seed_peptides(): array {
|
private static function seed_peptides(): array {
|
||||||
$peptides = [
|
$peptides = array(
|
||||||
[
|
array(
|
||||||
'title' => 'BPC-157',
|
'title' => 'BPC-157',
|
||||||
'slug' => 'bpc-157',
|
'slug' => 'bpc-157',
|
||||||
'excerpt' => 'Body Protection Compound-157, a pentadecapeptide derived from human gastric juice.',
|
'excerpt' => 'Body Protection Compound-157, a pentadecapeptide derived from human gastric juice.',
|
||||||
@@ -50,8 +50,8 @@ class PR_Core_Seed_Data {
|
|||||||
'drugbank_id' => '',
|
'drugbank_id' => '',
|
||||||
'chembl_id' => '',
|
'chembl_id' => '',
|
||||||
'evidence_strength' => 'observational',
|
'evidence_strength' => 'observational',
|
||||||
],
|
),
|
||||||
[
|
array(
|
||||||
'title' => 'Semaglutide',
|
'title' => 'Semaglutide',
|
||||||
'slug' => 'semaglutide',
|
'slug' => 'semaglutide',
|
||||||
'excerpt' => 'A GLP-1 receptor agonist approved for type 2 diabetes and chronic weight management.',
|
'excerpt' => 'A GLP-1 receptor agonist approved for type 2 diabetes and chronic weight management.',
|
||||||
@@ -63,8 +63,8 @@ class PR_Core_Seed_Data {
|
|||||||
'drugbank_id' => 'DB13928',
|
'drugbank_id' => 'DB13928',
|
||||||
'chembl_id' => 'CHEMBL3137309',
|
'chembl_id' => 'CHEMBL3137309',
|
||||||
'evidence_strength' => 'meta-analysis',
|
'evidence_strength' => 'meta-analysis',
|
||||||
],
|
),
|
||||||
[
|
array(
|
||||||
'title' => 'TB-500',
|
'title' => 'TB-500',
|
||||||
'slug' => 'tb-500',
|
'slug' => 'tb-500',
|
||||||
'excerpt' => 'Thymosin Beta-4 fragment, a synthetic peptide used in tissue repair research.',
|
'excerpt' => 'Thymosin Beta-4 fragment, a synthetic peptide used in tissue repair research.',
|
||||||
@@ -76,37 +76,41 @@ class PR_Core_Seed_Data {
|
|||||||
'drugbank_id' => '',
|
'drugbank_id' => '',
|
||||||
'chembl_id' => '',
|
'chembl_id' => '',
|
||||||
'evidence_strength' => 'preclinical',
|
'evidence_strength' => 'preclinical',
|
||||||
],
|
),
|
||||||
];
|
);
|
||||||
|
|
||||||
$ids = [];
|
$ids = array();
|
||||||
foreach ( $peptides as $p ) {
|
foreach ( $peptides as $p ) {
|
||||||
$existing = get_posts( [
|
$existing = get_posts(
|
||||||
|
array(
|
||||||
'post_type' => PR_Core_Peptide_CPT::POST_TYPE,
|
'post_type' => PR_Core_Peptide_CPT::POST_TYPE,
|
||||||
'name' => $p['slug'],
|
'name' => $p['slug'],
|
||||||
'posts_per_page' => 1,
|
'posts_per_page' => 1,
|
||||||
'post_status' => 'any',
|
'post_status' => 'any',
|
||||||
] );
|
)
|
||||||
|
);
|
||||||
|
|
||||||
if ( ! empty( $existing ) ) {
|
if ( ! empty( $existing ) ) {
|
||||||
$ids[ $p['slug'] ] = $existing[0]->ID;
|
$ids[ $p['slug'] ] = $existing[0]->ID;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$post_id = wp_insert_post( [
|
$post_id = wp_insert_post(
|
||||||
|
array(
|
||||||
'post_type' => PR_Core_Peptide_CPT::POST_TYPE,
|
'post_type' => PR_Core_Peptide_CPT::POST_TYPE,
|
||||||
'post_title' => $p['title'],
|
'post_title' => $p['title'],
|
||||||
'post_name' => $p['slug'],
|
'post_name' => $p['slug'],
|
||||||
'post_excerpt' => $p['excerpt'],
|
'post_excerpt' => $p['excerpt'],
|
||||||
'post_status' => 'publish',
|
'post_status' => 'publish',
|
||||||
'post_content' => '',
|
'post_content' => '',
|
||||||
] );
|
)
|
||||||
|
);
|
||||||
|
|
||||||
if ( is_wp_error( $post_id ) ) {
|
if ( is_wp_error( $post_id ) ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ( [ 'display_name', 'aliases', 'molecular_formula', 'molecular_weight', 'cas_number', 'drugbank_id', 'chembl_id', 'evidence_strength' ] as $key ) {
|
foreach ( array( 'display_name', 'aliases', 'molecular_formula', 'molecular_weight', 'cas_number', 'drugbank_id', 'chembl_id', 'evidence_strength' ) as $key ) {
|
||||||
update_post_meta( $post_id, $key, $p[ $key ] );
|
update_post_meta( $post_id, $key, $p[ $key ] );
|
||||||
}
|
}
|
||||||
update_post_meta( $post_id, 'editorial_review_status', 'published' );
|
update_post_meta( $post_id, 'editorial_review_status', 'published' );
|
||||||
@@ -126,21 +130,145 @@ class PR_Core_Seed_Data {
|
|||||||
*/
|
*/
|
||||||
private static function seed_dosing_rows( array $peptide_ids ): int {
|
private static function seed_dosing_rows( array $peptide_ids ): int {
|
||||||
$repo = new PR_Core_Dosing_Repository();
|
$repo = new PR_Core_Dosing_Repository();
|
||||||
$rows = [
|
$rows = array(
|
||||||
// BPC-157 (4 rows).
|
// BPC-157 (4 rows).
|
||||||
[ 'peptide' => 'bpc-157', 'dose_min' => 200, 'dose_max' => 300, 'dose_unit' => 'mcg', 'route' => 'subq', 'frequency' => 'twice daily', 'population' => 'healthy', 'evidence_strength' => 'observational', 'study_title' => 'BPC 157 in wound healing review', 'study_year' => 2021, 'citation_pubmed_id' => '34537800' ],
|
array(
|
||||||
[ 'peptide' => 'bpc-157', 'dose_min' => 500, 'dose_max' => 500, 'dose_unit' => 'mcg', 'route' => 'subq', 'frequency' => 'daily', 'population' => 'healthy', 'evidence_strength' => 'case-series', 'study_title' => 'Subcutaneous BPC-157 in tendon repair', 'study_year' => 2019, 'citation_pubmed_id' => '30915550' ],
|
'peptide' => 'bpc-157',
|
||||||
[ 'peptide' => 'bpc-157', 'dose_min' => 10, 'dose_max' => 10, 'dose_unit' => 'mcg', 'route' => 'oral', 'frequency' => 'daily', 'population' => 'animal', 'evidence_strength' => 'preclinical', 'study_title' => 'Oral BPC-157 in rat gastric ulcer model', 'study_year' => 2018, 'citation_pubmed_id' => '29869189' ],
|
'dose_min' => 200,
|
||||||
[ 'peptide' => 'bpc-157', 'dose_min' => 250, 'dose_max' => 750, 'dose_unit' => 'mcg', 'route' => 'im', 'frequency' => 'daily', 'population' => 'clinical', 'evidence_strength' => 'case-series', 'study_title' => 'Intramuscular BPC-157 for muscle injuries', 'study_year' => 2020, 'citation_pubmed_id' => '33312000' ],
|
'dose_max' => 300,
|
||||||
|
'dose_unit' => 'mcg',
|
||||||
|
'route' => 'subq',
|
||||||
|
'frequency' => 'twice daily',
|
||||||
|
'population' => 'healthy',
|
||||||
|
'evidence_strength' => 'observational',
|
||||||
|
'study_title' => 'BPC 157 in wound healing review',
|
||||||
|
'study_year' => 2021,
|
||||||
|
'citation_pubmed_id' => '34537800',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'peptide' => 'bpc-157',
|
||||||
|
'dose_min' => 500,
|
||||||
|
'dose_max' => 500,
|
||||||
|
'dose_unit' => 'mcg',
|
||||||
|
'route' => 'subq',
|
||||||
|
'frequency' => 'daily',
|
||||||
|
'population' => 'healthy',
|
||||||
|
'evidence_strength' => 'case-series',
|
||||||
|
'study_title' => 'Subcutaneous BPC-157 in tendon repair',
|
||||||
|
'study_year' => 2019,
|
||||||
|
'citation_pubmed_id' => '30915550',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'peptide' => 'bpc-157',
|
||||||
|
'dose_min' => 10,
|
||||||
|
'dose_max' => 10,
|
||||||
|
'dose_unit' => 'mcg',
|
||||||
|
'route' => 'oral',
|
||||||
|
'frequency' => 'daily',
|
||||||
|
'population' => 'animal',
|
||||||
|
'evidence_strength' => 'preclinical',
|
||||||
|
'study_title' => 'Oral BPC-157 in rat gastric ulcer model',
|
||||||
|
'study_year' => 2018,
|
||||||
|
'citation_pubmed_id' => '29869189',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'peptide' => 'bpc-157',
|
||||||
|
'dose_min' => 250,
|
||||||
|
'dose_max' => 750,
|
||||||
|
'dose_unit' => 'mcg',
|
||||||
|
'route' => 'im',
|
||||||
|
'frequency' => 'daily',
|
||||||
|
'population' => 'clinical',
|
||||||
|
'evidence_strength' => 'case-series',
|
||||||
|
'study_title' => 'Intramuscular BPC-157 for muscle injuries',
|
||||||
|
'study_year' => 2020,
|
||||||
|
'citation_pubmed_id' => '33312000',
|
||||||
|
),
|
||||||
// Semaglutide (4 rows).
|
// Semaglutide (4 rows).
|
||||||
[ 'peptide' => 'semaglutide', 'dose_min' => 0.25, 'dose_max' => 0.25, 'dose_unit' => 'mg', 'route' => 'subq', 'frequency' => 'weekly', 'population' => 'clinical', 'evidence_strength' => 'rct-large', 'study_title' => 'SUSTAIN 1: Semaglutide in T2DM', 'study_year' => 2017, 'citation_pubmed_id' => '28930514', 'indication' => 'Type 2 diabetes — initiation dose' ],
|
array(
|
||||||
[ 'peptide' => 'semaglutide', 'dose_min' => 1.0, 'dose_max' => 1.0, 'dose_unit' => 'mg', 'route' => 'subq', 'frequency' => 'weekly', 'population' => 'clinical', 'evidence_strength' => 'rct-large', 'study_title' => 'SUSTAIN 6: CV outcomes with semaglutide', 'study_year' => 2016, 'citation_pubmed_id' => '27633186', 'indication' => 'Type 2 diabetes — maintenance' ],
|
'peptide' => 'semaglutide',
|
||||||
[ 'peptide' => 'semaglutide', 'dose_min' => 2.4, 'dose_max' => 2.4, 'dose_unit' => 'mg', 'route' => 'subq', 'frequency' => 'weekly', 'population' => 'clinical', 'evidence_strength' => 'rct-large', 'study_title' => 'STEP 1: Semaglutide 2.4mg for obesity', 'study_year' => 2021, 'citation_pubmed_id' => '33567185', 'indication' => 'Chronic weight management' ],
|
'dose_min' => 0.25,
|
||||||
[ 'peptide' => 'semaglutide', 'dose_min' => 14, 'dose_max' => 14, 'dose_unit' => 'mg', 'route' => 'oral', 'frequency' => 'daily', 'population' => 'clinical', 'evidence_strength' => 'rct-large', 'study_title' => 'PIONEER 1: Oral semaglutide in T2DM', 'study_year' => 2019, 'citation_pubmed_id' => '30924169', 'indication' => 'Type 2 diabetes — oral formulation' ],
|
'dose_max' => 0.25,
|
||||||
|
'dose_unit' => 'mg',
|
||||||
|
'route' => 'subq',
|
||||||
|
'frequency' => 'weekly',
|
||||||
|
'population' => 'clinical',
|
||||||
|
'evidence_strength' => 'rct-large',
|
||||||
|
'study_title' => 'SUSTAIN 1: Semaglutide in T2DM',
|
||||||
|
'study_year' => 2017,
|
||||||
|
'citation_pubmed_id' => '28930514',
|
||||||
|
'indication' => 'Type 2 diabetes — initiation dose',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'peptide' => 'semaglutide',
|
||||||
|
'dose_min' => 1.0,
|
||||||
|
'dose_max' => 1.0,
|
||||||
|
'dose_unit' => 'mg',
|
||||||
|
'route' => 'subq',
|
||||||
|
'frequency' => 'weekly',
|
||||||
|
'population' => 'clinical',
|
||||||
|
'evidence_strength' => 'rct-large',
|
||||||
|
'study_title' => 'SUSTAIN 6: CV outcomes with semaglutide',
|
||||||
|
'study_year' => 2016,
|
||||||
|
'citation_pubmed_id' => '27633186',
|
||||||
|
'indication' => 'Type 2 diabetes — maintenance',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'peptide' => 'semaglutide',
|
||||||
|
'dose_min' => 2.4,
|
||||||
|
'dose_max' => 2.4,
|
||||||
|
'dose_unit' => 'mg',
|
||||||
|
'route' => 'subq',
|
||||||
|
'frequency' => 'weekly',
|
||||||
|
'population' => 'clinical',
|
||||||
|
'evidence_strength' => 'rct-large',
|
||||||
|
'study_title' => 'STEP 1: Semaglutide 2.4mg for obesity',
|
||||||
|
'study_year' => 2021,
|
||||||
|
'citation_pubmed_id' => '33567185',
|
||||||
|
'indication' => 'Chronic weight management',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'peptide' => 'semaglutide',
|
||||||
|
'dose_min' => 14,
|
||||||
|
'dose_max' => 14,
|
||||||
|
'dose_unit' => 'mg',
|
||||||
|
'route' => 'oral',
|
||||||
|
'frequency' => 'daily',
|
||||||
|
'population' => 'clinical',
|
||||||
|
'evidence_strength' => 'rct-large',
|
||||||
|
'study_title' => 'PIONEER 1: Oral semaglutide in T2DM',
|
||||||
|
'study_year' => 2019,
|
||||||
|
'citation_pubmed_id' => '30924169',
|
||||||
|
'indication' => 'Type 2 diabetes — oral formulation',
|
||||||
|
),
|
||||||
// TB-500 (2 rows).
|
// TB-500 (2 rows).
|
||||||
[ 'peptide' => 'tb-500', 'dose_min' => 2, 'dose_max' => 2.5, 'dose_unit' => 'mg', 'route' => 'subq', 'frequency' => 'twice weekly', 'population' => 'animal', 'evidence_strength' => 'preclinical', 'study_title' => 'Thymosin beta-4 promotes dermal healing in rats', 'study_year' => 2007, 'citation_pubmed_id' => '17584560' ],
|
array(
|
||||||
[ 'peptide' => 'tb-500', 'dose_min' => 5, 'dose_max' => 5, 'dose_unit' => 'mg', 'route' => 'subq', 'frequency' => 'weekly', 'population' => 'animal', 'evidence_strength' => 'preclinical', 'study_title' => 'TB4 cardiac repair in murine MI model', 'study_year' => 2012, 'citation_pubmed_id' => '22561753' ],
|
'peptide' => 'tb-500',
|
||||||
];
|
'dose_min' => 2,
|
||||||
|
'dose_max' => 2.5,
|
||||||
|
'dose_unit' => 'mg',
|
||||||
|
'route' => 'subq',
|
||||||
|
'frequency' => 'twice weekly',
|
||||||
|
'population' => 'animal',
|
||||||
|
'evidence_strength' => 'preclinical',
|
||||||
|
'study_title' => 'Thymosin beta-4 promotes dermal healing in rats',
|
||||||
|
'study_year' => 2007,
|
||||||
|
'citation_pubmed_id' => '17584560',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'peptide' => 'tb-500',
|
||||||
|
'dose_min' => 5,
|
||||||
|
'dose_max' => 5,
|
||||||
|
'dose_unit' => 'mg',
|
||||||
|
'route' => 'subq',
|
||||||
|
'frequency' => 'weekly',
|
||||||
|
'population' => 'animal',
|
||||||
|
'evidence_strength' => 'preclinical',
|
||||||
|
'study_title' => 'TB4 cardiac repair in murine MI model',
|
||||||
|
'study_year' => 2012,
|
||||||
|
'citation_pubmed_id' => '22561753',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
$count = 0;
|
$count = 0;
|
||||||
foreach ( $rows as $row ) {
|
foreach ( $rows as $row ) {
|
||||||
@@ -156,7 +284,7 @@ class PR_Core_Seed_Data {
|
|||||||
$row['added_by'] = get_current_user_id() ?: 1;
|
$row['added_by'] = get_current_user_id() ?: 1;
|
||||||
|
|
||||||
if ( $repo->insert( $row ) > 0 ) {
|
if ( $repo->insert( $row ) > 0 ) {
|
||||||
$count++;
|
++$count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,13 +299,44 @@ class PR_Core_Seed_Data {
|
|||||||
*/
|
*/
|
||||||
private static function seed_legal_cells( array $peptide_ids ): int {
|
private static function seed_legal_cells( array $peptide_ids ): int {
|
||||||
$repo = new PR_Core_Legal_Repository();
|
$repo = new PR_Core_Legal_Repository();
|
||||||
$cells = [
|
$cells = array(
|
||||||
[ 'peptide' => 'bpc-157', 'country_code' => 'US', 'status' => 'ruo', 'regulatory_framework' => 'Not FDA-approved; available as Research Use Only', 'notes' => 'Compounding pharmacies may dispense under FDA 503A/503B exemptions.' ],
|
array(
|
||||||
[ 'peptide' => 'bpc-157', 'country_code' => 'GB', 'status' => 'unclear', 'regulatory_framework' => 'Not listed by MHRA', 'notes' => 'No specific scheduling; import for personal use is a grey area.' ],
|
'peptide' => 'bpc-157',
|
||||||
[ 'peptide' => 'semaglutide', 'country_code' => 'US', 'status' => 'prescription', 'regulatory_framework' => 'FDA-approved (Ozempic, Wegovy, Rybelsus)', 'regulatory_text_url' => 'https://www.accessdata.fda.gov/drugsatfda_docs/label/2023/209637s020lbl.pdf', 'notes' => 'Schedule IV not applicable; requires valid prescription.' ],
|
'country_code' => 'US',
|
||||||
[ 'peptide' => 'semaglutide', 'country_code' => 'GB', 'status' => 'prescription', 'regulatory_framework' => 'MHRA-approved (Ozempic, Wegovy)', 'notes' => 'Available via NHS and private prescription.' ],
|
'status' => 'ruo',
|
||||||
[ 'peptide' => 'semaglutide', 'country_code' => 'AU', 'status' => 'prescription', 'regulatory_framework' => 'TGA-approved (Ozempic)', 'notes' => 'PBS-listed for type 2 diabetes; Wegovy approval pending as of 2025.' ],
|
'regulatory_framework' => 'Not FDA-approved; available as Research Use Only',
|
||||||
];
|
'notes' => 'Compounding pharmacies may dispense under FDA 503A/503B exemptions.',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'peptide' => 'bpc-157',
|
||||||
|
'country_code' => 'GB',
|
||||||
|
'status' => 'unclear',
|
||||||
|
'regulatory_framework' => 'Not listed by MHRA',
|
||||||
|
'notes' => 'No specific scheduling; import for personal use is a grey area.',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'peptide' => 'semaglutide',
|
||||||
|
'country_code' => 'US',
|
||||||
|
'status' => 'prescription',
|
||||||
|
'regulatory_framework' => 'FDA-approved (Ozempic, Wegovy, Rybelsus)',
|
||||||
|
'regulatory_text_url' => 'https://www.accessdata.fda.gov/drugsatfda_docs/label/2023/209637s020lbl.pdf',
|
||||||
|
'notes' => 'Schedule IV not applicable; requires valid prescription.',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'peptide' => 'semaglutide',
|
||||||
|
'country_code' => 'GB',
|
||||||
|
'status' => 'prescription',
|
||||||
|
'regulatory_framework' => 'MHRA-approved (Ozempic, Wegovy)',
|
||||||
|
'notes' => 'Available via NHS and private prescription.',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'peptide' => 'semaglutide',
|
||||||
|
'country_code' => 'AU',
|
||||||
|
'status' => 'prescription',
|
||||||
|
'regulatory_framework' => 'TGA-approved (Ozempic)',
|
||||||
|
'notes' => 'PBS-listed for type 2 diabetes; Wegovy approval pending as of 2025.',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
$count = 0;
|
$count = 0;
|
||||||
foreach ( $cells as $cell ) {
|
foreach ( $cells as $cell ) {
|
||||||
@@ -192,7 +351,7 @@ class PR_Core_Seed_Data {
|
|||||||
$cell['reviewer_id'] = get_current_user_id() ?: 1;
|
$cell['reviewer_id'] = get_current_user_id() ?: 1;
|
||||||
|
|
||||||
if ( $repo->insert( $cell ) > 0 ) {
|
if ( $repo->insert( $cell ) > 0 ) {
|
||||||
$count++;
|
++$count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -47,24 +47,24 @@ class PR_Core {
|
|||||||
// end of init (priority 999) so all CPTs/taxonomies — ours and
|
// end of init (priority 999) so all CPTs/taxonomies — ours and
|
||||||
// anyone else's — are registered first. Handles updates deployed
|
// anyone else's — are registered first. Handles updates deployed
|
||||||
// without a deactivate/reactivate cycle (e.g., SCP/rsync pushes).
|
// without a deactivate/reactivate cycle (e.g., SCP/rsync pushes).
|
||||||
add_action( 'init', [ PR_Core_Activator::class, 'maybe_flush_on_version_change' ], 999 );
|
add_action( 'init', array( PR_Core_Activator::class, 'maybe_flush_on_version_change' ), 999 );
|
||||||
|
|
||||||
// Verification scanner: register cron hook and schedule if not already scheduled.
|
// Verification scanner: register cron hook and schedule if not already scheduled.
|
||||||
if ( ! wp_next_scheduled( 'pr_core_verification_scan' ) ) {
|
if ( ! wp_next_scheduled( 'pr_core_verification_scan' ) ) {
|
||||||
wp_schedule_event( time(), get_option( 'pr_core_scan_cadence', 'weekly' ), 'pr_core_verification_scan' );
|
wp_schedule_event( time(), get_option( 'pr_core_scan_cadence', 'weekly' ), 'pr_core_verification_scan' );
|
||||||
}
|
}
|
||||||
add_action( 'pr_core_verification_scan', [ PR_Core_Verification_Scanner::class, 'run_scan' ] );
|
add_action( 'pr_core_verification_scan', array( PR_Core_Verification_Scanner::class, 'run_scan' ) );
|
||||||
|
|
||||||
// Ajax handlers must be registered outside is_admin() — admin-ajax.php
|
// Ajax handlers must be registered outside is_admin() — admin-ajax.php
|
||||||
// does not define WP_ADMIN, so is_admin() returns false for ajax requests.
|
// does not define WP_ADMIN, so is_admin() returns false for ajax requests.
|
||||||
add_action( 'wp_ajax_pr_core_mark_verified', [ PR_Core_Ajax_Handlers::class, 'handle_mark_verified' ] );
|
add_action( 'wp_ajax_pr_core_mark_verified', array( PR_Core_Ajax_Handlers::class, 'handle_mark_verified' ) );
|
||||||
add_action( 'wp_ajax_pr_core_scan_now', [ PR_Core_Ajax_Handlers::class, 'handle_scan_now' ] );
|
add_action( 'wp_ajax_pr_core_scan_now', array( PR_Core_Ajax_Handlers::class, 'handle_scan_now' ) );
|
||||||
|
|
||||||
// Admin UI (fires on admin_init, admin_menu).
|
// Admin UI (fires on admin_init, admin_menu).
|
||||||
if ( is_admin() ) {
|
if ( is_admin() ) {
|
||||||
add_action( 'admin_menu', [ PR_Core_Settings::class, 'add_settings_page' ] );
|
add_action( 'admin_menu', array( PR_Core_Settings::class, 'add_settings_page' ) );
|
||||||
add_action( 'admin_init', [ PR_Core_Settings::class, 'register_settings' ] );
|
add_action( 'admin_init', array( PR_Core_Settings::class, 'register_settings' ) );
|
||||||
add_action( 'wp_dashboard_setup', [ PR_Core_Verification_Widget::class, 'register' ] );
|
add_action( 'wp_dashboard_setup', array( PR_Core_Verification_Widget::class, 'register' ) );
|
||||||
|
|
||||||
$admin = new PR_Core_Admin();
|
$admin = new PR_Core_Admin();
|
||||||
$admin->register_hooks();
|
$admin->register_hooks();
|
||||||
@@ -86,7 +86,7 @@ class PR_Core {
|
|||||||
$related_posts->register_hooks();
|
$related_posts->register_hooks();
|
||||||
|
|
||||||
// Enqueue related-posts CSS on single peptide pages.
|
// Enqueue related-posts CSS on single peptide pages.
|
||||||
add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_frontend_styles' ] );
|
add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_frontend_styles' ) );
|
||||||
|
|
||||||
// REST API.
|
// REST API.
|
||||||
$rest = new PR_Core_Rest_Controller();
|
$rest = new PR_Core_Rest_Controller();
|
||||||
@@ -109,7 +109,7 @@ class PR_Core {
|
|||||||
wp_enqueue_style(
|
wp_enqueue_style(
|
||||||
'pr-core-related-posts',
|
'pr-core-related-posts',
|
||||||
PR_CORE_PLUGIN_URL . 'assets/css/related-posts.css',
|
PR_CORE_PLUGIN_URL . 'assets/css/related-posts.css',
|
||||||
[],
|
array(),
|
||||||
PR_CORE_VERSION
|
PR_CORE_VERSION
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -125,9 +125,9 @@ class PR_Core {
|
|||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
private function register_public_filters(): void {
|
private function register_public_filters(): void {
|
||||||
add_filter( 'pr_core_get_indexable_corpus', [ $this, 'filter_indexable_corpus' ] );
|
add_filter( 'pr_core_get_indexable_corpus', array( $this, 'filter_indexable_corpus' ) );
|
||||||
add_filter( 'pr_core_disclaimer_for_surface', [ $this, 'filter_disclaimer_for_surface' ], 10, 2 );
|
add_filter( 'pr_core_disclaimer_for_surface', array( $this, 'filter_disclaimer_for_surface' ), 10, 2 );
|
||||||
add_filter( 'pr_core_evidence_strength_label', [ $this, 'filter_evidence_label' ], 10, 2 );
|
add_filter( 'pr_core_evidence_strength_label', array( $this, 'filter_evidence_label' ), 10, 2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -140,16 +140,16 @@ class PR_Core {
|
|||||||
*/
|
*/
|
||||||
public function filter_indexable_corpus( array $entries ): array {
|
public function filter_indexable_corpus( array $entries ): array {
|
||||||
$repo = new PR_Core_Peptide_Repository();
|
$repo = new PR_Core_Peptide_Repository();
|
||||||
$peptides = $repo->find_all( [ 'status' => 'publish' ] );
|
$peptides = $repo->find_all( array( 'status' => 'publish' ) );
|
||||||
|
|
||||||
foreach ( $peptides as $dto ) {
|
foreach ( $peptides as $dto ) {
|
||||||
$entries[] = [
|
$entries[] = array(
|
||||||
'id' => $dto->id,
|
'id' => $dto->id,
|
||||||
'url' => get_permalink( $dto->id ),
|
'url' => get_permalink( $dto->id ),
|
||||||
'title' => $dto->title,
|
'title' => $dto->title,
|
||||||
'body' => $dto->excerpt . "\n" . $dto->content,
|
'body' => $dto->excerpt . "\n" . $dto->content,
|
||||||
'type' => 'peptide_monograph',
|
'type' => 'peptide_monograph',
|
||||||
];
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $entries;
|
return $entries;
|
||||||
@@ -174,14 +174,14 @@ class PR_Core {
|
|||||||
* @return string Localized label.
|
* @return string Localized label.
|
||||||
*/
|
*/
|
||||||
public function filter_evidence_label( string $label, string $strength ): string {
|
public function filter_evidence_label( string $label, string $strength ): string {
|
||||||
$map = [
|
$map = array(
|
||||||
'preclinical' => __( 'Preclinical', 'peptide-repo-core' ),
|
'preclinical' => __( 'Preclinical', 'peptide-repo-core' ),
|
||||||
'case-series' => __( 'Case Series', 'peptide-repo-core' ),
|
'case-series' => __( 'Case Series', 'peptide-repo-core' ),
|
||||||
'observational' => __( 'Observational', 'peptide-repo-core' ),
|
'observational' => __( 'Observational', 'peptide-repo-core' ),
|
||||||
'rct-small' => __( 'Small RCT', 'peptide-repo-core' ),
|
'rct-small' => __( 'Small RCT', 'peptide-repo-core' ),
|
||||||
'rct-large' => __( 'Large RCT', 'peptide-repo-core' ),
|
'rct-large' => __( 'Large RCT', 'peptide-repo-core' ),
|
||||||
'meta-analysis' => __( 'Meta-Analysis', 'peptide-repo-core' ),
|
'meta-analysis' => __( 'Meta-Analysis', 'peptide-repo-core' ),
|
||||||
];
|
);
|
||||||
|
|
||||||
return $map[ $strength ] ?? $strength;
|
return $map[ $strength ] ?? $strength;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ class PR_Core_Internal_Posts_Provider implements PR_Core_Related_Posts_Provider
|
|||||||
public function get_posts( int $peptide_id, int $limit ): array {
|
public function get_posts( int $peptide_id, int $limit ): array {
|
||||||
$peptide = get_post( $peptide_id );
|
$peptide = get_post( $peptide_id );
|
||||||
if ( ! $peptide || 'peptide' !== $peptide->post_type ) {
|
if ( ! $peptide || 'peptide' !== $peptide->post_type ) {
|
||||||
return [];
|
return array();
|
||||||
}
|
}
|
||||||
|
|
||||||
$cache_key = 'pr_core_related_' . $peptide_id;
|
$cache_key = 'pr_core_related_' . $peptide_id;
|
||||||
@@ -64,21 +64,23 @@ class PR_Core_Internal_Posts_Provider implements PR_Core_Related_Posts_Provider
|
|||||||
* @return array<int, \WP_Post>
|
* @return array<int, \WP_Post>
|
||||||
*/
|
*/
|
||||||
private function query_by_taxonomy( string $peptide_slug, int $limit ): array {
|
private function query_by_taxonomy( string $peptide_slug, int $limit ): array {
|
||||||
$query = new WP_Query( [
|
$query = new WP_Query(
|
||||||
|
array(
|
||||||
'post_type' => 'post',
|
'post_type' => 'post',
|
||||||
'posts_per_page' => $limit,
|
'posts_per_page' => $limit,
|
||||||
'orderby' => 'date',
|
'orderby' => 'date',
|
||||||
'order' => 'DESC',
|
'order' => 'DESC',
|
||||||
'tax_query' => [
|
'tax_query' => array(
|
||||||
[
|
array(
|
||||||
'taxonomy' => 'peptide_topic',
|
'taxonomy' => 'peptide_topic',
|
||||||
'field' => 'slug',
|
'field' => 'slug',
|
||||||
'terms' => $peptide_slug,
|
'terms' => $peptide_slug,
|
||||||
],
|
),
|
||||||
],
|
),
|
||||||
] );
|
)
|
||||||
|
);
|
||||||
|
|
||||||
return $query->posts ?: [];
|
return $query->posts ?: array();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -89,14 +91,16 @@ class PR_Core_Internal_Posts_Provider implements PR_Core_Related_Posts_Provider
|
|||||||
* @return array<int, \WP_Post>
|
* @return array<int, \WP_Post>
|
||||||
*/
|
*/
|
||||||
private function query_by_search( string $search_term, int $limit ): array {
|
private function query_by_search( string $search_term, int $limit ): array {
|
||||||
$query = new WP_Query( [
|
$query = new WP_Query(
|
||||||
|
array(
|
||||||
'post_type' => 'post',
|
'post_type' => 'post',
|
||||||
'posts_per_page' => $limit,
|
'posts_per_page' => $limit,
|
||||||
'orderby' => 'date',
|
'orderby' => 'date',
|
||||||
'order' => 'DESC',
|
'order' => 'DESC',
|
||||||
's' => $search_term,
|
's' => $search_term,
|
||||||
] );
|
)
|
||||||
|
);
|
||||||
|
|
||||||
return $query->posts ?: [];
|
return $query->posts ?: array();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,8 +33,8 @@ class PR_Core_Related_Posts_Section {
|
|||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function register_hooks(): void {
|
public function register_hooks(): void {
|
||||||
add_action( 'pr_core_after_peptide_content', [ $this, 'render' ] );
|
add_action( 'pr_core_after_peptide_content', array( $this, 'render' ) );
|
||||||
add_action( 'save_post_post', [ $this, 'invalidate_caches' ] );
|
add_action( 'save_post_post', array( $this, 'invalidate_caches' ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -72,7 +72,7 @@ class PR_Core_Related_Posts_Section {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
setup_postdata( $post );
|
setup_postdata( $post );
|
||||||
get_template_part( 'template-parts/related-posts/card', null, [ 'post' => $post ] );
|
get_template_part( 'template-parts/related-posts/card', null, array( 'post' => $post ) );
|
||||||
++$count;
|
++$count;
|
||||||
}
|
}
|
||||||
wp_reset_postdata();
|
wp_reset_postdata();
|
||||||
|
|||||||
@@ -31,26 +31,26 @@ class PR_Core_Peptide_CPT {
|
|||||||
*
|
*
|
||||||
* @var string[]
|
* @var string[]
|
||||||
*/
|
*/
|
||||||
public const EVIDENCE_STRENGTHS = [
|
public const EVIDENCE_STRENGTHS = array(
|
||||||
'preclinical',
|
'preclinical',
|
||||||
'case-series',
|
'case-series',
|
||||||
'observational',
|
'observational',
|
||||||
'rct-small',
|
'rct-small',
|
||||||
'rct-large',
|
'rct-large',
|
||||||
'meta-analysis',
|
'meta-analysis',
|
||||||
];
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Editorial review status enum values.
|
* Editorial review status enum values.
|
||||||
*
|
*
|
||||||
* @var string[]
|
* @var string[]
|
||||||
*/
|
*/
|
||||||
public const REVIEW_STATUSES = [
|
public const REVIEW_STATUSES = array(
|
||||||
'draft',
|
'draft',
|
||||||
'in-review',
|
'in-review',
|
||||||
'published',
|
'published',
|
||||||
'retired',
|
'retired',
|
||||||
];
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Post-meta field definitions (1:1 with peptide).
|
* Post-meta field definitions (1:1 with peptide).
|
||||||
@@ -59,115 +59,115 @@ class PR_Core_Peptide_CPT {
|
|||||||
* @return array<string, array<string, mixed>>
|
* @return array<string, array<string, mixed>>
|
||||||
*/
|
*/
|
||||||
public static function get_meta_fields(): array {
|
public static function get_meta_fields(): array {
|
||||||
return [
|
return array(
|
||||||
'display_name' => [
|
'display_name' => array(
|
||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
'default' => '',
|
'default' => '',
|
||||||
'sanitize' => 'sanitize_text_field',
|
'sanitize' => 'sanitize_text_field',
|
||||||
],
|
),
|
||||||
'aliases' => [
|
'aliases' => array(
|
||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
'default' => '[]',
|
'default' => '[]',
|
||||||
'sanitize' => [ PR_Core_Schema_Sanitizers::class, 'sanitize_json_array' ],
|
'sanitize' => array( PR_Core_Schema_Sanitizers::class, 'sanitize_json_array' ),
|
||||||
],
|
),
|
||||||
'molecular_formula' => [
|
'molecular_formula' => array(
|
||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
'default' => '',
|
'default' => '',
|
||||||
'sanitize' => 'sanitize_text_field',
|
'sanitize' => 'sanitize_text_field',
|
||||||
],
|
),
|
||||||
'molecular_weight' => [
|
'molecular_weight' => array(
|
||||||
'type' => 'number',
|
'type' => 'number',
|
||||||
'default' => 0,
|
'default' => 0,
|
||||||
'sanitize' => 'floatval',
|
'sanitize' => 'floatval',
|
||||||
],
|
),
|
||||||
'cas_number' => [
|
'cas_number' => array(
|
||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
'default' => '',
|
'default' => '',
|
||||||
'sanitize' => 'sanitize_text_field',
|
'sanitize' => 'sanitize_text_field',
|
||||||
],
|
),
|
||||||
'drugbank_id' => [
|
'drugbank_id' => array(
|
||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
'default' => '',
|
'default' => '',
|
||||||
'sanitize' => 'sanitize_text_field',
|
'sanitize' => 'sanitize_text_field',
|
||||||
],
|
),
|
||||||
'chembl_id' => [
|
'chembl_id' => array(
|
||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
'default' => '',
|
'default' => '',
|
||||||
'sanitize' => 'sanitize_text_field',
|
'sanitize' => 'sanitize_text_field',
|
||||||
],
|
),
|
||||||
'evidence_strength' => [
|
'evidence_strength' => array(
|
||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
'default' => 'preclinical',
|
'default' => 'preclinical',
|
||||||
'sanitize' => [ __CLASS__, 'sanitize_evidence_strength' ],
|
'sanitize' => array( __CLASS__, 'sanitize_evidence_strength' ),
|
||||||
],
|
),
|
||||||
'editorial_review_status' => [
|
'editorial_review_status' => array(
|
||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
'default' => 'draft',
|
'default' => 'draft',
|
||||||
'sanitize' => [ __CLASS__, 'sanitize_review_status' ],
|
'sanitize' => array( __CLASS__, 'sanitize_review_status' ),
|
||||||
],
|
),
|
||||||
'last_editorial_review_at' => [
|
'last_editorial_review_at' => array(
|
||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
'default' => '',
|
'default' => '',
|
||||||
'sanitize' => 'sanitize_text_field',
|
'sanitize' => 'sanitize_text_field',
|
||||||
],
|
),
|
||||||
'medical_editor_id' => [
|
'medical_editor_id' => array(
|
||||||
'type' => 'integer',
|
'type' => 'integer',
|
||||||
'default' => 0,
|
'default' => 0,
|
||||||
'sanitize' => 'absint',
|
'sanitize' => 'absint',
|
||||||
],
|
),
|
||||||
'_pr_last_source_verified' => [
|
'_pr_last_source_verified' => array(
|
||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
'default' => '',
|
'default' => '',
|
||||||
'sanitize' => 'sanitize_text_field',
|
'sanitize' => 'sanitize_text_field',
|
||||||
],
|
),
|
||||||
'_pr_last_reviewed' => [
|
'_pr_last_reviewed' => array(
|
||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
'default' => '',
|
'default' => '',
|
||||||
'sanitize' => 'sanitize_text_field',
|
'sanitize' => 'sanitize_text_field',
|
||||||
],
|
),
|
||||||
'_pr_next_review_by' => [
|
'_pr_next_review_by' => array(
|
||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
'default' => '',
|
'default' => '',
|
||||||
'sanitize' => 'sanitize_text_field',
|
'sanitize' => 'sanitize_text_field',
|
||||||
],
|
),
|
||||||
'_pr_verification_velocity' => [
|
'_pr_verification_velocity' => array(
|
||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
'default' => 'medium',
|
'default' => 'medium',
|
||||||
'sanitize' => [ PR_Core_Verification_Sanitizers::class, 'sanitize_velocity' ],
|
'sanitize' => array( PR_Core_Verification_Sanitizers::class, 'sanitize_velocity' ),
|
||||||
],
|
),
|
||||||
'_pr_verification_notes' => [
|
'_pr_verification_notes' => array(
|
||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
'default' => '',
|
'default' => '',
|
||||||
'sanitize' => 'sanitize_textarea_field',
|
'sanitize' => 'sanitize_textarea_field',
|
||||||
],
|
),
|
||||||
'_pr_verification_status' => [
|
'_pr_verification_status' => array(
|
||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
'default' => 'current',
|
'default' => 'current',
|
||||||
'sanitize' => [ PR_Core_Verification_Sanitizers::class, 'sanitize_status' ],
|
'sanitize' => array( PR_Core_Verification_Sanitizers::class, 'sanitize_status' ),
|
||||||
],
|
),
|
||||||
// Schema-input meta (v0.6.0): molecular data sourced from PSA psa_* keys via migration 0004.
|
// Schema-input meta (v0.6.0): molecular data sourced from PSA psa_* keys via migration 0004.
|
||||||
'_pr_molecular_formula' => [
|
'_pr_molecular_formula' => array(
|
||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
'default' => '',
|
'default' => '',
|
||||||
'sanitize' => [ PR_Core_Schema_Sanitizers::class, 'sanitize_molecular_formula' ],
|
'sanitize' => array( PR_Core_Schema_Sanitizers::class, 'sanitize_molecular_formula' ),
|
||||||
],
|
),
|
||||||
'_pr_molecular_weight' => [
|
'_pr_molecular_weight' => array(
|
||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
'default' => '',
|
'default' => '',
|
||||||
'sanitize' => [ PR_Core_Schema_Sanitizers::class, 'sanitize_molecular_weight_string' ],
|
'sanitize' => array( PR_Core_Schema_Sanitizers::class, 'sanitize_molecular_weight_string' ),
|
||||||
],
|
),
|
||||||
'_pr_aliases' => [
|
'_pr_aliases' => array(
|
||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
'default' => '[]',
|
'default' => '[]',
|
||||||
'sanitize' => [ PR_Core_Schema_Sanitizers::class, 'sanitize_json_array' ],
|
'sanitize' => array( PR_Core_Schema_Sanitizers::class, 'sanitize_json_array' ),
|
||||||
],
|
),
|
||||||
// FAQ items (v0.6.0): [{question, answer}] JSON for FAQPage schema. Populated by CMO content sprint.
|
// FAQ items (v0.6.0): [{question, answer}] JSON for FAQPage schema. Populated by CMO content sprint.
|
||||||
'_pr_faq_items' => [
|
'_pr_faq_items' => array(
|
||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
'default' => '[]',
|
'default' => '[]',
|
||||||
'sanitize' => [ PR_Core_Schema_Sanitizers::class, 'sanitize_faq_items' ],
|
'sanitize' => array( PR_Core_Schema_Sanitizers::class, 'sanitize_faq_items' ),
|
||||||
],
|
),
|
||||||
];
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -176,9 +176,9 @@ class PR_Core_Peptide_CPT {
|
|||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function register_hooks(): void {
|
public function register_hooks(): void {
|
||||||
add_action( 'init', [ __CLASS__, 'register_peptide_post_type' ] );
|
add_action( 'init', array( __CLASS__, 'register_peptide_post_type' ) );
|
||||||
add_action( 'init', [ __CLASS__, 'register_taxonomies' ] );
|
add_action( 'init', array( __CLASS__, 'register_taxonomies' ) );
|
||||||
add_action( 'init', [ __CLASS__, 'register_meta_fields' ] );
|
add_action( 'init', array( __CLASS__, 'register_meta_fields' ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -193,7 +193,7 @@ class PR_Core_Peptide_CPT {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$labels = [
|
$labels = array(
|
||||||
'name' => __( 'Peptides', 'peptide-repo-core' ),
|
'name' => __( 'Peptides', 'peptide-repo-core' ),
|
||||||
'singular_name' => __( 'Peptide', 'peptide-repo-core' ),
|
'singular_name' => __( 'Peptide', 'peptide-repo-core' ),
|
||||||
'add_new_item' => __( 'Add New Peptide', 'peptide-repo-core' ),
|
'add_new_item' => __( 'Add New Peptide', 'peptide-repo-core' ),
|
||||||
@@ -205,11 +205,11 @@ class PR_Core_Peptide_CPT {
|
|||||||
'not_found_in_trash' => __( 'No peptides found in trash', 'peptide-repo-core' ),
|
'not_found_in_trash' => __( 'No peptides found in trash', 'peptide-repo-core' ),
|
||||||
'all_items' => __( 'All Peptides', 'peptide-repo-core' ),
|
'all_items' => __( 'All Peptides', 'peptide-repo-core' ),
|
||||||
'menu_name' => __( 'Peptides', 'peptide-repo-core' ),
|
'menu_name' => __( 'Peptides', 'peptide-repo-core' ),
|
||||||
];
|
);
|
||||||
|
|
||||||
// Args harmonized superset of PR Core + PSA for 89 existing posts.
|
// Args harmonized superset of PR Core + PSA for 89 existing posts.
|
||||||
// Supports union, capability/role perms preserved, slugs unchanged.
|
// Supports union, capability/role perms preserved, slugs unchanged.
|
||||||
$args = [
|
$args = array(
|
||||||
'labels' => $labels,
|
'labels' => $labels,
|
||||||
'public' => true,
|
'public' => true,
|
||||||
'publicly_queryable' => true,
|
'publicly_queryable' => true,
|
||||||
@@ -228,9 +228,12 @@ class PR_Core_Peptide_CPT {
|
|||||||
'map_meta_cap' => true,
|
'map_meta_cap' => true,
|
||||||
'hierarchical' => false,
|
'hierarchical' => false,
|
||||||
'has_archive' => true,
|
'has_archive' => true,
|
||||||
'rewrite' => [ 'slug' => 'peptides', 'with_front' => false ],
|
'rewrite' => array(
|
||||||
'supports' => [ 'title', 'editor', 'thumbnail', 'excerpt', 'revisions', 'custom-fields' ],
|
'slug' => 'peptides',
|
||||||
];
|
'with_front' => false,
|
||||||
|
),
|
||||||
|
'supports' => array( 'title', 'editor', 'thumbnail', 'excerpt', 'revisions', 'custom-fields' ),
|
||||||
|
);
|
||||||
register_post_type( self::POST_TYPE, $args );
|
register_post_type( self::POST_TYPE, $args );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,19 +249,26 @@ class PR_Core_Peptide_CPT {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
register_taxonomy( self::TAX_CATEGORY, self::POST_TYPE, [
|
register_taxonomy(
|
||||||
'labels' => [
|
self::TAX_CATEGORY,
|
||||||
|
self::POST_TYPE,
|
||||||
|
array(
|
||||||
|
'labels' => array(
|
||||||
'name' => __( 'Peptide Categories', 'peptide-repo-core' ),
|
'name' => __( 'Peptide Categories', 'peptide-repo-core' ),
|
||||||
'singular_name' => __( 'Peptide Category', 'peptide-repo-core' ),
|
'singular_name' => __( 'Peptide Category', 'peptide-repo-core' ),
|
||||||
],
|
),
|
||||||
'public' => true,
|
'public' => true,
|
||||||
'publicly_queryable' => true,
|
'publicly_queryable' => true,
|
||||||
'show_in_rest' => true,
|
'show_in_rest' => true,
|
||||||
'show_ui' => true,
|
'show_ui' => true,
|
||||||
'show_admin_column' => true,
|
'show_admin_column' => true,
|
||||||
'hierarchical' => true,
|
'hierarchical' => true,
|
||||||
'rewrite' => [ 'slug' => 'peptide-category', 'with_front' => false ],
|
'rewrite' => array(
|
||||||
] );
|
'slug' => 'peptide-category',
|
||||||
|
'with_front' => false,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -268,7 +278,10 @@ class PR_Core_Peptide_CPT {
|
|||||||
*/
|
*/
|
||||||
public static function register_meta_fields(): void {
|
public static function register_meta_fields(): void {
|
||||||
foreach ( self::get_meta_fields() as $key => $config ) {
|
foreach ( self::get_meta_fields() as $key => $config ) {
|
||||||
register_post_meta( self::POST_TYPE, $key, [
|
register_post_meta(
|
||||||
|
self::POST_TYPE,
|
||||||
|
$key,
|
||||||
|
array(
|
||||||
'type' => $config['type'],
|
'type' => $config['type'],
|
||||||
'single' => true,
|
'single' => true,
|
||||||
'default' => $config['default'],
|
'default' => $config['default'],
|
||||||
@@ -277,7 +290,8 @@ class PR_Core_Peptide_CPT {
|
|||||||
'auth_callback' => static function () {
|
'auth_callback' => static function () {
|
||||||
return current_user_can( self::CAPABILITY );
|
return current_user_can( self::CAPABILITY );
|
||||||
},
|
},
|
||||||
] );
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ class PR_Core_Repo_Daily_CPT {
|
|||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function register_hooks(): void {
|
public function register_hooks(): void {
|
||||||
add_action( 'init', [ __CLASS__, 'register_post_type' ] );
|
add_action( 'init', array( __CLASS__, 'register_post_type' ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -42,7 +42,7 @@ class PR_Core_Repo_Daily_CPT {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$labels = [
|
$labels = array(
|
||||||
'name' => __( 'Repo Daily', 'peptide-repo-core' ),
|
'name' => __( 'Repo Daily', 'peptide-repo-core' ),
|
||||||
'singular_name' => __( 'Repo Daily', 'peptide-repo-core' ),
|
'singular_name' => __( 'Repo Daily', 'peptide-repo-core' ),
|
||||||
'add_new_item' => __( 'Add New Article', 'peptide-repo-core' ),
|
'add_new_item' => __( 'Add New Article', 'peptide-repo-core' ),
|
||||||
@@ -54,9 +54,9 @@ class PR_Core_Repo_Daily_CPT {
|
|||||||
'not_found_in_trash' => __( 'No articles found in trash', 'peptide-repo-core' ),
|
'not_found_in_trash' => __( 'No articles found in trash', 'peptide-repo-core' ),
|
||||||
'all_items' => __( 'All Articles', 'peptide-repo-core' ),
|
'all_items' => __( 'All Articles', 'peptide-repo-core' ),
|
||||||
'menu_name' => __( 'Repo Daily', 'peptide-repo-core' ),
|
'menu_name' => __( 'Repo Daily', 'peptide-repo-core' ),
|
||||||
];
|
);
|
||||||
|
|
||||||
$args = [
|
$args = array(
|
||||||
'labels' => $labels,
|
'labels' => $labels,
|
||||||
'public' => true,
|
'public' => true,
|
||||||
'publicly_queryable' => true,
|
'publicly_queryable' => true,
|
||||||
@@ -71,9 +71,12 @@ class PR_Core_Repo_Daily_CPT {
|
|||||||
'map_meta_cap' => true,
|
'map_meta_cap' => true,
|
||||||
'hierarchical' => false,
|
'hierarchical' => false,
|
||||||
'has_archive' => true,
|
'has_archive' => true,
|
||||||
'rewrite' => [ 'slug' => 'daily', 'with_front' => false ],
|
'rewrite' => array(
|
||||||
'supports' => [ 'title', 'editor', 'excerpt', 'thumbnail', 'custom-fields' ],
|
'slug' => 'daily',
|
||||||
];
|
'with_front' => false,
|
||||||
|
),
|
||||||
|
'supports' => array( 'title', 'editor', 'excerpt', 'thumbnail', 'custom-fields' ),
|
||||||
|
);
|
||||||
|
|
||||||
register_post_type( self::POST_TYPE, $args );
|
register_post_type( self::POST_TYPE, $args );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ class PR_Core_Schema_Sanitizers {
|
|||||||
return '[]';
|
return '[]';
|
||||||
}
|
}
|
||||||
|
|
||||||
$clean = [];
|
$clean = array();
|
||||||
foreach ( $value as $item ) {
|
foreach ( $value as $item ) {
|
||||||
if ( ! is_array( $item ) ) {
|
if ( ! is_array( $item ) ) {
|
||||||
continue;
|
continue;
|
||||||
@@ -140,10 +140,10 @@ class PR_Core_Schema_Sanitizers {
|
|||||||
$question = sanitize_text_field( (string) ( $item['question'] ?? '' ) );
|
$question = sanitize_text_field( (string) ( $item['question'] ?? '' ) );
|
||||||
$answer = sanitize_textarea_field( (string) ( $item['answer'] ?? '' ) );
|
$answer = sanitize_textarea_field( (string) ( $item['answer'] ?? '' ) );
|
||||||
if ( '' !== $question && '' !== $answer ) {
|
if ( '' !== $question && '' !== $answer ) {
|
||||||
$clean[] = [
|
$clean[] = array(
|
||||||
'question' => $question,
|
'question' => $question,
|
||||||
'answer' => $answer,
|
'answer' => $answer,
|
||||||
];
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ class PR_Core_Topic_Taxonomy {
|
|||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function register_hooks(): void {
|
public function register_hooks(): void {
|
||||||
add_action( 'init', [ __CLASS__, 'register_topic_taxonomy' ] );
|
add_action( 'init', array( __CLASS__, 'register_topic_taxonomy' ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -45,18 +45,25 @@ class PR_Core_Topic_Taxonomy {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
register_taxonomy( self::TAX_TOPIC, 'post', [
|
register_taxonomy(
|
||||||
'labels' => [
|
self::TAX_TOPIC,
|
||||||
|
'post',
|
||||||
|
array(
|
||||||
|
'labels' => array(
|
||||||
'name' => __( 'Peptide Topics', 'peptide-repo-core' ),
|
'name' => __( 'Peptide Topics', 'peptide-repo-core' ),
|
||||||
'singular_name' => __( 'Peptide Topic', 'peptide-repo-core' ),
|
'singular_name' => __( 'Peptide Topic', 'peptide-repo-core' ),
|
||||||
],
|
),
|
||||||
'public' => true,
|
'public' => true,
|
||||||
'publicly_queryable' => true,
|
'publicly_queryable' => true,
|
||||||
'show_in_rest' => true,
|
'show_in_rest' => true,
|
||||||
'show_ui' => true,
|
'show_ui' => true,
|
||||||
'show_admin_column' => true,
|
'show_admin_column' => true,
|
||||||
'hierarchical' => false,
|
'hierarchical' => false,
|
||||||
'rewrite' => [ 'slug' => 'peptide-topic', 'with_front' => false ],
|
'rewrite' => array(
|
||||||
] );
|
'slug' => 'peptide-topic',
|
||||||
|
'with_front' => false,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ class PR_Core_Verification_Sanitizers {
|
|||||||
* @return string Valid enum value (low, medium, high).
|
* @return string Valid enum value (low, medium, high).
|
||||||
*/
|
*/
|
||||||
public static function sanitize_velocity( string $value ): string {
|
public static function sanitize_velocity( string $value ): string {
|
||||||
return in_array( $value, [ 'low', 'medium', 'high' ], true ) ? $value : 'medium';
|
return in_array( $value, array( 'low', 'medium', 'high' ), true ) ? $value : 'medium';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -29,6 +29,6 @@ class PR_Core_Verification_Sanitizers {
|
|||||||
* @return string Valid enum value (current, due, overdue).
|
* @return string Valid enum value (current, due, overdue).
|
||||||
*/
|
*/
|
||||||
public static function sanitize_status( string $value ): string {
|
public static function sanitize_status( string $value ): string {
|
||||||
return in_array( $value, [ 'current', 'due', 'overdue' ], true ) ? $value : 'current';
|
return in_array( $value, array( 'current', 'due', 'overdue' ), true ) ? $value : 'current';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ class PR_Core_Candidate_DTO {
|
|||||||
* @return array<string, mixed>
|
* @return array<string, mixed>
|
||||||
*/
|
*/
|
||||||
public function to_array(): array {
|
public function to_array(): array {
|
||||||
return [
|
return array(
|
||||||
'id' => $this->id,
|
'id' => $this->id,
|
||||||
'peptide_id' => $this->peptide_id,
|
'peptide_id' => $this->peptide_id,
|
||||||
'dose_min' => $this->dose_min,
|
'dose_min' => $this->dose_min,
|
||||||
@@ -90,6 +90,6 @@ class PR_Core_Candidate_DTO {
|
|||||||
'extraction_confidence' => $this->extraction_confidence,
|
'extraction_confidence' => $this->extraction_confidence,
|
||||||
'queue_status' => $this->queue_status,
|
'queue_status' => $this->queue_status,
|
||||||
'extracted_at' => $this->extracted_at,
|
'extracted_at' => $this->extracted_at,
|
||||||
];
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ class PR_Core_Dosing_Row_DTO {
|
|||||||
* @return array<string, mixed>
|
* @return array<string, mixed>
|
||||||
*/
|
*/
|
||||||
public function to_array(): array {
|
public function to_array(): array {
|
||||||
return [
|
return array(
|
||||||
'id' => $this->id,
|
'id' => $this->id,
|
||||||
'peptide_id' => $this->peptide_id,
|
'peptide_id' => $this->peptide_id,
|
||||||
'dose_min' => $this->dose_min,
|
'dose_min' => $this->dose_min,
|
||||||
@@ -99,6 +99,6 @@ class PR_Core_Dosing_Row_DTO {
|
|||||||
'notes' => $this->notes,
|
'notes' => $this->notes,
|
||||||
'source' => $this->source,
|
'source' => $this->source,
|
||||||
'added_at' => $this->added_at,
|
'added_at' => $this->added_at,
|
||||||
];
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ class PR_Core_Legal_Cell_DTO {
|
|||||||
* @return array<string, mixed>
|
* @return array<string, mixed>
|
||||||
*/
|
*/
|
||||||
public function to_array(): array {
|
public function to_array(): array {
|
||||||
return [
|
return array(
|
||||||
'id' => $this->id,
|
'id' => $this->id,
|
||||||
'peptide_id' => $this->peptide_id,
|
'peptide_id' => $this->peptide_id,
|
||||||
'country_code' => $this->country_code,
|
'country_code' => $this->country_code,
|
||||||
@@ -70,6 +70,6 @@ class PR_Core_Legal_Cell_DTO {
|
|||||||
'notes' => $this->notes,
|
'notes' => $this->notes,
|
||||||
'last_verified_at' => $this->last_verified_at,
|
'last_verified_at' => $this->last_verified_at,
|
||||||
'is_active' => $this->is_active(),
|
'is_active' => $this->is_active(),
|
||||||
];
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ class PR_Core_Peptide_DTO {
|
|||||||
$this->excerpt = (string) ( $data['excerpt'] ?? '' );
|
$this->excerpt = (string) ( $data['excerpt'] ?? '' );
|
||||||
$this->status = (string) ( $data['status'] ?? 'draft' );
|
$this->status = (string) ( $data['status'] ?? 'draft' );
|
||||||
$this->display_name = (string) ( $data['display_name'] ?? '' );
|
$this->display_name = (string) ( $data['display_name'] ?? '' );
|
||||||
$this->aliases = (array) ( $data['aliases'] ?? [] );
|
$this->aliases = (array) ( $data['aliases'] ?? array() );
|
||||||
$this->molecular_formula = (string) ( $data['molecular_formula'] ?? '' );
|
$this->molecular_formula = (string) ( $data['molecular_formula'] ?? '' );
|
||||||
$this->molecular_weight = (float) ( $data['molecular_weight'] ?? 0 );
|
$this->molecular_weight = (float) ( $data['molecular_weight'] ?? 0 );
|
||||||
$this->cas_number = (string) ( $data['cas_number'] ?? '' );
|
$this->cas_number = (string) ( $data['cas_number'] ?? '' );
|
||||||
@@ -57,8 +57,8 @@ class PR_Core_Peptide_DTO {
|
|||||||
$this->editorial_review_status = (string) ( $data['editorial_review_status'] ?? 'draft' );
|
$this->editorial_review_status = (string) ( $data['editorial_review_status'] ?? 'draft' );
|
||||||
$this->last_editorial_review_at = (string) ( $data['last_editorial_review_at'] ?? '' );
|
$this->last_editorial_review_at = (string) ( $data['last_editorial_review_at'] ?? '' );
|
||||||
$this->medical_editor_id = (int) ( $data['medical_editor_id'] ?? 0 );
|
$this->medical_editor_id = (int) ( $data['medical_editor_id'] ?? 0 );
|
||||||
$this->categories = (array) ( $data['categories'] ?? [] );
|
$this->categories = (array) ( $data['categories'] ?? array() );
|
||||||
$this->families = (array) ( $data['families'] ?? [] );
|
$this->families = (array) ( $data['families'] ?? array() );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -67,7 +67,7 @@ class PR_Core_Peptide_DTO {
|
|||||||
* @return array<string, mixed>
|
* @return array<string, mixed>
|
||||||
*/
|
*/
|
||||||
public function to_array(): array {
|
public function to_array(): array {
|
||||||
return [
|
return array(
|
||||||
'id' => $this->id,
|
'id' => $this->id,
|
||||||
'title' => $this->title,
|
'title' => $this->title,
|
||||||
'slug' => $this->slug,
|
'slug' => $this->slug,
|
||||||
@@ -86,6 +86,6 @@ class PR_Core_Peptide_DTO {
|
|||||||
'categories' => $this->categories,
|
'categories' => $this->categories,
|
||||||
'families' => $this->families,
|
'families' => $this->families,
|
||||||
'url' => get_permalink( $this->id ),
|
'url' => get_permalink( $this->id ),
|
||||||
];
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,13 +28,13 @@ class PR_Core_Disclaimer {
|
|||||||
*
|
*
|
||||||
* @var array<string, string>
|
* @var array<string, string>
|
||||||
*/
|
*/
|
||||||
private const DEFAULTS = [
|
private const DEFAULTS = array(
|
||||||
'dosing' => 'The dosing information presented here is compiled from published peer-reviewed literature and is provided for educational and research purposes only. It does not constitute medical advice, diagnosis, or treatment recommendations. Always consult a licensed healthcare professional before making any decisions based on this information.',
|
'dosing' => 'The dosing information presented here is compiled from published peer-reviewed literature and is provided for educational and research purposes only. It does not constitute medical advice, diagnosis, or treatment recommendations. Always consult a licensed healthcare professional before making any decisions based on this information.',
|
||||||
'legal' => 'Legal status information is compiled from publicly available regulatory texts and is current as of the last-verified date shown. Regulatory frameworks change frequently. This information does not constitute legal advice. Verify current regulations with the relevant regulatory authority in your jurisdiction before taking any action.',
|
'legal' => 'Legal status information is compiled from publicly available regulatory texts and is current as of the last-verified date shown. Regulatory frameworks change frequently. This information does not constitute legal advice. Verify current regulations with the relevant regulatory authority in your jurisdiction before taking any action.',
|
||||||
'reconstitution' => 'This calculator is provided for educational purposes only. Always verify your calculations independently and consult a licensed healthcare professional. The results are based on the inputs you provide and standard reconstitution mathematics.',
|
'reconstitution' => 'This calculator is provided for educational purposes only. Always verify your calculations independently and consult a licensed healthcare professional. The results are based on the inputs you provide and standard reconstitution mathematics.',
|
||||||
'ai-answer' => 'This response was generated by an AI system and may contain errors or omissions. All claims are grounded in the Peptide Repo corpus and cited sources where possible. This is not medical advice. Always verify information with primary sources and consult a licensed healthcare professional.',
|
'ai-answer' => 'This response was generated by an AI system and may contain errors or omissions. All claims are grounded in the Peptide Repo corpus and cited sources where possible. This is not medical advice. Always verify information with primary sources and consult a licensed healthcare professional.',
|
||||||
'general' => 'The information on this site is for educational and research purposes only. It is not intended as medical advice, diagnosis, or treatment. Always consult a licensed healthcare professional.',
|
'general' => 'The information on this site is for educational and research purposes only. It is not intended as medical advice, diagnosis, or treatment. Always consult a licensed healthcare professional.',
|
||||||
];
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register shortcode and any frontend hooks.
|
* Register shortcode and any frontend hooks.
|
||||||
@@ -42,7 +42,7 @@ class PR_Core_Disclaimer {
|
|||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function register_hooks(): void {
|
public function register_hooks(): void {
|
||||||
add_shortcode( 'pr_disclaimer', [ $this, 'shortcode_handler' ] );
|
add_shortcode( 'pr_disclaimer', array( $this, 'shortcode_handler' ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -52,7 +52,7 @@ class PR_Core_Disclaimer {
|
|||||||
* @return string Disclaimer HTML.
|
* @return string Disclaimer HTML.
|
||||||
*/
|
*/
|
||||||
public function shortcode_handler( $atts ): string {
|
public function shortcode_handler( $atts ): string {
|
||||||
$atts = shortcode_atts( [ 'surface' => 'general' ], $atts, 'pr_disclaimer' );
|
$atts = shortcode_atts( array( 'surface' => 'general' ), $atts, 'pr_disclaimer' );
|
||||||
return self::render( sanitize_text_field( $atts['surface'] ) );
|
return self::render( sanitize_text_field( $atts['surface'] ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,7 +81,7 @@ class PR_Core_Disclaimer {
|
|||||||
*/
|
*/
|
||||||
public static function get_disclaimer_text( string $surface ): string {
|
public static function get_disclaimer_text( string $surface ): string {
|
||||||
$custom = get_option( self::COPY_OPTION, '{}' );
|
$custom = get_option( self::COPY_OPTION, '{}' );
|
||||||
$copy = json_decode( $custom, true ) ?: [];
|
$copy = json_decode( $custom, true ) ?: array();
|
||||||
|
|
||||||
if ( ! empty( $copy[ $surface ] ) ) {
|
if ( ! empty( $copy[ $surface ] ) ) {
|
||||||
return (string) $copy[ $surface ];
|
return (string) $copy[ $surface ];
|
||||||
@@ -110,7 +110,7 @@ class PR_Core_Disclaimer {
|
|||||||
*/
|
*/
|
||||||
public static function update_disclaimer( string $surface, string $text ): void {
|
public static function update_disclaimer( string $surface, string $text ): void {
|
||||||
$custom = get_option( self::COPY_OPTION, '{}' );
|
$custom = get_option( self::COPY_OPTION, '{}' );
|
||||||
$copy = json_decode( $custom, true ) ?: [];
|
$copy = json_decode( $custom, true ) ?: array();
|
||||||
|
|
||||||
$copy[ sanitize_text_field( $surface ) ] = sanitize_textarea_field( $text );
|
$copy[ sanitize_text_field( $surface ) ] = sanitize_textarea_field( $text );
|
||||||
|
|
||||||
|
|||||||
@@ -38,12 +38,12 @@ class PR_Core_Jsonld_Drug {
|
|||||||
public function build( PR_Core_Peptide_DTO $peptide ): array {
|
public function build( PR_Core_Peptide_DTO $peptide ): array {
|
||||||
$permalink = get_permalink( $peptide->id );
|
$permalink = get_permalink( $peptide->id );
|
||||||
|
|
||||||
$node = [
|
$node = array(
|
||||||
'@type' => [ 'Drug', 'MolecularEntity' ],
|
'@type' => array( 'Drug', 'MolecularEntity' ),
|
||||||
'@id' => $permalink . '#drug',
|
'@id' => $permalink . '#drug',
|
||||||
'name' => $peptide->display_name ?: $peptide->title,
|
'name' => $peptide->display_name ?: $peptide->title,
|
||||||
'url' => $permalink,
|
'url' => $permalink,
|
||||||
];
|
);
|
||||||
|
|
||||||
if ( '' !== $peptide->excerpt ) {
|
if ( '' !== $peptide->excerpt ) {
|
||||||
$node['description'] = $peptide->excerpt;
|
$node['description'] = $peptide->excerpt;
|
||||||
@@ -64,11 +64,11 @@ class PR_Core_Jsonld_Drug {
|
|||||||
// molecularWeight: prefer _pr_molecular_weight, fall back to DTO field.
|
// molecularWeight: prefer _pr_molecular_weight, fall back to DTO field.
|
||||||
$weight = $this->get_weight( $peptide );
|
$weight = $this->get_weight( $peptide );
|
||||||
if ( $weight > 0.0 ) {
|
if ( $weight > 0.0 ) {
|
||||||
$node['molecularWeight'] = [
|
$node['molecularWeight'] = array(
|
||||||
'@type' => 'QuantitativeValue',
|
'@type' => 'QuantitativeValue',
|
||||||
'value' => $weight,
|
'value' => $weight,
|
||||||
'unitText' => self::UNIT_TEXT,
|
'unitText' => self::UNIT_TEXT,
|
||||||
];
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// External identifiers: CAS and DrugBank omitted in v0.6.0 (no source).
|
// External identifiers: CAS and DrugBank omitted in v0.6.0 (no source).
|
||||||
@@ -150,9 +150,9 @@ class PR_Core_Jsonld_Drug {
|
|||||||
* @return array<string, string>|null
|
* @return array<string, string>|null
|
||||||
*/
|
*/
|
||||||
private function build_legal_status(): ?array {
|
private function build_legal_status(): ?array {
|
||||||
return [
|
return array(
|
||||||
'@type' => 'DrugLegalStatus',
|
'@type' => 'DrugLegalStatus',
|
||||||
'description' => esc_html__( 'Not approved for human therapeutic use; supplied for laboratory research purposes only.', 'peptide-repo-core' ),
|
'description' => esc_html__( 'Not approved for human therapeutic use; supplied for laboratory research purposes only.', 'peptide-repo-core' ),
|
||||||
];
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,11 +34,11 @@ class PR_Core_Jsonld_Faq {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return array(
|
||||||
'@type' => 'FAQPage',
|
'@type' => 'FAQPage',
|
||||||
'@id' => $permalink . '#faq',
|
'@id' => $permalink . '#faq',
|
||||||
'mainEntity' => array_map( [ $this, 'build_question' ], $items ),
|
'mainEntity' => array_map( array( $this, 'build_question' ), $items ),
|
||||||
];
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -48,14 +48,14 @@ class PR_Core_Jsonld_Faq {
|
|||||||
* @return array<string, mixed> Schema.org Question node.
|
* @return array<string, mixed> Schema.org Question node.
|
||||||
*/
|
*/
|
||||||
private function build_question( array $item ): array {
|
private function build_question( array $item ): array {
|
||||||
return [
|
return array(
|
||||||
'@type' => 'Question',
|
'@type' => 'Question',
|
||||||
'name' => esc_html( $item['question'] ),
|
'name' => esc_html( $item['question'] ),
|
||||||
'acceptedAnswer' => [
|
'acceptedAnswer' => array(
|
||||||
'@type' => 'Answer',
|
'@type' => 'Answer',
|
||||||
'text' => esc_html( $item['answer'] ),
|
'text' => esc_html( $item['answer'] ),
|
||||||
],
|
),
|
||||||
];
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -71,16 +71,16 @@ class PR_Core_Jsonld_Faq {
|
|||||||
$raw = get_post_meta( $post_id, self::META_FAQ_ITEMS, true );
|
$raw = get_post_meta( $post_id, self::META_FAQ_ITEMS, true );
|
||||||
|
|
||||||
if ( ! is_string( $raw ) || '' === $raw ) {
|
if ( ! is_string( $raw ) || '' === $raw ) {
|
||||||
return [];
|
return array();
|
||||||
}
|
}
|
||||||
|
|
||||||
$decoded = json_decode( $raw, true );
|
$decoded = json_decode( $raw, true );
|
||||||
|
|
||||||
if ( ! is_array( $decoded ) || empty( $decoded ) ) {
|
if ( ! is_array( $decoded ) || empty( $decoded ) ) {
|
||||||
return [];
|
return array();
|
||||||
}
|
}
|
||||||
|
|
||||||
$valid = [];
|
$valid = array();
|
||||||
foreach ( $decoded as $item ) {
|
foreach ( $decoded as $item ) {
|
||||||
if ( ! is_array( $item ) ) {
|
if ( ! is_array( $item ) ) {
|
||||||
continue;
|
continue;
|
||||||
@@ -88,10 +88,10 @@ class PR_Core_Jsonld_Faq {
|
|||||||
$question = sanitize_text_field( (string) ( $item['question'] ?? '' ) );
|
$question = sanitize_text_field( (string) ( $item['question'] ?? '' ) );
|
||||||
$answer = sanitize_textarea_field( (string) ( $item['answer'] ?? '' ) );
|
$answer = sanitize_textarea_field( (string) ( $item['answer'] ?? '' ) );
|
||||||
if ( '' !== $question && '' !== $answer ) {
|
if ( '' !== $question && '' !== $answer ) {
|
||||||
$valid[] = [
|
$valid[] = array(
|
||||||
'question' => $question,
|
'question' => $question,
|
||||||
'answer' => $answer,
|
'answer' => $answer,
|
||||||
];
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ class PR_Core_Jsonld_Webpage {
|
|||||||
// Yoast may set @type as a plain string OR an array of strings.
|
// Yoast may set @type as a plain string OR an array of strings.
|
||||||
// Normalise to array so in_array() works regardless of shape.
|
// Normalise to array so in_array() works regardless of shape.
|
||||||
$raw_type = $piece['@type'] ?? '';
|
$raw_type = $piece['@type'] ?? '';
|
||||||
$types = is_array( $raw_type ) ? $raw_type : [ $raw_type ];
|
$types = is_array( $raw_type ) ? $raw_type : array( $raw_type );
|
||||||
|
|
||||||
if ( in_array( 'WebPage', $types, true ) || in_array( 'MedicalWebPage', $types, true ) ) {
|
if ( in_array( 'WebPage', $types, true ) || in_array( 'MedicalWebPage', $types, true ) ) {
|
||||||
foreach ( $enrichments as $key => $value ) {
|
foreach ( $enrichments as $key => $value ) {
|
||||||
@@ -97,7 +97,7 @@ class PR_Core_Jsonld_Webpage {
|
|||||||
* @return array<string, mixed> Enrichment fields to merge into the WebPage node.
|
* @return array<string, mixed> Enrichment fields to merge into the WebPage node.
|
||||||
*/
|
*/
|
||||||
private function build_webpage_enrichments( int $post_id ): array {
|
private function build_webpage_enrichments( int $post_id ): array {
|
||||||
$enrichments = [];
|
$enrichments = array();
|
||||||
|
|
||||||
// lastReviewed: prefer _pr_last_reviewed, fall back to _pr_last_source_verified,
|
// lastReviewed: prefer _pr_last_reviewed, fall back to _pr_last_source_verified,
|
||||||
// then post modified date.
|
// then post modified date.
|
||||||
@@ -118,27 +118,27 @@ class PR_Core_Jsonld_Webpage {
|
|||||||
if ( $editor_id > 0 ) {
|
if ( $editor_id > 0 ) {
|
||||||
$editor = get_userdata( $editor_id );
|
$editor = get_userdata( $editor_id );
|
||||||
if ( $editor ) {
|
if ( $editor ) {
|
||||||
$enrichments['reviewedBy'] = [
|
$enrichments['reviewedBy'] = array(
|
||||||
'@type' => 'Person',
|
'@type' => 'Person',
|
||||||
'name' => sanitize_text_field( $editor->display_name ),
|
'name' => sanitize_text_field( $editor->display_name ),
|
||||||
'url' => get_author_posts_url( $editor_id ),
|
'url' => get_author_posts_url( $editor_id ),
|
||||||
];
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! isset( $enrichments['reviewedBy'] ) ) {
|
if ( ! isset( $enrichments['reviewedBy'] ) ) {
|
||||||
$enrichments['reviewedBy'] = [
|
$enrichments['reviewedBy'] = array(
|
||||||
'@type' => 'Organization',
|
'@type' => 'Organization',
|
||||||
'name' => 'Peptide Repo',
|
'name' => 'Peptide Repo',
|
||||||
'url' => home_url(),
|
'url' => home_url(),
|
||||||
];
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// audience: MedicalAudience for researchers.
|
// audience: MedicalAudience for researchers.
|
||||||
$enrichments['audience'] = [
|
$enrichments['audience'] = array(
|
||||||
'@type' => 'MedicalAudience',
|
'@type' => 'MedicalAudience',
|
||||||
'audienceType' => 'Researcher',
|
'audienceType' => 'Researcher',
|
||||||
];
|
);
|
||||||
|
|
||||||
return $enrichments;
|
return $enrichments;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ declare(strict_types=1);
|
|||||||
*
|
*
|
||||||
* What: Integrates Drug, MedicalWebPage, and FAQPage schema into Yoast's graph
|
* What: Integrates Drug, MedicalWebPage, and FAQPage schema into Yoast's graph
|
||||||
* on single peptide pages. When Yoast is inactive, emits a standalone
|
* on single peptide pages. When Yoast is inactive, emits a standalone
|
||||||
|
*
|
||||||
* @graph block via wp_head as a fallback.
|
* @graph block via wp_head as a fallback.
|
||||||
*
|
*
|
||||||
* Who calls it: PR_Core::init() calls register_hooks(). Yoast hooks fire on
|
* Who calls it: PR_Core::init() calls register_hooks(). Yoast hooks fire on
|
||||||
@@ -67,7 +68,7 @@ class PR_Core_Jsonld {
|
|||||||
*/
|
*/
|
||||||
public function register_hooks(): void {
|
public function register_hooks(): void {
|
||||||
// wpseo_schema_webpage_type: retype WebPage -> MedicalWebPage on peptide singles.
|
// wpseo_schema_webpage_type: retype WebPage -> MedicalWebPage on peptide singles.
|
||||||
add_filter( 'wpseo_schema_webpage_type', [ $this->webpage_enricher, 'retype_to_medical_webpage' ] );
|
add_filter( 'wpseo_schema_webpage_type', array( $this->webpage_enricher, 'retype_to_medical_webpage' ) );
|
||||||
|
|
||||||
// wpseo_schema_graph: two callbacks at different priorities.
|
// wpseo_schema_graph: two callbacks at different priorities.
|
||||||
// Priority 11 -- enrich_webpage_piece: merge lastReviewed/reviewedBy/audience into the
|
// Priority 11 -- enrich_webpage_piece: merge lastReviewed/reviewedBy/audience into the
|
||||||
@@ -75,11 +76,11 @@ class PR_Core_Jsonld {
|
|||||||
// Priority 12 -- inject_graph_nodes: append Drug + FAQPage arrays to the graph.
|
// Priority 12 -- inject_graph_nodes: append Drug + FAQPage arrays to the graph.
|
||||||
// Must run after enrich_webpage_piece so the WebPage node is already
|
// Must run after enrich_webpage_piece so the WebPage node is already
|
||||||
// enriched before Drug/FAQ are appended.
|
// enriched before Drug/FAQ are appended.
|
||||||
add_filter( 'wpseo_schema_graph', [ $this->webpage_enricher, 'enrich_webpage_piece' ], 11, 2 );
|
add_filter( 'wpseo_schema_graph', array( $this->webpage_enricher, 'enrich_webpage_piece' ), 11, 2 );
|
||||||
add_filter( 'wpseo_schema_graph', [ $this, 'inject_graph_nodes' ], 12, 2 );
|
add_filter( 'wpseo_schema_graph', array( $this, 'inject_graph_nodes' ), 12, 2 );
|
||||||
|
|
||||||
// Standalone fallback: emits only when Yoast is not producing output.
|
// Standalone fallback: emits only when Yoast is not producing output.
|
||||||
add_action( 'wp_head', [ $this, 'emit_standalone_fallback' ], 99 );
|
add_action( 'wp_head', array( $this, 'emit_standalone_fallback' ), 99 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -150,7 +151,7 @@ class PR_Core_Jsonld {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$permalink = get_permalink( (int) $post_id );
|
$permalink = get_permalink( (int) $post_id );
|
||||||
$graph = [ $this->drug_builder->build( $peptide ) ];
|
$graph = array( $this->drug_builder->build( $peptide ) );
|
||||||
|
|
||||||
$faq_node = $this->faq_builder->build( (int) $post_id, $permalink );
|
$faq_node = $this->faq_builder->build( (int) $post_id, $permalink );
|
||||||
if ( null !== $faq_node ) {
|
if ( null !== $faq_node ) {
|
||||||
@@ -160,7 +161,10 @@ class PR_Core_Jsonld {
|
|||||||
printf(
|
printf(
|
||||||
'<script type="application/ld+json">%s</script>' . "\n",
|
'<script type="application/ld+json">%s</script>' . "\n",
|
||||||
wp_json_encode(
|
wp_json_encode(
|
||||||
[ '@context' => 'https://schema.org', '@graph' => $graph ],
|
array(
|
||||||
|
'@context' => 'https://schema.org',
|
||||||
|
'@graph' => $graph,
|
||||||
|
),
|
||||||
JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT
|
JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ class PR_Core_Verification_Display {
|
|||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public static function init(): void {
|
public static function init(): void {
|
||||||
add_filter( 'the_content', [ __CLASS__, 'append_verification_display' ], 20 );
|
add_filter( 'the_content', array( __CLASS__, 'append_verification_display' ), 20 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -15,14 +15,14 @@ declare(strict_types=1);
|
|||||||
class PR_Core_Migration_0002_Legal_Cells {
|
class PR_Core_Migration_0002_Legal_Cells {
|
||||||
|
|
||||||
/** @var string[] Valid legal status enum values. */
|
/** @var string[] Valid legal status enum values. */
|
||||||
public const STATUSES = [
|
public const STATUSES = array(
|
||||||
'prescription',
|
'prescription',
|
||||||
'ruo',
|
'ruo',
|
||||||
'otc',
|
'otc',
|
||||||
'restricted',
|
'restricted',
|
||||||
'banned',
|
'banned',
|
||||||
'unclear',
|
'unclear',
|
||||||
];
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create the pr_legal_cells table.
|
* Create the pr_legal_cells table.
|
||||||
@@ -61,7 +61,7 @@ class PR_Core_Migration_0002_Legal_Cells {
|
|||||||
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
|
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
|
||||||
$index_exists = $wpdb->get_var(
|
$index_exists = $wpdb->get_var(
|
||||||
$wpdb->prepare(
|
$wpdb->prepare(
|
||||||
"SELECT COUNT(*) FROM information_schema.STATISTICS WHERE TABLE_SCHEMA = %s AND TABLE_NAME = %s AND INDEX_NAME = %s",
|
'SELECT COUNT(*) FROM information_schema.STATISTICS WHERE TABLE_SCHEMA = %s AND TABLE_NAME = %s AND INDEX_NAME = %s',
|
||||||
DB_NAME,
|
DB_NAME,
|
||||||
$table,
|
$table,
|
||||||
'uq_peptide_country_active'
|
'uq_peptide_country_active'
|
||||||
|
|||||||
@@ -16,12 +16,12 @@ declare(strict_types=1);
|
|||||||
class PR_Core_Migration_0003_Candidate_Queue {
|
class PR_Core_Migration_0003_Candidate_Queue {
|
||||||
|
|
||||||
/** @var string[] Valid queue status enum values. */
|
/** @var string[] Valid queue status enum values. */
|
||||||
public const STATUSES = [
|
public const STATUSES = array(
|
||||||
'pending',
|
'pending',
|
||||||
'approved',
|
'approved',
|
||||||
'rejected',
|
'rejected',
|
||||||
'merged',
|
'merged',
|
||||||
];
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create the pr_ai_candidate_queue table.
|
* Create the pr_ai_candidate_queue table.
|
||||||
|
|||||||
@@ -66,20 +66,27 @@ class PR_Core_Migration_0004_Backfill_Peptide_Meta {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$counts = [ 'skipped' => 0, 'copied_psa' => 0, 'pubchem_ok' => 0, 'pubchem_skip' => 0 ];
|
$counts = array(
|
||||||
|
'skipped' => 0,
|
||||||
|
'copied_psa' => 0,
|
||||||
|
'pubchem_ok' => 0,
|
||||||
|
'pubchem_skip' => 0,
|
||||||
|
);
|
||||||
|
|
||||||
foreach ( $peptide_ids as $post_id ) {
|
foreach ( $peptide_ids as $post_id ) {
|
||||||
$result = $this->backfill_post( $post_id );
|
$result = $this->backfill_post( $post_id );
|
||||||
$counts[ $result ] += 1;
|
$counts[ $result ] += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
error_log( sprintf(
|
error_log(
|
||||||
|
sprintf(
|
||||||
'[PR Core Migration 0004] Complete. Skipped: %d, PSA-copied: %d, PubChem-ok: %d, PubChem-skip: %d',
|
'[PR Core Migration 0004] Complete. Skipped: %d, PSA-copied: %d, PubChem-ok: %d, PubChem-skip: %d',
|
||||||
$counts['skipped'],
|
$counts['skipped'],
|
||||||
$counts['copied_psa'],
|
$counts['copied_psa'],
|
||||||
$counts['pubchem_ok'],
|
$counts['pubchem_ok'],
|
||||||
$counts['pubchem_skip']
|
$counts['pubchem_skip']
|
||||||
) );
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -125,26 +132,30 @@ class PR_Core_Migration_0004_Backfill_Peptide_Meta {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ( null === $data ) {
|
if ( null === $data ) {
|
||||||
error_log( sprintf(
|
error_log(
|
||||||
|
sprintf(
|
||||||
'[PR Core Migration 0004] Post ID %d (%s): PubChem returned no data — leaving meta empty.',
|
'[PR Core Migration 0004] Post ID %d (%s): PubChem returned no data — leaving meta empty.',
|
||||||
$post_id,
|
$post_id,
|
||||||
esc_html( $name )
|
esc_html( $name )
|
||||||
) );
|
)
|
||||||
|
);
|
||||||
return 'pubchem_skip';
|
return 'pubchem_skip';
|
||||||
}
|
}
|
||||||
|
|
||||||
$formula = PR_Core_Schema_Sanitizers::sanitize_molecular_formula( $data['formula'] );
|
$formula = PR_Core_Schema_Sanitizers::sanitize_molecular_formula( $data['formula'] );
|
||||||
$weight = (float) $data['weight'];
|
$weight = (float) $data['weight'];
|
||||||
$aliases_json = $this->synonyms_to_json( $data['synonyms'] ?? [] );
|
$aliases_json = $this->synonyms_to_json( $data['synonyms'] ?? array() );
|
||||||
$this->write_pr_meta( $post_id, $formula, $weight, $aliases_json );
|
$this->write_pr_meta( $post_id, $formula, $weight, $aliases_json );
|
||||||
|
|
||||||
error_log( sprintf(
|
error_log(
|
||||||
|
sprintf(
|
||||||
'[PR Core Migration 0004] Post ID %d (%s): PubChem-sourced formula=%s weight=%s',
|
'[PR Core Migration 0004] Post ID %d (%s): PubChem-sourced formula=%s weight=%s',
|
||||||
$post_id,
|
$post_id,
|
||||||
esc_html( $name ),
|
esc_html( $name ),
|
||||||
$formula,
|
$formula,
|
||||||
(string) $weight
|
(string) $weight
|
||||||
) );
|
)
|
||||||
|
);
|
||||||
|
|
||||||
return 'pubchem_ok';
|
return 'pubchem_ok';
|
||||||
}
|
}
|
||||||
@@ -223,7 +234,7 @@ class PR_Core_Migration_0004_Backfill_Peptide_Meta {
|
|||||||
return '[]';
|
return '[]';
|
||||||
}
|
}
|
||||||
|
|
||||||
$clean = [];
|
$clean = array();
|
||||||
foreach ( explode( ',', $value ) as $part ) {
|
foreach ( explode( ',', $value ) as $part ) {
|
||||||
$alias = sanitize_text_field( trim( $part ) );
|
$alias = sanitize_text_field( trim( $part ) );
|
||||||
if ( '' !== $alias ) {
|
if ( '' !== $alias ) {
|
||||||
@@ -243,7 +254,7 @@ class PR_Core_Migration_0004_Backfill_Peptide_Meta {
|
|||||||
* @return string JSON array of sanitized strings.
|
* @return string JSON array of sanitized strings.
|
||||||
*/
|
*/
|
||||||
private function synonyms_to_json( array $synonyms ): string {
|
private function synonyms_to_json( array $synonyms ): string {
|
||||||
$clean = [];
|
$clean = array();
|
||||||
foreach ( $synonyms as $syn ) {
|
foreach ( $synonyms as $syn ) {
|
||||||
$alias = sanitize_text_field( (string) $syn );
|
$alias = sanitize_text_field( (string) $syn );
|
||||||
if ( '' !== $alias ) {
|
if ( '' !== $alias ) {
|
||||||
@@ -259,12 +270,14 @@ class PR_Core_Migration_0004_Backfill_Peptide_Meta {
|
|||||||
* @return int[]
|
* @return int[]
|
||||||
*/
|
*/
|
||||||
private function get_all_peptide_ids(): array {
|
private function get_all_peptide_ids(): array {
|
||||||
$posts = get_posts( [
|
$posts = get_posts(
|
||||||
|
array(
|
||||||
'post_type' => PR_Core_Peptide_CPT::POST_TYPE,
|
'post_type' => PR_Core_Peptide_CPT::POST_TYPE,
|
||||||
'post_status' => 'publish',
|
'post_status' => 'publish',
|
||||||
'posts_per_page' => -1,
|
'posts_per_page' => -1,
|
||||||
'fields' => 'ids',
|
'fields' => 'ids',
|
||||||
] );
|
)
|
||||||
return array_map( 'intval', is_array( $posts ) ? $posts : [] );
|
);
|
||||||
|
return array_map( 'intval', is_array( $posts ) ? $posts : array() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,12 +25,12 @@ class PR_Core_Migration_Runner {
|
|||||||
*
|
*
|
||||||
* @var string[]
|
* @var string[]
|
||||||
*/
|
*/
|
||||||
private const MIGRATIONS = [
|
private const MIGRATIONS = array(
|
||||||
'PR_Core_Migration_0001_Dosing_Rows',
|
'PR_Core_Migration_0001_Dosing_Rows',
|
||||||
'PR_Core_Migration_0002_Legal_Cells',
|
'PR_Core_Migration_0002_Legal_Cells',
|
||||||
'PR_Core_Migration_0003_Candidate_Queue',
|
'PR_Core_Migration_0003_Candidate_Queue',
|
||||||
'PR_Core_Migration_0004_Backfill_Peptide_Meta',
|
'PR_Core_Migration_0004_Backfill_Peptide_Meta',
|
||||||
];
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Run all pending migrations up to PR_CORE_TARGET_SCHEMA_VERSION.
|
* Run all pending migrations up to PR_CORE_TARGET_SCHEMA_VERSION.
|
||||||
|
|||||||
@@ -109,11 +109,11 @@ class PR_Core_Pubchem_Client {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return array(
|
||||||
'formula' => $formula,
|
'formula' => $formula,
|
||||||
'weight' => $weight,
|
'weight' => $weight,
|
||||||
'cid' => $cid,
|
'cid' => $cid,
|
||||||
];
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -130,14 +130,14 @@ class PR_Core_Pubchem_Client {
|
|||||||
$body = $this->get_with_retry( $url );
|
$body = $this->get_with_retry( $url );
|
||||||
|
|
||||||
if ( null === $body ) {
|
if ( null === $body ) {
|
||||||
return [];
|
return array();
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = json_decode( $body, true );
|
$data = json_decode( $body, true );
|
||||||
$synonyms = $data['InformationList']['Information'][0]['Synonym'] ?? [];
|
$synonyms = $data['InformationList']['Information'][0]['Synonym'] ?? array();
|
||||||
|
|
||||||
if ( ! is_array( $synonyms ) ) {
|
if ( ! is_array( $synonyms ) ) {
|
||||||
return [];
|
return array();
|
||||||
}
|
}
|
||||||
|
|
||||||
return array_slice( $synonyms, 0, self::MAX_SYNONYMS );
|
return array_slice( $synonyms, 0, self::MAX_SYNONYMS );
|
||||||
@@ -176,10 +176,13 @@ class PR_Core_Pubchem_Client {
|
|||||||
*/
|
*/
|
||||||
private function get_once( string $url ): ?string {
|
private function get_once( string $url ): ?string {
|
||||||
if ( function_exists( 'wp_remote_get' ) ) {
|
if ( function_exists( 'wp_remote_get' ) ) {
|
||||||
$response = wp_remote_get( $url, [
|
$response = wp_remote_get(
|
||||||
|
$url,
|
||||||
|
array(
|
||||||
'timeout' => self::TIMEOUT,
|
'timeout' => self::TIMEOUT,
|
||||||
'headers' => [ 'Accept' => 'application/json' ],
|
'headers' => array( 'Accept' => 'application/json' ),
|
||||||
] );
|
)
|
||||||
|
);
|
||||||
|
|
||||||
if ( is_wp_error( $response ) ) {
|
if ( is_wp_error( $response ) ) {
|
||||||
return null;
|
return null;
|
||||||
@@ -194,13 +197,15 @@ class PR_Core_Pubchem_Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// WP-CLI / plain PHP fallback.
|
// WP-CLI / plain PHP fallback.
|
||||||
$context = stream_context_create( [
|
$context = stream_context_create(
|
||||||
'http' => [
|
array(
|
||||||
|
'http' => array(
|
||||||
'timeout' => self::TIMEOUT,
|
'timeout' => self::TIMEOUT,
|
||||||
'header' => "Accept: application/json\r\n",
|
'header' => "Accept: application/json\r\n",
|
||||||
'method' => 'GET',
|
'method' => 'GET',
|
||||||
],
|
),
|
||||||
] );
|
)
|
||||||
|
);
|
||||||
|
|
||||||
$body = @file_get_contents( $url, false, $context );
|
$body = @file_get_contents( $url, false, $context );
|
||||||
return ( false === $body ) ? null : $body;
|
return ( false === $body ) ? null : $body;
|
||||||
|
|||||||
@@ -47,8 +47,8 @@ class PR_Core_Candidate_Queue_Repository {
|
|||||||
global $wpdb;
|
global $wpdb;
|
||||||
$table = $wpdb->prefix . 'pr_ai_candidate_queue';
|
$table = $wpdb->prefix . 'pr_ai_candidate_queue';
|
||||||
|
|
||||||
$where = [ 'queue_status = %s' ];
|
$where = array( 'queue_status = %s' );
|
||||||
$params = [ sanitize_text_field( $status ) ];
|
$params = array( sanitize_text_field( $status ) );
|
||||||
|
|
||||||
if ( $peptide_id > 0 ) {
|
if ( $peptide_id > 0 ) {
|
||||||
$where[] = 'peptide_id = %d';
|
$where[] = 'peptide_id = %d';
|
||||||
@@ -65,7 +65,7 @@ class PR_Core_Candidate_Queue_Repository {
|
|||||||
...$params
|
...$params
|
||||||
),
|
),
|
||||||
ARRAY_A
|
ARRAY_A
|
||||||
) ?: [];
|
) ?: array();
|
||||||
|
|
||||||
return array_map(
|
return array_map(
|
||||||
static fn( array $row ) => new PR_Core_Candidate_DTO( $row ),
|
static fn( array $row ) => new PR_Core_Candidate_DTO( $row ),
|
||||||
@@ -85,7 +85,7 @@ class PR_Core_Candidate_Queue_Repository {
|
|||||||
global $wpdb;
|
global $wpdb;
|
||||||
$table = $wpdb->prefix . 'pr_ai_candidate_queue';
|
$table = $wpdb->prefix . 'pr_ai_candidate_queue';
|
||||||
|
|
||||||
$row = [
|
$row = array(
|
||||||
'peptide_id' => absint( $data['peptide_id'] ?? 0 ),
|
'peptide_id' => absint( $data['peptide_id'] ?? 0 ),
|
||||||
'dose_min' => isset( $data['dose_min'] ) ? (float) $data['dose_min'] : null,
|
'dose_min' => isset( $data['dose_min'] ) ? (float) $data['dose_min'] : null,
|
||||||
'dose_max' => isset( $data['dose_max'] ) ? (float) $data['dose_max'] : null,
|
'dose_max' => isset( $data['dose_max'] ) ? (float) $data['dose_max'] : null,
|
||||||
@@ -106,7 +106,7 @@ class PR_Core_Candidate_Queue_Repository {
|
|||||||
'extraction_confidence' => (float) ( $data['extraction_confidence'] ?? 0 ),
|
'extraction_confidence' => (float) ( $data['extraction_confidence'] ?? 0 ),
|
||||||
'queue_status' => 'pending',
|
'queue_status' => 'pending',
|
||||||
'extracted_at' => current_time( 'mysql' ),
|
'extracted_at' => current_time( 'mysql' ),
|
||||||
];
|
);
|
||||||
|
|
||||||
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
|
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
|
||||||
$result = $wpdb->insert( $table, $row );
|
$result = $wpdb->insert( $table, $row );
|
||||||
@@ -134,7 +134,8 @@ class PR_Core_Candidate_Queue_Repository {
|
|||||||
|
|
||||||
// Copy candidate data into a dosing row.
|
// Copy candidate data into a dosing row.
|
||||||
$dosing_repo = new PR_Core_Dosing_Repository();
|
$dosing_repo = new PR_Core_Dosing_Repository();
|
||||||
$dosing_id = $dosing_repo->insert( [
|
$dosing_id = $dosing_repo->insert(
|
||||||
|
array(
|
||||||
'peptide_id' => $candidate->peptide_id,
|
'peptide_id' => $candidate->peptide_id,
|
||||||
'dose_min' => $candidate->dose_min,
|
'dose_min' => $candidate->dose_min,
|
||||||
'dose_max' => $candidate->dose_max,
|
'dose_max' => $candidate->dose_max,
|
||||||
@@ -157,7 +158,8 @@ class PR_Core_Candidate_Queue_Repository {
|
|||||||
'added_by' => $reviewer_id,
|
'added_by' => $reviewer_id,
|
||||||
'reviewed_by' => $reviewer_id,
|
'reviewed_by' => $reviewer_id,
|
||||||
'reviewed_at' => current_time( 'mysql' ),
|
'reviewed_at' => current_time( 'mysql' ),
|
||||||
] );
|
)
|
||||||
|
);
|
||||||
|
|
||||||
if ( 0 === $dosing_id ) {
|
if ( 0 === $dosing_id ) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -224,15 +226,15 @@ class PR_Core_Candidate_Queue_Repository {
|
|||||||
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
|
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
|
||||||
$result = $wpdb->update(
|
$result = $wpdb->update(
|
||||||
$table,
|
$table,
|
||||||
[
|
array(
|
||||||
'queue_status' => sanitize_text_field( $status ),
|
'queue_status' => sanitize_text_field( $status ),
|
||||||
'reviewed_by' => $reviewer_id,
|
'reviewed_by' => $reviewer_id,
|
||||||
'reviewed_at' => current_time( 'mysql' ),
|
'reviewed_at' => current_time( 'mysql' ),
|
||||||
'reviewer_notes' => sanitize_textarea_field( $notes ),
|
'reviewer_notes' => sanitize_textarea_field( $notes ),
|
||||||
],
|
),
|
||||||
[ 'id' => $id ],
|
array( 'id' => $id ),
|
||||||
[ '%s', '%d', '%s', '%s' ],
|
array( '%s', '%d', '%s', '%s' ),
|
||||||
[ '%d' ]
|
array( '%d' )
|
||||||
);
|
);
|
||||||
|
|
||||||
return false !== $result;
|
return false !== $result;
|
||||||
|
|||||||
@@ -39,12 +39,12 @@ class PR_Core_Dosing_Repository {
|
|||||||
* @param array<string, mixed> $filters Optional: route, population, evidence_strength.
|
* @param array<string, mixed> $filters Optional: route, population, evidence_strength.
|
||||||
* @return PR_Core_Dosing_Row_DTO[]
|
* @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;
|
global $wpdb;
|
||||||
$table = $wpdb->prefix . 'pr_dosing_rows';
|
$table = $wpdb->prefix . 'pr_dosing_rows';
|
||||||
|
|
||||||
$where = [ 'peptide_id = %d', 'superseded_by_id IS NULL' ];
|
$where = array( 'peptide_id = %d', 'superseded_by_id IS NULL' );
|
||||||
$params = [ $peptide_id ];
|
$params = array( $peptide_id );
|
||||||
|
|
||||||
if ( ! empty( $filters['route'] ) ) {
|
if ( ! empty( $filters['route'] ) ) {
|
||||||
$where[] = 'route = %s';
|
$where[] = 'route = %s';
|
||||||
@@ -70,7 +70,7 @@ class PR_Core_Dosing_Repository {
|
|||||||
...$params
|
...$params
|
||||||
),
|
),
|
||||||
ARRAY_A
|
ARRAY_A
|
||||||
) ?: [];
|
) ?: array();
|
||||||
|
|
||||||
return array_map(
|
return array_map(
|
||||||
static fn( array $row ) => new PR_Core_Dosing_Row_DTO( $row ),
|
static fn( array $row ) => new PR_Core_Dosing_Row_DTO( $row ),
|
||||||
@@ -137,10 +137,10 @@ class PR_Core_Dosing_Repository {
|
|||||||
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
|
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
|
||||||
$wpdb->update(
|
$wpdb->update(
|
||||||
$table,
|
$table,
|
||||||
[ 'superseded_by_id' => $new_id ],
|
array( 'superseded_by_id' => $new_id ),
|
||||||
[ 'id' => $old_id ],
|
array( 'id' => $old_id ),
|
||||||
[ '%d' ],
|
array( '%d' ),
|
||||||
[ '%d' ]
|
array( '%d' )
|
||||||
);
|
);
|
||||||
|
|
||||||
return $new_id;
|
return $new_id;
|
||||||
@@ -172,7 +172,7 @@ class PR_Core_Dosing_Repository {
|
|||||||
* @return array<string, mixed> Sanitized row.
|
* @return array<string, mixed> Sanitized row.
|
||||||
*/
|
*/
|
||||||
private function sanitize_row( array $data ): array {
|
private function sanitize_row( array $data ): array {
|
||||||
return [
|
return array(
|
||||||
'peptide_id' => absint( $data['peptide_id'] ?? 0 ),
|
'peptide_id' => absint( $data['peptide_id'] ?? 0 ),
|
||||||
'dose_min' => isset( $data['dose_min'] ) ? (float) $data['dose_min'] : null,
|
'dose_min' => isset( $data['dose_min'] ) ? (float) $data['dose_min'] : null,
|
||||||
'dose_max' => isset( $data['dose_max'] ) ? (float) $data['dose_max'] : null,
|
'dose_max' => isset( $data['dose_max'] ) ? (float) $data['dose_max'] : null,
|
||||||
@@ -195,6 +195,6 @@ class PR_Core_Dosing_Repository {
|
|||||||
'added_by' => absint( $data['added_by'] ?? get_current_user_id() ),
|
'added_by' => absint( $data['added_by'] ?? get_current_user_id() ),
|
||||||
'reviewed_by' => isset( $data['reviewed_by'] ) ? absint( $data['reviewed_by'] ) : null,
|
'reviewed_by' => isset( $data['reviewed_by'] ) ? absint( $data['reviewed_by'] ) : null,
|
||||||
'reviewed_at' => $data['reviewed_at'] ?? null,
|
'reviewed_at' => $data['reviewed_at'] ?? null,
|
||||||
];
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ class PR_Core_Legal_Repository {
|
|||||||
$peptide_id
|
$peptide_id
|
||||||
),
|
),
|
||||||
ARRAY_A
|
ARRAY_A
|
||||||
) ?: [];
|
) ?: array();
|
||||||
|
|
||||||
return array_map(
|
return array_map(
|
||||||
static fn( array $row ) => new PR_Core_Legal_Cell_DTO( $row ),
|
static fn( array $row ) => new PR_Core_Legal_Cell_DTO( $row ),
|
||||||
@@ -101,7 +101,7 @@ class PR_Core_Legal_Repository {
|
|||||||
strtoupper( sanitize_text_field( $country_code ) )
|
strtoupper( sanitize_text_field( $country_code ) )
|
||||||
),
|
),
|
||||||
ARRAY_A
|
ARRAY_A
|
||||||
) ?: [];
|
) ?: array();
|
||||||
|
|
||||||
return array_map(
|
return array_map(
|
||||||
static fn( array $row ) => new PR_Core_Legal_Cell_DTO( $row ),
|
static fn( array $row ) => new PR_Core_Legal_Cell_DTO( $row ),
|
||||||
@@ -161,10 +161,10 @@ class PR_Core_Legal_Repository {
|
|||||||
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
|
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
|
||||||
$wpdb->update(
|
$wpdb->update(
|
||||||
$table,
|
$table,
|
||||||
[ 'superseded_by_id' => $new_id ],
|
array( 'superseded_by_id' => $new_id ),
|
||||||
[ 'id' => $old_id ],
|
array( 'id' => $old_id ),
|
||||||
[ '%d' ],
|
array( '%d' ),
|
||||||
[ '%d' ]
|
array( '%d' )
|
||||||
);
|
);
|
||||||
|
|
||||||
return $new_id;
|
return $new_id;
|
||||||
@@ -184,7 +184,7 @@ class PR_Core_Legal_Repository {
|
|||||||
$status = 'unclear';
|
$status = 'unclear';
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return array(
|
||||||
'peptide_id' => absint( $data['peptide_id'] ?? 0 ),
|
'peptide_id' => absint( $data['peptide_id'] ?? 0 ),
|
||||||
'country_code' => strtoupper( sanitize_text_field( $data['country_code'] ?? '' ) ),
|
'country_code' => strtoupper( sanitize_text_field( $data['country_code'] ?? '' ) ),
|
||||||
'status' => $status,
|
'status' => $status,
|
||||||
@@ -195,6 +195,6 @@ class PR_Core_Legal_Repository {
|
|||||||
'last_verified_at' => sanitize_text_field( $data['last_verified_at'] ?? current_time( 'mysql' ) ),
|
'last_verified_at' => sanitize_text_field( $data['last_verified_at'] ?? current_time( 'mysql' ) ),
|
||||||
'schema_version' => 1,
|
'schema_version' => 1,
|
||||||
'reviewer_id' => absint( $data['reviewer_id'] ?? get_current_user_id() ),
|
'reviewer_id' => absint( $data['reviewer_id'] ?? get_current_user_id() ),
|
||||||
];
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,12 +36,14 @@ class PR_Core_Peptide_Repository {
|
|||||||
* @return PR_Core_Peptide_DTO|null
|
* @return PR_Core_Peptide_DTO|null
|
||||||
*/
|
*/
|
||||||
public function find_by_slug( string $slug ): ?PR_Core_Peptide_DTO {
|
public function find_by_slug( string $slug ): ?PR_Core_Peptide_DTO {
|
||||||
$posts = get_posts( [
|
$posts = get_posts(
|
||||||
|
array(
|
||||||
'post_type' => PR_Core_Peptide_CPT::POST_TYPE,
|
'post_type' => PR_Core_Peptide_CPT::POST_TYPE,
|
||||||
'name' => sanitize_title( $slug ),
|
'name' => sanitize_title( $slug ),
|
||||||
'posts_per_page' => 1,
|
'posts_per_page' => 1,
|
||||||
'post_status' => 'any',
|
'post_status' => 'any',
|
||||||
] );
|
)
|
||||||
|
);
|
||||||
|
|
||||||
return ! empty( $posts ) ? $this->post_to_dto( $posts[0] ) : null;
|
return ! empty( $posts ) ? $this->post_to_dto( $posts[0] ) : null;
|
||||||
}
|
}
|
||||||
@@ -56,14 +58,16 @@ class PR_Core_Peptide_Repository {
|
|||||||
public function search( string $query, int $limit = 20 ): array {
|
public function search( string $query, int $limit = 20 ): array {
|
||||||
$query = sanitize_text_field( $query );
|
$query = sanitize_text_field( $query );
|
||||||
|
|
||||||
$posts = get_posts( [
|
$posts = get_posts(
|
||||||
|
array(
|
||||||
'post_type' => PR_Core_Peptide_CPT::POST_TYPE,
|
'post_type' => PR_Core_Peptide_CPT::POST_TYPE,
|
||||||
's' => $query,
|
's' => $query,
|
||||||
'posts_per_page' => $limit,
|
'posts_per_page' => $limit,
|
||||||
'post_status' => 'publish',
|
'post_status' => 'publish',
|
||||||
] );
|
)
|
||||||
|
);
|
||||||
|
|
||||||
return array_map( [ $this, 'post_to_dto' ], $posts );
|
return array_map( array( $this, 'post_to_dto' ), $posts );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -73,23 +77,25 @@ class PR_Core_Peptide_Repository {
|
|||||||
* evidence_strength, per_page, page.
|
* evidence_strength, per_page, page.
|
||||||
* @return PR_Core_Peptide_DTO[]
|
* @return PR_Core_Peptide_DTO[]
|
||||||
*/
|
*/
|
||||||
public function find_all( array $filters = [] ): array {
|
public function find_all( array $filters = array() ): array {
|
||||||
$args = [
|
$args = array(
|
||||||
'post_type' => PR_Core_Peptide_CPT::POST_TYPE,
|
'post_type' => PR_Core_Peptide_CPT::POST_TYPE,
|
||||||
'posts_per_page' => (int) ( $filters['per_page'] ?? 100 ),
|
'posts_per_page' => (int) ( $filters['per_page'] ?? 100 ),
|
||||||
'paged' => (int) ( $filters['page'] ?? 1 ),
|
'paged' => (int) ( $filters['page'] ?? 1 ),
|
||||||
'orderby' => 'title',
|
'orderby' => 'title',
|
||||||
'order' => 'ASC',
|
'order' => 'ASC',
|
||||||
];
|
);
|
||||||
|
|
||||||
$args['post_status'] = $filters['status'] ?? 'publish';
|
$args['post_status'] = $filters['status'] ?? 'publish';
|
||||||
|
|
||||||
if ( ! empty( $filters['category'] ) ) {
|
if ( ! empty( $filters['category'] ) ) {
|
||||||
$args['tax_query'] = [ [
|
$args['tax_query'] = array(
|
||||||
|
array(
|
||||||
'taxonomy' => PR_Core_Peptide_CPT::TAX_CATEGORY,
|
'taxonomy' => PR_Core_Peptide_CPT::TAX_CATEGORY,
|
||||||
'field' => 'slug',
|
'field' => 'slug',
|
||||||
'terms' => sanitize_text_field( $filters['category'] ),
|
'terms' => sanitize_text_field( $filters['category'] ),
|
||||||
] ];
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// v0.2.0: `family` filter silently ignored — `pr_peptide_family` taxonomy
|
// v0.2.0: `family` filter silently ignored — `pr_peptide_family` taxonomy
|
||||||
@@ -98,15 +104,17 @@ class PR_Core_Peptide_Repository {
|
|||||||
// REST schema in a future minor bump.
|
// REST schema in a future minor bump.
|
||||||
|
|
||||||
if ( ! empty( $filters['evidence_strength'] ) ) {
|
if ( ! empty( $filters['evidence_strength'] ) ) {
|
||||||
$args['meta_query'] = [ [
|
$args['meta_query'] = array(
|
||||||
|
array(
|
||||||
'key' => 'evidence_strength',
|
'key' => 'evidence_strength',
|
||||||
'value' => sanitize_text_field( $filters['evidence_strength'] ),
|
'value' => sanitize_text_field( $filters['evidence_strength'] ),
|
||||||
] ];
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$posts = get_posts( $args );
|
$posts = get_posts( $args );
|
||||||
|
|
||||||
return array_map( [ $this, 'post_to_dto' ], $posts );
|
return array_map( array( $this, 'post_to_dto' ), $posts );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -128,15 +136,16 @@ class PR_Core_Peptide_Repository {
|
|||||||
*/
|
*/
|
||||||
private function post_to_dto( \WP_Post $post ): PR_Core_Peptide_DTO {
|
private function post_to_dto( \WP_Post $post ): PR_Core_Peptide_DTO {
|
||||||
$aliases_raw = get_post_meta( $post->ID, 'aliases', true );
|
$aliases_raw = get_post_meta( $post->ID, 'aliases', true );
|
||||||
$aliases = json_decode( $aliases_raw ?: '[]', true ) ?: [];
|
$aliases = json_decode( $aliases_raw ?: '[]', true ) ?: array();
|
||||||
|
|
||||||
$categories = wp_get_post_terms( $post->ID, PR_Core_Peptide_CPT::TAX_CATEGORY, [ 'fields' => 'names' ] );
|
$categories = wp_get_post_terms( $post->ID, PR_Core_Peptide_CPT::TAX_CATEGORY, array( 'fields' => 'names' ) );
|
||||||
// v0.2.0: `pr_peptide_family` taxonomy removed. DTO `families` field
|
// v0.2.0: `pr_peptide_family` taxonomy removed. DTO `families` field
|
||||||
// preserved as empty array to keep the REST response shape stable for
|
// preserved as empty array to keep the REST response shape stable for
|
||||||
// clients; will be dropped in a future minor bump with a release note.
|
// clients; will be dropped in a future minor bump with a release note.
|
||||||
$families = [];
|
$families = array();
|
||||||
|
|
||||||
return new PR_Core_Peptide_DTO( [
|
return new PR_Core_Peptide_DTO(
|
||||||
|
array(
|
||||||
'id' => $post->ID,
|
'id' => $post->ID,
|
||||||
'title' => $post->post_title,
|
'title' => $post->post_title,
|
||||||
'slug' => $post->post_name,
|
'slug' => $post->post_name,
|
||||||
@@ -154,8 +163,9 @@ class PR_Core_Peptide_Repository {
|
|||||||
'editorial_review_status' => get_post_meta( $post->ID, 'editorial_review_status', true ) ?: 'draft',
|
'editorial_review_status' => get_post_meta( $post->ID, 'editorial_review_status', true ) ?: 'draft',
|
||||||
'last_editorial_review_at' => get_post_meta( $post->ID, 'last_editorial_review_at', true ) ?: '',
|
'last_editorial_review_at' => get_post_meta( $post->ID, 'last_editorial_review_at', true ) ?: '',
|
||||||
'medical_editor_id' => (int) get_post_meta( $post->ID, 'medical_editor_id', true ),
|
'medical_editor_id' => (int) get_post_meta( $post->ID, 'medical_editor_id', true ),
|
||||||
'categories' => is_array( $categories ) ? $categories : [],
|
'categories' => is_array( $categories ) ? $categories : array(),
|
||||||
'families' => $families,
|
'families' => $families,
|
||||||
] );
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,10 +29,10 @@ class PR_Core_Verification_Scanner {
|
|||||||
*/
|
*/
|
||||||
public static function run_scan(): void {
|
public static function run_scan(): void {
|
||||||
$repo = new PR_Core_Peptide_Repository();
|
$repo = new PR_Core_Peptide_Repository();
|
||||||
$peptides = $repo->find_all( [ 'status' => 'publish' ] );
|
$peptides = $repo->find_all( array( 'status' => 'publish' ) );
|
||||||
|
|
||||||
$due_peptides = [];
|
$due_peptides = array();
|
||||||
$overdue_peptides = [];
|
$overdue_peptides = array();
|
||||||
|
|
||||||
foreach ( $peptides as $dto ) {
|
foreach ( $peptides as $dto ) {
|
||||||
$last_verified = get_post_meta( $dto->id, '_pr_last_source_verified', true );
|
$last_verified = get_post_meta( $dto->id, '_pr_last_source_verified', true );
|
||||||
@@ -102,17 +102,17 @@ class PR_Core_Verification_Scanner {
|
|||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
private static function log_scan( int $total, int $due, int $overdue ): void {
|
private static function log_scan( int $total, int $due, int $overdue ): void {
|
||||||
$log = get_option( self::SCAN_LOG_OPTION_KEY, [] );
|
$log = get_option( self::SCAN_LOG_OPTION_KEY, array() );
|
||||||
if ( ! is_array( $log ) ) {
|
if ( ! is_array( $log ) ) {
|
||||||
$log = [];
|
$log = array();
|
||||||
}
|
}
|
||||||
|
|
||||||
$log[] = [
|
$log[] = array(
|
||||||
'timestamp' => current_time( 'mysql' ),
|
'timestamp' => current_time( 'mysql' ),
|
||||||
'total' => $total,
|
'total' => $total,
|
||||||
'due' => $due,
|
'due' => $due,
|
||||||
'overdue' => $overdue,
|
'overdue' => $overdue,
|
||||||
];
|
);
|
||||||
|
|
||||||
// Keep only the last MAX_LOG_ENTRIES.
|
// Keep only the last MAX_LOG_ENTRIES.
|
||||||
if ( count( $log ) > self::MAX_LOG_ENTRIES ) {
|
if ( count( $log ) > self::MAX_LOG_ENTRIES ) {
|
||||||
@@ -137,9 +137,12 @@ class PR_Core_Verification_Scanner {
|
|||||||
|
|
||||||
// Parse comma-separated emails.
|
// Parse comma-separated emails.
|
||||||
$emails = array_map( 'trim', explode( ',', $recipients ) );
|
$emails = array_map( 'trim', explode( ',', $recipients ) );
|
||||||
$emails = array_filter( $emails, static function ( $email ) {
|
$emails = array_filter(
|
||||||
|
$emails,
|
||||||
|
static function ( $email ) {
|
||||||
return is_email( $email );
|
return is_email( $email );
|
||||||
} );
|
}
|
||||||
|
);
|
||||||
|
|
||||||
if ( empty( $emails ) ) {
|
if ( empty( $emails ) ) {
|
||||||
return;
|
return;
|
||||||
@@ -153,7 +156,7 @@ class PR_Core_Verification_Scanner {
|
|||||||
|
|
||||||
$body = self::build_email_body( $due_peptides, $overdue_peptides );
|
$body = self::build_email_body( $due_peptides, $overdue_peptides );
|
||||||
|
|
||||||
wp_mail( $emails, $subject, $body, [ 'Content-Type: text/html; charset=UTF-8' ] );
|
wp_mail( $emails, $subject, $body, array( 'Content-Type: text/html; charset=UTF-8' ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ class PR_Core_Repo_Daily_Taxonomy {
|
|||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function register_hooks(): void {
|
public function register_hooks(): void {
|
||||||
add_action( 'init', [ __CLASS__, 'register_taxonomy' ] );
|
add_action( 'init', array( __CLASS__, 'register_taxonomy' ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -41,19 +41,26 @@ class PR_Core_Repo_Daily_Taxonomy {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
register_taxonomy( self::TAX_CATEGORY, PR_Core_Repo_Daily_CPT::POST_TYPE, [
|
register_taxonomy(
|
||||||
'labels' => [
|
self::TAX_CATEGORY,
|
||||||
|
PR_Core_Repo_Daily_CPT::POST_TYPE,
|
||||||
|
array(
|
||||||
|
'labels' => array(
|
||||||
'name' => __( 'Category', 'peptide-repo-core' ),
|
'name' => __( 'Category', 'peptide-repo-core' ),
|
||||||
'singular_name' => __( 'Category', 'peptide-repo-core' ),
|
'singular_name' => __( 'Category', 'peptide-repo-core' ),
|
||||||
],
|
),
|
||||||
'public' => true,
|
'public' => true,
|
||||||
'publicly_queryable' => true,
|
'publicly_queryable' => true,
|
||||||
'show_in_rest' => true,
|
'show_in_rest' => true,
|
||||||
'show_ui' => true,
|
'show_ui' => true,
|
||||||
'show_admin_column' => true,
|
'show_admin_column' => true,
|
||||||
'hierarchical' => false,
|
'hierarchical' => false,
|
||||||
'rewrite' => [ 'slug' => 'daily/category', 'with_front' => false ],
|
'rewrite' => array(
|
||||||
] );
|
'slug' => 'daily/category',
|
||||||
|
'with_front' => false,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -67,7 +74,7 @@ class PR_Core_Repo_Daily_Taxonomy {
|
|||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public static function seed_terms(): void {
|
public static function seed_terms(): void {
|
||||||
$terms = [ 'article', 'guide', 'comparison', 'news' ];
|
$terms = array( 'article', 'guide', 'comparison', 'news' );
|
||||||
|
|
||||||
foreach ( $terms as $term ) {
|
foreach ( $terms as $term ) {
|
||||||
if ( ! term_exists( $term, self::TAX_CATEGORY ) ) {
|
if ( ! term_exists( $term, self::TAX_CATEGORY ) ) {
|
||||||
|
|||||||
@@ -40,12 +40,15 @@ require_once PR_CORE_PLUGIN_DIR . 'includes/class-pr-core.php';
|
|||||||
|
|
||||||
/* ── Activation / Deactivation ────────────────────────────────────────── */
|
/* ── Activation / Deactivation ────────────────────────────────────────── */
|
||||||
|
|
||||||
register_activation_hook( __FILE__, [ 'PR_Core_Activator', 'activate' ] );
|
register_activation_hook( __FILE__, array( 'PR_Core_Activator', 'activate' ) );
|
||||||
register_deactivation_hook( __FILE__, [ 'PR_Core_Deactivator', 'deactivate' ] );
|
register_deactivation_hook( __FILE__, array( 'PR_Core_Deactivator', 'deactivate' ) );
|
||||||
|
|
||||||
/* ── Boot ──────────────────────────────────────────────────────────────── */
|
/* ── Boot ──────────────────────────────────────────────────────────────── */
|
||||||
|
|
||||||
add_action( 'plugins_loaded', static function (): void {
|
add_action(
|
||||||
|
'plugins_loaded',
|
||||||
|
static function (): void {
|
||||||
$plugin = new PR_Core();
|
$plugin = new PR_Core();
|
||||||
$plugin->init();
|
$plugin->init();
|
||||||
} );
|
}
|
||||||
|
);
|
||||||
|
|||||||
@@ -24,11 +24,11 @@ $post = $args['post'];
|
|||||||
get_the_post_thumbnail(
|
get_the_post_thumbnail(
|
||||||
$post,
|
$post,
|
||||||
'post-thumbnail',
|
'post-thumbnail',
|
||||||
[
|
array(
|
||||||
'class' => 'pr-related-posts__image-element',
|
'class' => 'pr-related-posts__image-element',
|
||||||
'loading' => 'lazy',
|
'loading' => 'lazy',
|
||||||
'decoding' => 'async',
|
'decoding' => 'async',
|
||||||
]
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
?>
|
?>
|
||||||
|
|||||||
@@ -18,11 +18,11 @@ global $wpdb;
|
|||||||
|
|
||||||
/* ── 1. Drop custom tables ────────────────────────────────────────────── */
|
/* ── 1. Drop custom tables ────────────────────────────────────────────── */
|
||||||
|
|
||||||
$tables = [
|
$tables = array(
|
||||||
$wpdb->prefix . 'pr_dosing_rows',
|
$wpdb->prefix . 'pr_dosing_rows',
|
||||||
$wpdb->prefix . 'pr_legal_cells',
|
$wpdb->prefix . 'pr_legal_cells',
|
||||||
$wpdb->prefix . 'pr_ai_candidate_queue',
|
$wpdb->prefix . 'pr_ai_candidate_queue',
|
||||||
];
|
);
|
||||||
|
|
||||||
foreach ( $tables as $table ) {
|
foreach ( $tables as $table ) {
|
||||||
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.SchemaChange
|
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.SchemaChange
|
||||||
@@ -85,19 +85,19 @@ $wpdb->query(
|
|||||||
*
|
*
|
||||||
* @see ARCHITECTURE.md — §2.9 Uninstall specification.
|
* @see ARCHITECTURE.md — §2.9 Uninstall specification.
|
||||||
*/
|
*/
|
||||||
$schema_meta_keys = [
|
$schema_meta_keys = array(
|
||||||
'_pr_molecular_formula',
|
'_pr_molecular_formula',
|
||||||
'_pr_molecular_weight',
|
'_pr_molecular_weight',
|
||||||
'_pr_aliases',
|
'_pr_aliases',
|
||||||
'_pr_faq_items',
|
'_pr_faq_items',
|
||||||
];
|
);
|
||||||
|
|
||||||
foreach ( $schema_meta_keys as $meta_key ) {
|
foreach ( $schema_meta_keys as $meta_key ) {
|
||||||
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
|
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
|
||||||
$wpdb->delete(
|
$wpdb->delete(
|
||||||
$wpdb->postmeta,
|
$wpdb->postmeta,
|
||||||
[ 'meta_key' => $meta_key ],
|
array( 'meta_key' => $meta_key ),
|
||||||
[ '%s' ]
|
array( '%s' )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user