feat(cpt): consolidate peptide CPT with PSA; drop pr_peptide (v0.2.0) (#1)

Consolidates the `peptide` CPT under PR Core ownership, dropping the `pr_peptide` slug-collision that was 404ing all 89 peptide detail pages.

- POST_TYPE: pr_peptide -> peptide
- TAX_CATEGORY: pr_peptide_category -> peptide_category
- TAX_FAMILY + pr_peptide_family taxonomy removed
- Defensive post_type_exists/taxonomy_exists guards on both registrations
- Args harmonized as superset of PSA + prior PR Core (adds thumbnail support)
- Activation hook + init:999 version-change flush handler
- Uninstall scoped to _pr_core_authored flag (PSA-authored posts survive)
- Plugin version 0.1.1 -> 0.2.0, CHANGELOG in same commit
- ARCHITECTURE.md + CONVENTIONS.md updated with CPT ownership rule

QA gate verdict: PASS (qa-reviews/peptide-repo-core/2026-04-22-874f93b.md)
Sibling release: peptiderepo/peptide-search-ai#15 (PSA v4.5.0)

Known follow-up: manage_peptide_content capability is not granted to any role as of v0.2.0. No current UI/theme reads or writes PR Core-defined meta keys, so no regression. Follow-up thread to decide role assignment.
This commit is contained in:
peptiderepo
2026-04-22 16:44:04 +07:00
committed by GitHub
parent c70352eb40
commit f086b89e2d
16 changed files with 592 additions and 78 deletions

View File

@@ -1,11 +1,13 @@
<?php
/**
* Peptide Repo Core — Full data teardown on uninstall.
* Peptide Repo Core — Selective data teardown on uninstall.
*
* Removes ALL plugin data: custom tables, CPT posts + meta, taxonomy terms,
* options, and capabilities. No orphaned data left behind.
* Removes plugin-owned data only: custom tables, PR Core-authored peptide
* posts, pr_core_ options, and the manage_peptide_content capability.
* Shared data (the 89 canonical peptide posts authored by PSA, and the
* peptide_category taxonomy terms) is preserved.
*
* @see ARCHITECTURE.md — Section 2.9 Uninstall specification.
* @see ARCHITECTURE.md — §2.9 Uninstall specification.
*/
if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
@@ -27,33 +29,45 @@ foreach ( $tables as $table ) {
$wpdb->query( "DROP TABLE IF EXISTS {$table}" );
}
/* ── 2. Delete all pr_peptide posts (cascade deletes meta) ────────────── */
/* ── 2. Delete only peptide posts authored through PR Core's UI ───────── */
/*
* As of v0.2.0, PR Core shares the `peptide` CPT with Peptide Search AI.
* PSA authored the 89 canonical peptide posts on peptiderepo.com; those
* predate PR Core and do NOT carry the `_pr_core_authored` flag. A blanket
* DELETE here would destroy site-owned content, not plugin-owned content.
*
* This loop only deletes posts that PR Core itself created (flagged with
* post-meta `_pr_core_authored = '1'`). If no post carries the flag, the
* loop no-ops and shared content is preserved.
*/
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
$post_ids = $wpdb->get_col(
"SELECT ID FROM {$wpdb->posts} WHERE post_type = 'pr_peptide'"
$wpdb->prepare(
"SELECT p.ID FROM {$wpdb->posts} p
INNER JOIN {$wpdb->postmeta} pm
ON p.ID = pm.post_id AND pm.meta_key = %s AND pm.meta_value = %s
WHERE p.post_type = %s",
'_pr_core_authored',
'1',
'peptide'
)
);
foreach ( $post_ids as $post_id ) {
wp_delete_post( (int) $post_id, true );
}
/* ── 3. Delete taxonomy terms ─────────────────────────────────────────── */
/* ── 3. Preserve taxonomy terms (shared ownership post-v0.2.0) ────────── */
$taxonomies = [ 'pr_peptide_category', 'pr_peptide_family' ];
foreach ( $taxonomies as $taxonomy ) {
$terms = get_terms( [
'taxonomy' => $taxonomy,
'hide_empty' => false,
'fields' => 'ids',
] );
if ( is_array( $terms ) ) {
foreach ( $terms as $term_id ) {
wp_delete_term( (int) $term_id, $taxonomy );
}
}
}
/*
* `peptide_category` is shared between PR Core and PSA. Term metadata
* (descriptions, parent relationships, counts) is data the site owns —
* removing it on PR Core uninstall would strip categorization from the
* peptide posts that remain. So we intentionally do NOT enumerate or
* delete terms here. `pr_peptide_family` is gone in v0.2.0 so no cleanup
* is needed for it either.
*/
/* ── 4. Delete all pr_core_ prefixed options ──────────────────────────── */
@@ -62,7 +76,7 @@ $wpdb->query(
"DELETE FROM {$wpdb->options} WHERE option_name LIKE 'pr\_core\_%'"
);
/* ── 5. Remove manage_peptide_content capability from all roles ────────── */
/* ── 5. Remove manage_peptide_content capability from all roles ───────── */
$editable_roles = wp_roles()->roles;