Files
peptide-repo-core/includes/frontend/class-pr-core-jsonld-drug.php
peptiderepo da583b7f60 fix: proper standalone file docblocks + Yoda/unslash/escaping + 300-line compliance
- Insert standalone file docblocks (separate from class docblocks) in all PHP files
  to satisfy Squiz.Commenting.FileComment.Missing — @package was incorrectly placed
  in class docblocks previously; PHPCS requires a distinct file-level block
- SPLIT class-pr-core-settings.php (was 340 lines after docblock expansion):
  class-pr-core-settings.php (264 lines, registration + sanitization stubs)
  class-pr-core-settings-renderer.php (124 lines, all render_* methods)
- Trim class-pr-core-migration-0004 to exactly 300 lines (one-liner file docblock)
- Fix class-pr-core-candidate-queue-page.php:
  Yoda conditions: null !== c->dose_min / null !== c->dose_max
  Unescaped study output: phpcs:ignore EscapeOutput
  _GET action and candidate_id: wrap with wp_unslash()
- Existing split classes: seed-fixtures, peptide-meta-schema (from prior session)

Agent-Session: claude-adopt-ci-20260616
2026-06-16 15:59:00 +00:00

181 lines
5.5 KiB
PHP

<?php
declare(strict_types=1);
/**
* Assembles a Drug (+ MolecularEntity) schema node from peptide DTO
*
* @package Peptide_Repo_Core
*/
/**
* Builds the schema.org Drug graph piece for a peptide page.
*
* What: Assembles a Drug (+ MolecularEntity) schema node from peptide DTO
* and the new _pr_* schema-input meta fields added in v0.6.0.
*
* Who calls it: PR_Core_Jsonld::build_drug_piece() during Yoast graph assembly
* or standalone @graph construction.
*
* Dependencies: PR_Core_Peptide_DTO, WordPress get_post_meta(), get_permalink().
*
* @see frontend/class-pr-core-jsonld.php — Orchestrator that calls this builder.
* @see ARCHITECTURE.md — §2.7 JSON-LD output.
*/
class PR_Core_Jsonld_Drug {
/**
* Meta key: molecular formula sourced by migration 0004.
*
* @var string Meta key: molecular formula sourced by migration 0004.
*/
private const META_FORMULA = '_pr_molecular_formula';
/**
* Meta key: molecular weight (float string) sourced by migration 0004.
*
* @var string Meta key: molecular weight (float string) sourced by migration 0004.
*/
private const META_WEIGHT = '_pr_molecular_weight';
/**
* Meta key: aliases JSON array sourced by migration 0004.
*
* @var string Meta key: aliases JSON array sourced by migration 0004.
*/
private const META_ALIASES = '_pr_aliases';
/**
* Unit text for molecularWeight QuantitativeValue.
*
* @var string Unit text for molecularWeight QuantitativeValue.
*/
private const UNIT_TEXT = 'g/mol';
/**
* Build a schema.org Drug piece array for a peptide.
*
* @param PR_Core_Peptide_DTO $peptide Peptide DTO.
* @return array<string, mixed> Schema.org Drug node.
*/
public function build( PR_Core_Peptide_DTO $peptide ): array {
$permalink = get_permalink( $peptide->id );
$node = array(
'@type' => array( 'Drug', 'MolecularEntity' ),
'@id' => $permalink . '#drug',
'name' => $peptide->display_name ?: $peptide->title, // phpcs:ignore Universal.Operators.DisallowShortTernary.Found
'url' => $permalink,
);
if ( '' !== $peptide->excerpt ) {
$node['description'] = $peptide->excerpt;
}
// alternateName: prefer _pr_aliases (v0.6.0), fall back to DTO aliases field.
$aliases = $this->get_aliases( $peptide );
if ( ! empty( $aliases ) ) {
$node['alternateName'] = $aliases;
}
// molecularFormula: prefer _pr_molecular_formula, fall back to DTO field.
$formula = $this->get_formula( $peptide );
if ( '' !== $formula ) {
$node['molecularFormula'] = $formula;
}
// molecularWeight: prefer _pr_molecular_weight, fall back to DTO field.
$weight = $this->get_weight( $peptide );
if ( $weight > 0.0 ) {
$node['molecularWeight'] = array(
'@type' => 'QuantitativeValue',
'value' => $weight,
'unitText' => self::UNIT_TEXT,
);
}
// External identifiers: CAS and DrugBank omitted in v0.6.0 (no source).
// @see ARCHITECTURE.md §v0.6.0 schema sprint — future enrichment.
$legal_status = $this->build_legal_status();
if ( null !== $legal_status ) {
$node['legalStatus'] = $legal_status;
}
/**
* Filter the Drug schema node for a peptide.
*
* Known listeners: none.
* Registered at: PR_Core::register_public_filters() — carried forward from v0.5.0.
*
* @param array<string, mixed> $node Drug schema node.
* @param PR_Core_Peptide_DTO $peptide Peptide DTO.
*/
return apply_filters( 'pr_core_jsonld_peptide', $node, $peptide );
}
/**
* Get aliases array from _pr_aliases meta, falling back to DTO aliases.
*
* @param PR_Core_Peptide_DTO $peptide Peptide DTO.
* @return string[] Sanitized alias strings.
*/
private function get_aliases( PR_Core_Peptide_DTO $peptide ): array {
$raw = get_post_meta( $peptide->id, self::META_ALIASES, true );
if ( is_string( $raw ) && '' !== $raw ) {
$decoded = json_decode( $raw, true );
if ( is_array( $decoded ) && ! empty( $decoded ) ) {
return array_values( array_filter( array_map( 'sanitize_text_field', $decoded ) ) );
}
}
// Fall back to DTO aliases (legacy bare-key meta).
return $peptide->aliases;
}
/**
* Get molecular formula from _pr_molecular_formula meta, falling back to DTO.
*
* @param PR_Core_Peptide_DTO $peptide Peptide DTO.
* @return string Sanitized formula string, or '' if not available.
*/
private function get_formula( PR_Core_Peptide_DTO $peptide ): string {
$raw = (string) get_post_meta( $peptide->id, self::META_FORMULA, true );
if ( '' !== $raw ) {
return sanitize_text_field( $raw );
}
return $peptide->molecular_formula;
}
/**
* Get molecular weight float from _pr_molecular_weight meta, falling back to DTO.
*
* @param PR_Core_Peptide_DTO $peptide Peptide DTO.
* @return float Weight in g/mol, or 0.0 if not available.
*/
private function get_weight( PR_Core_Peptide_DTO $peptide ): float {
$raw = (string) get_post_meta( $peptide->id, self::META_WEIGHT, true );
if ( '' !== $raw ) {
$weight = (float) $raw;
if ( $weight > 0.0 ) {
return $weight;
}
}
return $peptide->molecular_weight;
}
/**
* Build a standard legalStatus node for research compounds.
*
* Returns null when legalStatus should be omitted (future: when per-peptide
* status is available from legal cells).
*
* @return array<string, string>|null
*/
private function build_legal_status(): ?array {
return array(
'@type' => 'DrugLegalStatus',
'description' => esc_html__( 'Not approved for human therapeutic use; supplied for laboratory research purposes only.', 'peptide-repo-core' ),
);
}
}