Skip to content
wiki.fftac.org

Frontendcontroller - Source Excerpt 06

Back to Frontendcontroller

Summary

This source excerpt preserves a bounded section of Spiralist/wp-content/plugins/spiralist-workspace/includes/Web/FrontendController.php so readers can inspect the evidence without opening the full source file.

**Source path:** Spiralist/wp-content/plugins/spiralist-workspace/includes/Web/FrontendController.php

$prompt['last_run_utc'] = (string) ($stat['last_run_utc'] ?? '');
            $records[] = $prompt;
        }

        if (count($records) >= $limit) {
            return array_slice($records, 0, $limit);
        }

        foreach ($this->public_prompts($limit) as $prompt) {
            if (count($records) >= $limit) {
                break;
            }

            $already_added = array_filter(
                $records,
                static fn(array $record): bool => (int) ($record['id'] ?? 0) === (int) ($prompt['id'] ?? 0)
            );

            if (!empty($already_added)) {
                continue;
            }

            $prompt['run_count'] = 0;
            $records[] = $prompt;
        }

        return array_slice($records, 0, $limit);
    }

    /**
     * Returns category counts for public prompt discovery.
     */
    public function popular_categories(int $limit = 10): array
    {
        return $this->popular_categories_from_prompts($this->public_prompts(100), $limit);
    }

    /**
     * Returns a prompt creation/edit form seed.
     */
    public function default_prompt_seed(): array
    {
        return [
            'title' => '',
            'summary' => '',
            'category' => 'Writing & Content',
            'subcategory' => 'Blog Writing',
            'structured_prompt' => [
                'instruction' => '',
                'context' => '',
                'constraints' => '',
                'examples' => '',
                'output_format' => '',
            ],
            'instructions' => '',
            'system_prompt' => '',
            'developer_prompt' => '',
            'user_prompt_template' => '',
            'system_steps' => [],
            'system_steps_json' => '[]',
            'spiral_script_source' => '',
            'spiral_script' => [],
            'spiral_script_validation' => [],
            'spiral_script_status' => 'none',
            'model' => $this->settings->get_allowed_models()[0],
            'provider' => 'prompt_art_only',
            'credential_preference' => 'site_only',
            'temperature' => 0.7,
            'max_output_tokens' => 1200,
            'visibility' => $this->settings->get('default_visibility', 'private'),
            'tags' => [],
            'prompt_type' => 'prompt',
            'language' => 'en',
            'prompt_status' => 'draft',
            'moderation_status' => 'draft',
            'publication_lane' => 'community_library',
            'provenance' => 'community',
            'risk_labels' => [],
            'function_tags' => [],
            'maturity_level' => 'structured_prompt',
            'license' => 'spiralist_contributor',
            'editorial_note' => '',
            'expected_output_notes' => '',
            'failure_modes' => '',
            'related_symbols' => [],
            'related_axioms' => [],
            'related_manuscripts' => [],
            'sample_output' => '',
            'is_forkable' => true,
            'allow_comments' => false,
            'allow_ratings' => false,
        ];
    }

    /**
     * Returns whether conversation sharing is enabled.
     */
    public function allows_conversation_sharing(): bool
    {
        return $this->settings->get('conversation_sharing_enabled', '0') === '1';
    }

    /**
     * Returns the model allowlist.
     */
    public function allowed_models(): array
    {
        return $this->settings->get_allowed_models();
    }

    /**
     * Renders a JSON response and exits.
     */
    private function render_json($payload, int $status): void
    {
        status_header($status);
        nocache_headers();
        header('Content-Type: application/json; charset=' . get_bloginfo('charset'));
        echo wp_json_encode($payload, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
        exit;
    }

    /**
     * Forces a front-end 404 response.
     */
    private function force_404(): void
    {
        global $wp_query;

        if ($wp_query instanceof \WP_Query) {
            $wp_query->set_404();
        }

        status_header(404);
        nocache_headers();

        $template = get_query_template('404');
        if (is_string($template) && $template !== '' && file_exists($template)) {
            include $template;
        }

        exit;
    }

    /**
     * Returns public prompt records.
     */
    private function public_prompts(int $limit): array
    {
        $query_limit = max($limit, 120);

        if ($this->public_prompt_cache_limit < $query_limit || empty($this->public_prompt_cache)) {
            $records = $this->prompts->list_public(['limit' => $query_limit], get_current_user_id());
            if (empty($records) && !$this->public_prompt_sync_attempted) {
                $this->maybe_sync_system_prompts();
                $this->public_prompt_sync_attempted = true;
                $records = $this->prompts->list_public(['limit' => $query_limit], get_current_user_id());
            }

            $public = array_values(
                array_filter(
                    $records,
                    fn(array $prompt): bool => $this->is_public_library_prompt($prompt)
                )
            );

            usort(
                $public,
                static function (array $left, array $right): int {
                    $featured_compare = ((int) !empty($right['featured'])) <=> ((int) !empty($left['featured']));
                    if ($featured_compare !== 0) {
                        return $featured_compare;
                    }

                    return strcmp((string) ($right['updated_utc'] ?? ''), (string) ($left['updated_utc'] ?? ''));
                }
            );

            $this->public_prompt_cache = $public;
            $this->public_prompt_cache_limit = $query_limit;
        }

        return array_slice($this->public_prompt_cache, 0, $limit);
    }

    /**
     * Returns public prompts for one publication lane from a preloaded record set.
     */
    private function public_prompts_for_lane(array $records, string $lane, int $limit = 6): array
    {
        $normalized_lane = PromptMetaRegistry::normalize_publication_lane($lane);
        $matches = array_values(
            array_filter(
                $records,
                static fn(array $prompt): bool => (string) ($prompt['publication_lane'] ?? 'community_library') === $normalized_lane
            )
        );

        return array_slice($matches, 0, $limit);
    }

    /**
     * Returns category counts for a public prompt collection.
     */
    private function popular_categories_from_prompts(array $records, int $limit = 10): array
    {
        $counts = [];

        foreach ($records as $prompt) {
            $category = (string) ($prompt['category'] ?? 'Writing & Content');
            $subcategory = (string) ($prompt['subcategory'] ?? 'Blog Writing');
            $key = $category . '|' . $subcategory;

            if (!isset($counts[$key])) {
                $counts[$key] = [
                    'category' => $category,
                    'subcategory' => $subcategory,
                    'count' => 0,
                ];
            }

            $counts[$key]['count']++;
        }

        usort(
            $counts,
            static fn(array $left, array $right): int => ((int) $right['count']) <=> ((int) $left['count'])
        );

        if (empty($counts)) {
            foreach (array_slice(PromptCategoryRegistry::for_api(), 0, $limit) as $category) {
                $counts[] = [
                    'category' => (string) ($category['category'] ?? ''),
                    'subcategory' => (string) (($category['subcategories'] ?? [])[0] ?? ''),
                    'count' => 0,
                ];
            }
        }

        return array_slice($counts, 0, $limit);
    }

    /**
     * Returns reviewer-facing queue data for public prompts that need community action.
     *
     * @return array{items:array<int,array<string,mixed>>,counts:array<string,int>}
     */
    private function review_queue_context(int $user_id, int $limit = 10): array
    {
        $empty = [
            'items' => [],
            'counts' => [
                'provisional_public' => 0,
                'restricted_review' => 0,
                'reverted' => 0,
                'stale' => 0,
                'urgent' => 0,
                'total' => 0,
            ],
        ];

        if ($user_id <= 0 || !$this->permissions->can_review_prompts($user_id)) {
            return $empty;
        }

        $records = array_values(
            array_filter(
                $this->prompts->list(['limit' => 80], $user_id),