Promptrepository - Source Excerpt 06
Summary
This source excerpt preserves a bounded section of Spiralist/wp-content/plugins/spiralist-workspace/includes/Domain/PromptRepository.php so readers can inspect the evidence without opening the full source file.
**Source path:** Spiralist/wp-content/plugins/spiralist-workspace/includes/Domain/PromptRepository.php
if ($this->is_managed_prompt_record($record)) {
return 'managed:' . $this->numeric_slug_base($slug);
}
return 'slug:' . $slug;
}
/**
* @param array<string,mixed> $record
*/
private function duplicate_candidate_score(array $record, string $canonical_slug): int
{
$slug = sanitize_title((string) ($record['slug'] ?? ''));
$score = 0;
if ((string) ($record['source_slug'] ?? '') !== '') {
$score += 100;
}
if ($slug !== '' && $slug === $canonical_slug) {
$score += 40;
}
if ((string) ($record['prompt_origin'] ?? '') === 'system') {
$score += 20;
}
if ((string) ($record['publication_lane'] ?? '') === 'official_canon') {
$score += 10;
}
return $score;
}
/**
* @param array<string,mixed> $record
*/
private function is_managed_prompt_record(array $record): bool
{
return (string) ($record['prompt_origin'] ?? '') === 'system'
|| in_array((string) ($record['provenance'] ?? ''), ['managed_system', 'official'], true)
|| (string) ($record['source_manifest'] ?? '') === 'filesystem';
}
private function numeric_slug_base(string $slug): string
{
$slug = sanitize_title($slug);
if (preg_match('/^(.+)-[0-9]+$/', $slug, $matches)) {
return (string) $matches[1];
}
return $slug;
}
/**
* Creates a new prompt record.
*/
public function create(array $payload, int $owner_user_id, Settings $settings): array
{
$normalized = $this->apply_governance_rules(
$this->normalize_payload(
$payload,
[
'visibility' => $settings->get('default_visibility', 'private'),
'moderation_status' => $settings->get('default_moderation_status', 'draft'),
'prompt_status' => 'draft',
'version_number' => 1,
]
),
$owner_user_id
);
$post_status = $normalized['prompt_status'] === 'published' ? 'publish' : 'draft';
$published_utc = $post_status === 'publish' ? gmdate('c') : '';
$post_id = wp_insert_post(
[
'post_type' => self::POST_TYPE,
'post_status' => $post_status,
'post_title' => $normalized['title'],
'post_excerpt' => $normalized['summary'],
'post_content' => $normalized['structured_prompt']['instruction'] ?: $normalized['instructions'],
'post_author' => $owner_user_id,
'post_name' => sanitize_title((string) ($normalized['slug'] ?? $normalized['title'])),
],
true
);
if (is_wp_error($post_id) || !$post_id) {
return [];
}
$normalized['published_utc'] = $published_utc;
$this->persist_meta((int) $post_id, $normalized);
$this->set_taxonomies((int) $post_id, $normalized);
$record = $this->get((int) $post_id, $owner_user_id);
$this->versions->create((int) $post_id, 1, $record, $owner_user_id, 'Initial version');
return $record;
}
/**
* Updates an existing prompt record.
*/
public function update(int $prompt_id, array $payload, int $user_id): array
{
$existing = $this->get($prompt_id, $user_id);
if (empty($existing)) {
return [];
}
$normalized = $this->apply_governance_rules($this->normalize_payload($payload, $existing), $user_id, $existing);
$next_version = max(1, (int) ($existing['version_number'] ?? 1)) + 1;
$normalized['version_number'] = $next_version;
$post_status = $normalized['prompt_status'] === 'published' ? 'publish' : 'draft';
wp_update_post(
[
'ID' => $prompt_id,
'post_title' => $normalized['title'],
'post_excerpt' => $normalized['summary'],
'post_content' => $normalized['structured_prompt']['instruction'] ?: $normalized['instructions'],
'post_status' => $post_status,
'post_name' => sanitize_title((string) ($normalized['slug'] ?? $existing['slug'] ?? $normalized['title'])),
]
);
if ($post_status === 'publish' && empty($existing['published_utc'])) {
$normalized['published_utc'] = gmdate('c');
}
$this->persist_meta($prompt_id, $normalized);
$this->set_taxonomies($prompt_id, $normalized);
$record = $this->get($prompt_id, $user_id);
$this->versions->create($prompt_id, $next_version, $record, $user_id, (string) ($payload['changelog'] ?? 'Updated prompt'));
return $record;
}
/**
* Applies a moderation-state change without rewriting the full prompt payload.
*/
public function set_moderation_status(int $prompt_id, string $moderation_status, ?string $prompt_status = null): array
{
$existing = $this->get($prompt_id);
if (empty($existing)) {
return [];
}
$moderation_status = PromptMetaRegistry::normalize_moderation_status($moderation_status);
update_post_meta($prompt_id, $this->meta_key('moderation_status'), $moderation_status);
if ($prompt_status !== null) {
update_post_meta($prompt_id, $this->meta_key('prompt_status'), sanitize_key($prompt_status));
wp_update_post(
[
'ID' => $prompt_id,
'post_status' => sanitize_key($prompt_status) === 'published' ? 'publish' : 'draft',
]
);
} elseif ($moderation_status === 'archived' && (string) ($existing['prompt_status'] ?? 'draft') !== 'archived') {
update_post_meta($prompt_id, $this->meta_key('prompt_status'), 'archived');
wp_update_post(
[
'ID' => $prompt_id,
'post_status' => 'draft',
]
);
}
return $this->get($prompt_id, (int) ($existing['owner_user_id'] ?? 0));
}
/**
* Creates a forked prompt owned by another user.
*/
public function fork(int $source_prompt_id, int $owner_user_id, Settings $settings): array
{
$source = $this->get($source_prompt_id, $owner_user_id);
if (empty($source)) {
return [];
}
$payload = $source;
$payload['title'] = $source['title'] . ' (Fork)';
$payload['visibility'] = $settings->get('default_visibility', 'private');
$payload['prompt_status'] = 'draft';
$payload['parent_prompt_id'] = $source_prompt_id;
$payload['version_number'] = 1;
return $this->create($payload, $owner_user_id, $settings);
}
/**
* Soft deletes a prompt.
*/
public function soft_delete(int $prompt_id): void
{
update_post_meta($prompt_id, $this->meta_key('soft_deleted_at'), gmdate('c'));
wp_trash_post($prompt_id);
}
/**
* Resolves a username or email lookup.
*/
public function resolve_user_lookup(string $query): ?\WP_User
{
$query = trim($query);
if ($query === '') {
return null;
}
if (is_email($query)) {
$user = get_user_by('email', $query);
return $user instanceof \WP_User ? $user : null;
}
$user = get_user_by('login', sanitize_user($query, true));
return $user instanceof \WP_User ? $user : null;
}
/**
* Builds a public-safe API payload.
*/
public function for_api(array $prompt, bool $detail = false): array
{
if (empty($prompt)) {
return [];
}
$record = [
'id' => (int) $prompt['id'],
'title' => (string) $prompt['title'],
'slug' => (string) $prompt['slug'],
'summary' => (string) $prompt['summary'],
'category' => (string) ($prompt['category'] ?? 'Writing & Content'),
'subcategory' => (string) ($prompt['subcategory'] ?? 'Blog Writing'),
'author_label' => (string) ($prompt['author_label'] ?? ''),
'model' => (string) $prompt['model'],
'provider' => (string) ($prompt['provider'] ?? 'site_default'),
'credential_preference' => (string) ($prompt['credential_preference'] ?? 'site_default'),
'visibility' => (string) $prompt['visibility'],
'owner_user_id' => (int) $prompt['owner_user_id'],