Skip to content
wiki.fftac.org

Promptrepository - Source Excerpt 05

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

$posts = get_posts(
            [
                'name' => sanitize_title($slug),
                'post_type' => self::POST_TYPE,
                'post_status' => ['publish', 'draft', 'pending', 'private'],
                'posts_per_page' => 1,
            ]
        );

        if (empty($posts[0]) || !$posts[0] instanceof WP_Post) {
            return [];
        }

        return $this->get((int) $posts[0]->ID, $viewer_user_id);
    }

    /**
     * Finds a managed system prompt by its source slug.
     */
    public function find_by_source_slug(string $source_slug, int $viewer_user_id = 0): array
    {
        $posts = get_posts(
            [
                'post_type' => self::POST_TYPE,
                'post_status' => ['publish', 'draft', 'pending', 'private'],
                'posts_per_page' => 1,
                'meta_query' => [
                    [
                        'key' => $this->meta_key('source_slug'),
                        'value' => sanitize_title($source_slug),
                    ],
                ],
            ]
        );

        if (empty($posts[0]) || !$posts[0] instanceof WP_Post) {
            return [];
        }

        return $this->get((int) $posts[0]->ID, $viewer_user_id);
    }

    /**
     * Finds a managed prompt that already exists under the filesystem slug or a WordPress suffix variant.
     */
    public function find_managed_slug_candidate(string $slug, int $viewer_user_id = 0): array
    {
        foreach ($this->find_slug_duplicate_candidates($slug, $viewer_user_id) as $candidate) {
            if ($this->is_managed_prompt_record($candidate)) {
                return $candidate;
            }
        }

        return [];
    }

    /**
     * Finds records whose slug is either the canonical slug or a WordPress-generated numeric variant.
     *
     * @return array<int,array<string,mixed>>
     */
    public function find_slug_duplicate_candidates(string $slug, int $viewer_user_id = 0): array
    {
        global $wpdb;

        $slug = sanitize_title($slug);
        if ($slug === '') {
            return [];
        }

        $like = $wpdb->esc_like($slug . '-') . '%';
        $sql = $wpdb->prepare(
            "SELECT ID, post_name FROM {$wpdb->posts} WHERE post_type = %s AND post_status IN ('publish', 'draft', 'pending', 'private') AND (post_name = %s OR post_name LIKE %s) ORDER BY ID ASC",
            self::POST_TYPE,
            $slug,
            $like
        );
        $rows = $wpdb->get_results($sql, ARRAY_A);

        if (!is_array($rows)) {
            return [];
        }

        $pattern = '/^' . preg_quote($slug, '/') . '(?:-[0-9]+)?$/';
        $records = [];

        foreach ($rows as $row) {
            $post_name = (string) ($row['post_name'] ?? '');
            if (!preg_match($pattern, $post_name)) {
                continue;
            }

            $record = $this->get((int) ($row['ID'] ?? 0), $viewer_user_id);
            if (!empty($record)) {
                $records[] = $record;
            }
        }

        usort(
            $records,
            function (array $left, array $right) use ($slug): int {
                return $this->duplicate_candidate_score($right, $slug) <=> $this->duplicate_candidate_score($left, $slug);
            }
        );

        return $records;
    }

    /**
     * Lists prompts for the public or authenticated libraries.
     */
    public function list(array $args = [], int $viewer_user_id = 0): array
    {
        $query_args = [
            'post_type' => self::POST_TYPE,
            'post_status' => ['publish', 'private', 'draft', 'pending'],
            'posts_per_page' => isset($args['limit']) ? max(1, (int) $args['limit']) : 20,
            'orderby' => 'modified',
            'order' => 'DESC',
        ];

        if (!empty($args['owner_user_id'])) {
            $query_args['author'] = (int) $args['owner_user_id'];
        }

        if (!empty($args['search'])) {
            $query_args['s'] = sanitize_text_field((string) $args['search']);
        }

        if (!empty($args['include'])) {
            $query_args['post__in'] = array_values(array_map('intval', (array) $args['include']));
            $query_args['orderby'] = 'post__in';
        }

        $posts = get_posts($query_args);
        $records = [];

        foreach ($posts as $post) {
            if (!$post instanceof WP_Post) {
                continue;
            }

            $records[] = $this->get((int) $post->ID, $viewer_user_id);
        }

        return $records;
    }

    /**
     * Lists only public, published prompts that are not hidden by moderation.
     */
    public function list_public(array $args = [], int $viewer_user_id = 0): array
    {
        $requested_limit = isset($args['limit']) ? max(1, (int) $args['limit']) : 100;
        $query_limit = !empty($args['include']) ? $requested_limit : min(max($requested_limit * 2, $requested_limit), 240);
        $query_args = [
            'post_type' => self::POST_TYPE,
            'post_status' => ['publish'],
            'posts_per_page' => $query_limit,
            'orderby' => 'modified',
            'order' => 'DESC',
            'ignore_sticky_posts' => true,
            'no_found_rows' => true,
            'update_post_meta_cache' => true,
            'update_post_term_cache' => true,
            'meta_query' => [
                'relation' => 'AND',
                [
                    'key' => $this->meta_key('visibility'),
                    'value' => 'public',
                ],
                [
                    'key' => $this->meta_key('prompt_status'),
                    'value' => 'published',
                ],
                [
                    'relation' => 'OR',
                    [
                        'key' => $this->meta_key('moderation_status'),
                        'compare' => 'NOT EXISTS',
                    ],
                    [
                        'key' => $this->meta_key('moderation_status'),
                        'value' => ['restricted', 'restricted_review', 'reverted', 'archived'],
                        'compare' => 'NOT IN',
                    ],
                ],
                [
                    'relation' => 'OR',
                    [
                        'key' => $this->meta_key('soft_deleted_at'),
                        'compare' => 'NOT EXISTS',
                    ],
                    [
                        'key' => $this->meta_key('soft_deleted_at'),
                        'value' => '',
                        'compare' => '=',
                    ],
                ],
            ],
        ];

        if (!empty($args['search'])) {
            $query_args['s'] = sanitize_text_field((string) $args['search']);
        }

        if (!empty($args['include'])) {
            $query_args['post__in'] = array_values(array_map('intval', (array) $args['include']));
            $query_args['orderby'] = 'post__in';
        }

        $posts = get_posts($query_args);
        $records = [];

        foreach ($posts as $post) {
            if (!$post instanceof WP_Post) {
                continue;
            }

            $records[] = $this->get((int) $post->ID, $viewer_user_id);
        }

        return array_slice($this->dedupe_public_records($records), 0, $requested_limit);
    }

    /**
     * @param array<int,array<string,mixed>> $records
     * @return array<int,array<string,mixed>>
     */
    private function dedupe_public_records(array $records): array
    {
        $deduped = [];

        foreach ($records as $record) {
            if (empty($record)) {
                continue;
            }

            $key = $this->public_dedupe_key($record);
            if ($key === '') {
                $deduped[] = $record;
                continue;
            }

            if (
                !isset($deduped[$key])
                || $this->duplicate_candidate_score($record, $this->numeric_slug_base((string) ($record['slug'] ?? ''))) > $this->duplicate_candidate_score($deduped[$key], $this->numeric_slug_base((string) ($deduped[$key]['slug'] ?? '')))
            ) {
                $deduped[$key] = $record;
            }
        }

        return array_values($deduped);
    }

    /**
     * @param array<string,mixed> $record
     */
    private function public_dedupe_key(array $record): string
    {
        $source_slug = sanitize_title((string) ($record['source_slug'] ?? ''));
        if ($source_slug !== '') {
            return 'source:' . $source_slug;
        }

        $slug = sanitize_title((string) ($record['slug'] ?? ''));
        if ($slug === '') {
            return '';
        }