Skip to content
wiki.fftac.org

Promptrepository - Source Excerpt 06

Back to Promptrepository

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'],