refactor: extract PSA_Directory_API from PSA_Directory (317→114+159)
REST endpoint registration, compounds query, and compound formatting moved to PSA_Directory_API. PSA_Directory retains shortcode rendering, constants, and hook registration. Backward-compatible proxies. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
159
includes/class-psa-directory-api.php
Normal file
159
includes/class-psa-directory-api.php
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* REST API endpoint for the browsable peptide directory.
|
||||||
|
*
|
||||||
|
* What: GET /v1/compounds — paginated, filterable compound listing with basic/full field sets.
|
||||||
|
* Who calls it: PSA_Directory::init() registers the REST route; frontend JS fetches data.
|
||||||
|
* Dependencies: PSA_Post_Type (meta fields, taxonomy), PSA_Directory (constants).
|
||||||
|
*
|
||||||
|
* @package PeptideSearchAI
|
||||||
|
* @since 4.5.0
|
||||||
|
* @see includes/class-psa-directory.php — Shortcode rendering, hook registration.
|
||||||
|
* @see assets/js/psa-directory.js — Frontend grid, filter, modal logic.
|
||||||
|
*/
|
||||||
|
declare( strict_types=1 );
|
||||||
|
|
||||||
|
if ( ! defined( 'ABSPATH' ) ) {
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
class PSA_Directory_API {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register the /v1/compounds endpoint. Public (no auth) — rate limiting at server/CDN level.
|
||||||
|
*/
|
||||||
|
public static function register_rest_routes(): void {
|
||||||
|
register_rest_route( 'peptide-search-ai/v1', '/compounds', array(
|
||||||
|
'methods' => 'GET',
|
||||||
|
'callback' => array( __CLASS__, 'rest_compounds' ),
|
||||||
|
'permission_callback' => '__return_true',
|
||||||
|
'args' => array(
|
||||||
|
'search' => array( 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field', 'default' => '' ),
|
||||||
|
'category' => array( 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field', 'default' => '' ),
|
||||||
|
'fields' => array( 'type' => 'string', 'enum' => array( 'basic', 'full' ), 'default' => 'full' ),
|
||||||
|
'page' => array( 'type' => 'integer', 'default' => 1, 'minimum' => 1, 'sanitize_callback' => 'absint' ),
|
||||||
|
'per_page' => array( 'type' => 'integer', 'default' => PSA_Directory::PER_PAGE_DEFAULT, 'minimum' => 1, 'maximum' => PSA_Directory::PER_PAGE_MAX, 'sanitize_callback' => 'absint' ),
|
||||||
|
),
|
||||||
|
) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* REST callback for GET /v1/compounds.
|
||||||
|
* Supports search, category filtering, pagination, and basic/full field sets.
|
||||||
|
*
|
||||||
|
* @param WP_REST_Request $request The REST request.
|
||||||
|
* @return WP_REST_Response
|
||||||
|
*/
|
||||||
|
public static function rest_compounds( $request ) {
|
||||||
|
$search = $request->get_param( 'search' );
|
||||||
|
$category = $request->get_param( 'category' );
|
||||||
|
$fields = $request->get_param( 'fields' );
|
||||||
|
$page = max( 1, (int) $request->get_param( 'page' ) );
|
||||||
|
$per_page = min( PSA_Directory::PER_PAGE_MAX, max( 1, (int) $request->get_param( 'per_page' ) ) );
|
||||||
|
|
||||||
|
$query_args = array(
|
||||||
|
'post_type' => 'peptide',
|
||||||
|
'post_status' => 'publish',
|
||||||
|
'posts_per_page' => $per_page,
|
||||||
|
'paged' => $page,
|
||||||
|
'orderby' => 'title',
|
||||||
|
'order' => 'ASC',
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( ! empty( $search ) ) {
|
||||||
|
$query_args['s'] = $search;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! empty( $category ) ) {
|
||||||
|
$query_args['tax_query'] = array( array(
|
||||||
|
'taxonomy' => 'peptide_category',
|
||||||
|
'field' => 'slug',
|
||||||
|
'terms' => $category,
|
||||||
|
) );
|
||||||
|
}
|
||||||
|
|
||||||
|
$query = new WP_Query( $query_args );
|
||||||
|
$post_ids = wp_list_pluck( $query->posts, 'ID' );
|
||||||
|
if ( ! empty( $post_ids ) ) {
|
||||||
|
update_meta_cache( 'post', $post_ids );
|
||||||
|
}
|
||||||
|
|
||||||
|
$compounds = array();
|
||||||
|
foreach ( $query->posts as $post ) {
|
||||||
|
$compounds[] = self::format_compound( $post, $fields );
|
||||||
|
}
|
||||||
|
|
||||||
|
$response = new WP_REST_Response( array(
|
||||||
|
'compounds' => $compounds,
|
||||||
|
'total' => (int) $query->found_posts,
|
||||||
|
'total_pages' => (int) $query->max_num_pages,
|
||||||
|
'page' => $page,
|
||||||
|
'per_page' => $per_page,
|
||||||
|
), 200 );
|
||||||
|
|
||||||
|
$response->header( 'X-WP-Total', (string) $query->found_posts );
|
||||||
|
$response->header( 'X-WP-TotalPages', (string) $query->max_num_pages );
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format a single compound for REST response.
|
||||||
|
*
|
||||||
|
* @param WP_Post $post The peptide post.
|
||||||
|
* @param string $fields 'basic' for lightweight data, 'full' for everything.
|
||||||
|
* @return array Formatted compound data.
|
||||||
|
*/
|
||||||
|
public static function format_compound( $post, string $fields = 'full' ): array {
|
||||||
|
$id = $post->ID;
|
||||||
|
|
||||||
|
$terms = wp_get_object_terms( $id, 'peptide_category', array( 'fields' => 'all' ) );
|
||||||
|
$categories = array();
|
||||||
|
if ( ! is_wp_error( $terms ) ) {
|
||||||
|
foreach ( $terms as $term ) {
|
||||||
|
$categories[] = array( 'slug' => $term->slug, 'name' => $term->name );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$basic = array(
|
||||||
|
'id' => $id,
|
||||||
|
'name' => $post->post_title,
|
||||||
|
'slug' => $post->post_name,
|
||||||
|
'url' => get_permalink( $id ),
|
||||||
|
'categories' => $categories,
|
||||||
|
'half_life' => get_post_meta( $id, 'psa_half_life', true ),
|
||||||
|
'stability' => get_post_meta( $id, 'psa_stability', true ),
|
||||||
|
'source' => get_post_meta( $id, 'psa_source', true ),
|
||||||
|
'extras' => apply_filters( 'psa_directory_card_extras', '', $id ),
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( 'basic' === $fields ) {
|
||||||
|
$basic['vial_size_mg'] = get_post_meta( $id, 'psa_vial_size_mg', true );
|
||||||
|
return $basic;
|
||||||
|
}
|
||||||
|
|
||||||
|
$full = array_merge( $basic, array(
|
||||||
|
'excerpt' => wp_trim_words( $post->post_content, 30 ),
|
||||||
|
'description' => wp_trim_words( $post->post_content, 80 ),
|
||||||
|
'sequence' => get_post_meta( $id, 'psa_sequence', true ),
|
||||||
|
'molecular_weight' => get_post_meta( $id, 'psa_molecular_weight', true ),
|
||||||
|
'molecular_formula' => get_post_meta( $id, 'psa_molecular_formula', true ),
|
||||||
|
'aliases' => get_post_meta( $id, 'psa_aliases', true ),
|
||||||
|
'mechanism' => get_post_meta( $id, 'psa_mechanism', true ),
|
||||||
|
'research_apps' => get_post_meta( $id, 'psa_research_apps', true ),
|
||||||
|
'safety_profile' => get_post_meta( $id, 'psa_safety_profile', true ),
|
||||||
|
'dosage_info' => get_post_meta( $id, 'psa_dosage_info', true ),
|
||||||
|
'references' => get_post_meta( $id, 'psa_references', true ),
|
||||||
|
'pubchem_cid' => get_post_meta( $id, 'psa_pubchem_cid', true ),
|
||||||
|
'solubility' => get_post_meta( $id, 'psa_solubility', true ),
|
||||||
|
'vial_size_mg' => get_post_meta( $id, 'psa_vial_size_mg', true ),
|
||||||
|
'storage_lyophilized' => get_post_meta( $id, 'psa_storage_lyophilized', true ),
|
||||||
|
'storage_reconstituted' => get_post_meta( $id, 'psa_storage_reconstituted', true ),
|
||||||
|
'typical_dose_mcg' => get_post_meta( $id, 'psa_typical_dose_mcg', true ),
|
||||||
|
'cycle_parameters' => get_post_meta( $id, 'psa_cycle_parameters', true ),
|
||||||
|
'amino_acid_count' => get_post_meta( $id, 'psa_amino_acid_count', true ),
|
||||||
|
) );
|
||||||
|
|
||||||
|
return apply_filters( 'psa_rest_compound_data', $full, $id );
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,15 +1,16 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* Browsable peptide directory — REST endpoint, shortcode, and data formatting.
|
* Browsable peptide directory — shortcode rendering and hook registration.
|
||||||
*
|
*
|
||||||
* What: Provides the [peptide_directory] shortcode and GET /v1/compounds REST endpoint.
|
* What: Provides the [peptide_directory] shortcode and delegates REST to PSA_Directory_API.
|
||||||
* Who calls it: WordPress shortcode parser, REST API router, main plugin file via PSA_Directory::init().
|
* Who calls it: WordPress shortcode parser, main plugin file via PSA_Directory::init().
|
||||||
* Dependencies: PSA_Post_Type (meta fields, taxonomy), PSA_Config.
|
* Dependencies: PSA_Directory_API (REST endpoint), frontend JS/CSS.
|
||||||
*
|
*
|
||||||
* @package PeptideSearchAI
|
* @package PeptideSearchAI
|
||||||
* @see includes/class-psa-post-type.php — CPT + taxonomy registration, meta keys
|
* @since 4.0.0
|
||||||
* @see includes/class-psa-search.php — existing search shortcode (separate from directory)
|
* @see includes/class-psa-directory-api.php — REST endpoint and compound formatting.
|
||||||
* @see assets/js/psa-directory.js — frontend grid, filter, modal logic
|
* @see assets/js/psa-directory.js — Frontend grid, filter, modal logic.
|
||||||
|
* @see assets/css/psa-directory.css — Directory-specific styles.
|
||||||
*/
|
*/
|
||||||
declare( strict_types=1 );
|
declare( strict_types=1 );
|
||||||
|
|
||||||
@@ -23,249 +24,35 @@ class PSA_Directory {
|
|||||||
const PER_PAGE_DEFAULT = 12;
|
const PER_PAGE_DEFAULT = 12;
|
||||||
const PER_PAGE_MAX = 100;
|
const PER_PAGE_MAX = 100;
|
||||||
|
|
||||||
/**
|
/** Register hooks. */
|
||||||
* Register hooks.
|
|
||||||
*/
|
|
||||||
public static function init(): void {
|
public static function init(): void {
|
||||||
add_shortcode( 'peptide_directory', array( __CLASS__, 'render_shortcode' ) );
|
add_shortcode( 'peptide_directory', array( __CLASS__, 'render_shortcode' ) );
|
||||||
add_action( 'rest_api_init', array( __CLASS__, 'register_rest_routes' ) );
|
add_action( 'rest_api_init', array( 'PSA_Directory_API', 'register_rest_routes' ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
|
||||||
// REST API
|
|
||||||
// -------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register the /v1/compounds endpoint for directory listing and cross-plugin data access.
|
|
||||||
*
|
|
||||||
* Public endpoint (no auth required) — serves the browsable directory.
|
|
||||||
* Rate limiting should be handled at the server/CDN level.
|
|
||||||
*/
|
|
||||||
public static function register_rest_routes(): void {
|
|
||||||
register_rest_route(
|
|
||||||
'peptide-search-ai/v1',
|
|
||||||
'/compounds',
|
|
||||||
array(
|
|
||||||
'methods' => 'GET',
|
|
||||||
'callback' => array( __CLASS__, 'rest_compounds' ),
|
|
||||||
'permission_callback' => '__return_true',
|
|
||||||
'args' => array(
|
|
||||||
'search' => array(
|
|
||||||
'type' => 'string',
|
|
||||||
'sanitize_callback' => 'sanitize_text_field',
|
|
||||||
'default' => '',
|
|
||||||
),
|
|
||||||
'category' => array(
|
|
||||||
'type' => 'string',
|
|
||||||
'sanitize_callback' => 'sanitize_text_field',
|
|
||||||
'default' => '',
|
|
||||||
),
|
|
||||||
'fields' => array(
|
|
||||||
'type' => 'string',
|
|
||||||
'enum' => array( 'basic', 'full' ),
|
|
||||||
'default' => 'full',
|
|
||||||
),
|
|
||||||
'page' => array(
|
|
||||||
'type' => 'integer',
|
|
||||||
'default' => 1,
|
|
||||||
'minimum' => 1,
|
|
||||||
'sanitize_callback' => 'absint',
|
|
||||||
),
|
|
||||||
'per_page' => array(
|
|
||||||
'type' => 'integer',
|
|
||||||
'default' => self::PER_PAGE_DEFAULT,
|
|
||||||
'minimum' => 1,
|
|
||||||
'maximum' => self::PER_PAGE_MAX,
|
|
||||||
'sanitize_callback' => 'absint',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* REST callback for GET /v1/compounds.
|
|
||||||
*
|
|
||||||
* Supports search, category filtering, pagination, and basic/full field sets.
|
|
||||||
*
|
|
||||||
* @param WP_REST_Request $request The REST request.
|
|
||||||
* @return WP_REST_Response
|
|
||||||
*/
|
|
||||||
public static function rest_compounds( $request ) {
|
|
||||||
$search = $request->get_param( 'search' );
|
|
||||||
$category = $request->get_param( 'category' );
|
|
||||||
$fields = $request->get_param( 'fields' );
|
|
||||||
$page = max( 1, (int) $request->get_param( 'page' ) );
|
|
||||||
$per_page = min( self::PER_PAGE_MAX, max( 1, (int) $request->get_param( 'per_page' ) ) );
|
|
||||||
|
|
||||||
$query_args = array(
|
|
||||||
'post_type' => 'peptide',
|
|
||||||
'post_status' => 'publish',
|
|
||||||
'posts_per_page' => $per_page,
|
|
||||||
'paged' => $page,
|
|
||||||
'orderby' => 'title',
|
|
||||||
'order' => 'ASC',
|
|
||||||
);
|
|
||||||
|
|
||||||
// Search filter: title and alias matching.
|
|
||||||
if ( ! empty( $search ) ) {
|
|
||||||
$query_args['s'] = $search;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Category filter: taxonomy query.
|
|
||||||
if ( ! empty( $category ) ) {
|
|
||||||
$query_args['tax_query'] = array(
|
|
||||||
array(
|
|
||||||
'taxonomy' => 'peptide_category',
|
|
||||||
'field' => 'slug',
|
|
||||||
'terms' => $category,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
$query = new WP_Query( $query_args );
|
|
||||||
|
|
||||||
// Prime caches for performance.
|
|
||||||
$post_ids = wp_list_pluck( $query->posts, 'ID' );
|
|
||||||
if ( ! empty( $post_ids ) ) {
|
|
||||||
update_meta_cache( 'post', $post_ids );
|
|
||||||
}
|
|
||||||
|
|
||||||
$compounds = array();
|
|
||||||
foreach ( $query->posts as $post ) {
|
|
||||||
$compounds[] = self::format_compound( $post, $fields );
|
|
||||||
}
|
|
||||||
|
|
||||||
$response_data = array(
|
|
||||||
'compounds' => $compounds,
|
|
||||||
'total' => (int) $query->found_posts,
|
|
||||||
'total_pages' => (int) $query->max_num_pages,
|
|
||||||
'page' => $page,
|
|
||||||
'per_page' => $per_page,
|
|
||||||
);
|
|
||||||
|
|
||||||
$response = new WP_REST_Response( $response_data, 200 );
|
|
||||||
|
|
||||||
// Pagination headers for client convenience.
|
|
||||||
$response->header( 'X-WP-Total', (string) $query->found_posts );
|
|
||||||
$response->header( 'X-WP-TotalPages', (string) $query->max_num_pages );
|
|
||||||
|
|
||||||
return $response;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Format a single compound for REST response.
|
|
||||||
*
|
|
||||||
* @param WP_Post $post The peptide post.
|
|
||||||
* @param string $fields 'basic' for lightweight data, 'full' for everything.
|
|
||||||
* @return array Formatted compound data.
|
|
||||||
*/
|
|
||||||
public static function format_compound( $post, string $fields = 'full' ): array {
|
|
||||||
$post_id = $post->ID;
|
|
||||||
|
|
||||||
// Get category terms.
|
|
||||||
$terms = wp_get_object_terms( $post_id, 'peptide_category', array( 'fields' => 'all' ) );
|
|
||||||
$categories = array();
|
|
||||||
if ( ! is_wp_error( $terms ) ) {
|
|
||||||
foreach ( $terms as $term ) {
|
|
||||||
$categories[] = array(
|
|
||||||
'slug' => $term->slug,
|
|
||||||
'name' => $term->name,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$basic = array(
|
|
||||||
'id' => $post_id,
|
|
||||||
'name' => $post->post_title,
|
|
||||||
'slug' => $post->post_name,
|
|
||||||
'url' => get_permalink( $post_id ),
|
|
||||||
'categories' => $categories,
|
|
||||||
'half_life' => get_post_meta( $post_id, 'psa_half_life', true ),
|
|
||||||
'stability' => get_post_meta( $post_id, 'psa_stability', true ),
|
|
||||||
'source' => get_post_meta( $post_id, 'psa_source', true ),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Allow other plugins to add data to directory cards (e.g., observation count).
|
|
||||||
$basic['extras'] = apply_filters( 'psa_directory_card_extras', '', $post_id );
|
|
||||||
|
|
||||||
if ( 'basic' === $fields ) {
|
|
||||||
// Lightweight response for cross-plugin use.
|
|
||||||
$basic['vial_size_mg'] = get_post_meta( $post_id, 'psa_vial_size_mg', true );
|
|
||||||
return $basic;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Full response: merge in all meta for detail modal.
|
|
||||||
$full = array_merge(
|
|
||||||
$basic,
|
|
||||||
array(
|
|
||||||
'excerpt' => wp_trim_words( $post->post_content, 30 ),
|
|
||||||
'description' => wp_trim_words( $post->post_content, 80 ),
|
|
||||||
'sequence' => get_post_meta( $post_id, 'psa_sequence', true ),
|
|
||||||
'molecular_weight' => get_post_meta( $post_id, 'psa_molecular_weight', true ),
|
|
||||||
'molecular_formula' => get_post_meta( $post_id, 'psa_molecular_formula', true ),
|
|
||||||
'aliases' => get_post_meta( $post_id, 'psa_aliases', true ),
|
|
||||||
'mechanism' => get_post_meta( $post_id, 'psa_mechanism', true ),
|
|
||||||
'research_apps' => get_post_meta( $post_id, 'psa_research_apps', true ),
|
|
||||||
'safety_profile' => get_post_meta( $post_id, 'psa_safety_profile', true ),
|
|
||||||
'dosage_info' => get_post_meta( $post_id, 'psa_dosage_info', true ),
|
|
||||||
'references' => get_post_meta( $post_id, 'psa_references', true ),
|
|
||||||
'pubchem_cid' => get_post_meta( $post_id, 'psa_pubchem_cid', true ),
|
|
||||||
'solubility' => get_post_meta( $post_id, 'psa_solubility', true ),
|
|
||||||
'vial_size_mg' => get_post_meta( $post_id, 'psa_vial_size_mg', true ),
|
|
||||||
'storage_lyophilized' => get_post_meta( $post_id, 'psa_storage_lyophilized', true ),
|
|
||||||
'storage_reconstituted' => get_post_meta( $post_id, 'psa_storage_reconstituted', true ),
|
|
||||||
'typical_dose_mcg' => get_post_meta( $post_id, 'psa_typical_dose_mcg', true ),
|
|
||||||
'cycle_parameters' => get_post_meta( $post_id, 'psa_cycle_parameters', true ),
|
|
||||||
'amino_acid_count' => get_post_meta( $post_id, 'psa_amino_acid_count', true ),
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Allow other plugins (e.g., Peptide Community) to enrich the compound data.
|
|
||||||
$full = apply_filters( 'psa_rest_compound_data', $full, $post_id );
|
|
||||||
|
|
||||||
return $full;
|
|
||||||
}
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
|
||||||
// Shortcode
|
|
||||||
// -------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render the [peptide_directory] shortcode.
|
* Render the [peptide_directory] shortcode.
|
||||||
|
* Outputs a container div populated by frontend JS via REST.
|
||||||
*
|
*
|
||||||
* Outputs a container div that the frontend JS populates with the card grid.
|
* @param array $atts Shortcode attributes (reserved for future use).
|
||||||
* Passes REST endpoint URL and category data via wp_localize_script.
|
|
||||||
*
|
|
||||||
* @param array $atts Shortcode attributes (unused for now, reserved for future).
|
|
||||||
* @return string HTML output.
|
* @return string HTML output.
|
||||||
*/
|
*/
|
||||||
public static function render_shortcode( $atts ): string {
|
public static function render_shortcode( $atts ): string {
|
||||||
// Get categories for filter buttons.
|
$terms = get_terms( array(
|
||||||
$terms = get_terms(
|
|
||||||
array(
|
|
||||||
'taxonomy' => 'peptide_category',
|
'taxonomy' => 'peptide_category',
|
||||||
'hide_empty' => false,
|
'hide_empty' => false,
|
||||||
'orderby' => 'name',
|
'orderby' => 'name',
|
||||||
'order' => 'ASC',
|
'order' => 'ASC',
|
||||||
)
|
) );
|
||||||
);
|
|
||||||
|
|
||||||
$categories = array();
|
$categories = array();
|
||||||
if ( ! is_wp_error( $terms ) ) {
|
if ( ! is_wp_error( $terms ) ) {
|
||||||
foreach ( $terms as $term ) {
|
foreach ( $terms as $term ) {
|
||||||
$categories[] = array(
|
$categories[] = array( 'slug' => $term->slug, 'name' => $term->name );
|
||||||
'slug' => $term->slug,
|
|
||||||
'name' => $term->name,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Localize script data for the directory JS.
|
wp_localize_script( 'psa-directory', 'psaDirectory', array(
|
||||||
wp_localize_script(
|
|
||||||
'psa-directory',
|
|
||||||
'psaDirectory',
|
|
||||||
array(
|
|
||||||
'restUrl' => esc_url_raw( rest_url( 'peptide-search-ai/v1/compounds' ) ),
|
'restUrl' => esc_url_raw( rest_url( 'peptide-search-ai/v1/compounds' ) ),
|
||||||
'nonce' => wp_create_nonce( 'wp_rest' ),
|
'nonce' => wp_create_nonce( 'wp_rest' ),
|
||||||
'categories' => $categories,
|
'categories' => $categories,
|
||||||
@@ -301,8 +88,7 @@ class PSA_Directory {
|
|||||||
'copySequence' => __( 'Copy', 'peptide-search-ai' ),
|
'copySequence' => __( 'Copy', 'peptide-search-ai' ),
|
||||||
'copied' => __( 'Copied!', 'peptide-search-ai' ),
|
'copied' => __( 'Copied!', 'peptide-search-ai' ),
|
||||||
),
|
),
|
||||||
)
|
) );
|
||||||
);
|
|
||||||
|
|
||||||
ob_start();
|
ob_start();
|
||||||
?>
|
?>
|
||||||
@@ -314,4 +100,15 @@ class PSA_Directory {
|
|||||||
<?php
|
<?php
|
||||||
return ob_get_clean();
|
return ob_get_clean();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Backward-compatible proxies (REST moved to PSA_Directory_API) ───
|
||||||
|
|
||||||
|
/** @see PSA_Directory_API::register_rest_routes() */
|
||||||
|
public static function register_rest_routes(): void { PSA_Directory_API::register_rest_routes(); }
|
||||||
|
|
||||||
|
/** @see PSA_Directory_API::rest_compounds() */
|
||||||
|
public static function rest_compounds( $request ) { return PSA_Directory_API::rest_compounds( $request ); }
|
||||||
|
|
||||||
|
/** @see PSA_Directory_API::format_compound() */
|
||||||
|
public static function format_compound( $post, string $fields = 'full' ): array { return PSA_Directory_API::format_compound( $post, $fields ); }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ require_once PSA_PLUGIN_DIR . 'includes/class-psa-admin-page.php';
|
|||||||
require_once PSA_PLUGIN_DIR . 'includes/class-psa-admin.php';
|
require_once PSA_PLUGIN_DIR . 'includes/class-psa-admin.php';
|
||||||
require_once PSA_PLUGIN_DIR . 'includes/class-psa-batch-enrichment.php';
|
require_once PSA_PLUGIN_DIR . 'includes/class-psa-batch-enrichment.php';
|
||||||
require_once PSA_PLUGIN_DIR . 'includes/class-psa-template.php';
|
require_once PSA_PLUGIN_DIR . 'includes/class-psa-template.php';
|
||||||
|
require_once PSA_PLUGIN_DIR . 'includes/class-psa-directory-api.php';
|
||||||
require_once PSA_PLUGIN_DIR . 'includes/class-psa-directory.php';
|
require_once PSA_PLUGIN_DIR . 'includes/class-psa-directory.php';
|
||||||
require_once PSA_PLUGIN_DIR . 'includes/class-psa-upgrade.php';
|
require_once PSA_PLUGIN_DIR . 'includes/class-psa-upgrade.php';
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user