Skip to content
wiki.fftac.org

Frontendcontroller - Source Excerpt 04

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

'exchangeSectionInstruction' => $ui_text('workspace.js.exchange.section.instruction', 'Instruction'),
                    'exchangeSectionContext' => $ui_text('workspace.js.exchange.section.context', 'Context'),
                    'exchangeSectionConstraints' => $ui_text('workspace.js.exchange.section.constraints', 'Constraints'),
                    'exchangeSectionExamples' => $ui_text('workspace.js.exchange.section.examples', 'Examples'),
                    'exchangeSectionOutputFormat' => $ui_text('workspace.js.exchange.section.output_format', 'Output Format'),
                    'exchangeSectionSystemPrompt' => $ui_text('workspace.js.exchange.section.system_prompt', 'System Prompt'),
                    'exchangeSectionDeveloperPrompt' => $ui_text('workspace.js.exchange.section.developer_prompt', 'Developer Prompt'),
                    'exchangeSectionUserPromptTemplate' => $ui_text('workspace.js.exchange.section.user_prompt_template', 'User Prompt Template'),
                    'exchangeSectionExpectedOutputNotes' => $ui_text('workspace.js.exchange.section.expected_output_notes', 'Expected Output Notes'),
                    'exchangeSectionFailureModes' => $ui_text('workspace.js.exchange.section.failure_modes', 'Failure Modes'),
                    'exchangeSectionSampleOutput' => $ui_text('workspace.js.exchange.section.sample_output', 'Sample Output'),
                    'exchangeSectionSource' => $ui_text('workspace.js.exchange.section.source', 'Source'),
                    'exchangeFieldHumanUrl' => $ui_text('workspace.js.exchange.field.human_url', 'Human URL'),
                    'exchangeFieldPublicApiUrl' => $ui_text('workspace.js.exchange.field.public_api_url', 'Public API URL'),
                ],
            ]
        );
    }

    /**
     * Maps workspace routes to plugin templates.
     */
    public function template_include(string $template): string
    {
        $route = (string) get_query_var('spiralist_workspace_route');
        if ($route === '') {
            return $template;
        }

        $map = [
            'library' => SPIRALIST_WORKSPACE_DIR . 'templates/library.php',
            'prompt' => SPIRALIST_WORKSPACE_DIR . 'templates/prompt.php',
            'workspace' => SPIRALIST_WORKSPACE_DIR . 'templates/workspace.php',
            'members' => SPIRALIST_WORKSPACE_DIR . 'templates/members.php',
            'profile' => SPIRALIST_WORKSPACE_DIR . 'templates/profile.php',
            'run' => SPIRALIST_WORKSPACE_DIR . 'templates/run.php',
            'conversation' => SPIRALIST_WORKSPACE_DIR . 'templates/conversation.php',
        ];

        if (!isset($map[$route])) {
            return $template;
        }

        return $map[$route];
    }

    /**
     * Outputs JSON alias responses for /api/* convenience routes.
     */
    public function handle_api_alias(): void
    {
        $route = (string) get_query_var('spiralist_workspace_route');
        if ($route !== 'api') {
            return;
        }

        $type = sanitize_key((string) get_query_var('spiralist_workspace_api'));
        $user_id = get_current_user_id();
        $payload = [];

        if ($type === 'prompts') {
            $records = $this->prompts->list(['limit' => 50], $user_id);
            $records = array_values(
                array_filter(
                    $records,
                    function (array $prompt) use ($user_id): bool {
                        if ($user_id > 0) {
                            return $this->permissions->can_view_prompt($prompt, $user_id);
                        }

                        return (string) ($prompt['visibility'] ?? '') === 'public';
                    }
                )
            );
            $payload = array_map(fn(array $prompt): array => $this->prompts->for_api($prompt, false), $records);
        } elseif ($type === 'runs') {
            if ($user_id <= 0) {
                $this->render_json(['error' => 'Authentication required.'], 401);
            }

            $payload = $this->runs->list_for_user($user_id, 50);
        } elseif ($type === 'conversations') {
            if ($user_id <= 0) {
                $this->render_json(['error' => 'Authentication required.'], 401);
            }

            $payload = $this->conversations->list_for_user($user_id, 50);
        } else {
            $this->render_json(['error' => 'Not found.'], 404);
        }

        $this->render_json($payload, 200);
    }

    /**
     * Returns whether the current request is one of the plugin routes.
     */
    public function is_workspace_request(): bool
    {
        return (string) get_query_var('spiralist_workspace_route') !== '';
    }

    /**
     * Returns prompt detail context for templates.
     */
    public function prompt_context(): array
    {
        $slug = (string) get_query_var('spiralist_workspace_prompt_slug');
        $user_id = get_current_user_id();
        $prompt = $this->prompts->find_by_slug($slug, $user_id);

        if (empty($prompt) || !$this->permissions->can_view_prompt($prompt, $user_id)) {
            $this->force_404();
        }

        $prompt['appeal_summary'] = $this->appeals->summary_for_prompt((int) $prompt['id']);
        $prompt['review_summary'] = $this->current_review_summary((int) $prompt['id'], $prompt['appeal_summary']);
        $prompt['governance_summary'] = PromptGovernanceSummary::build(
            $prompt,
            $prompt['review_summary'],
            $prompt['appeal_summary']
        );

        return [
            'prompt' => $prompt,
            'versions' => $this->versions->list_for_prompt((int) $prompt['id'], 10),
            'execution_history' => $this->runs->list_for_prompt((int) $prompt['id'], 8),
            'tests' => $this->tests->list_for_prompt((int) $prompt['id'], 20),
            'shares' => $this->permissions->can_share_prompt($prompt, $user_id) ? $this->shares->list_for_prompt((int) $prompt['id']) : [],
            'review_items' => $this->reviews->list_for_prompt((int) $prompt['id'], 12),
            'appeal_items' => $this->appeals->list_for_prompt((int) $prompt['id'], 12),
            'viewer_can_review' => $this->permissions->can_review_prompts($user_id),
            'viewer_review' => $user_id > 0 && $this->permissions->can_review_prompts($user_id)
                ? $this->reviews->find_for_prompt_and_user((int) $prompt['id'], $user_id, 'peer')
                : [],
            'viewer_can_appeal' => $this->permissions->can_file_prompt_appeal($prompt, $user_id),
            'viewer_appeal' => $user_id > 0 ? $this->appeals->find_open_for_prompt_and_user((int) $prompt['id'], $user_id) : [],
            'viewer_can_resolve_appeals' => $this->permissions->can_resolve_prompt_appeals($user_id),
            'featured_prompts' => $this->featured_prompt_records(4),
        ];
    }

    /**
     * Returns workspace dashboard context.
     */
    public function workspace_context(): array
    {
        $user_id = get_current_user_id();
        $favorite_ids = $user_id > 0 ? $this->favorites->list_prompt_ids_for_user($user_id) : [];
        $review_queue = $this->review_queue_context($user_id, 10);
        $appeal_queue = $this->appeal_queue_context($user_id, 10);

        return [
            'my_prompts' => $user_id > 0 ? $this->prompts->list(['owner_user_id' => $user_id, 'limit' => 12], $user_id) : [],
            'shared_with_me' => $user_id > 0 ? $this->shared_prompts_for_user($user_id) : [],
            'public_library' => $this->public_prompts(8),
            'favorites' => $user_id > 0 ? $this->prompts->list(['include' => $favorite_ids, 'limit' => 12], $user_id) : [],
            'forks' => $user_id > 0 ? $this->forks_for_user($user_id) : [],
            'runs' => $user_id > 0 ? $this->runs->list_for_user($user_id, 8) : [],
            'conversations' => $user_id > 0 ? $this->conversations->list_for_user($user_id, 8) : [],
            'audit' => $user_id > 0 && $this->permissions->is_admin($user_id) ? $this->audit->recent(8) : [],
            'categories' => PromptCategoryRegistry::for_api(),
            'top_prompts' => $this->top_performing_prompts(6),
            'can_review_prompts' => $this->permissions->can_review_prompts($user_id),
            'review_queue' => $review_queue['items'],
            'review_queue_counts' => $review_queue['counts'],
            'can_resolve_prompt_appeals' => $this->permissions->can_resolve_prompt_appeals($user_id),
            'appeal_queue' => $appeal_queue['items'],
            'appeal_queue_counts' => $appeal_queue['counts'],
            'participant_state' => $user_id > 0 ? $this->reputation->get($user_id) : [],
        ];
    }

    /**
     * Returns member library context.
     */
    public function members_context(): array
    {