Skip to content
wiki.fftac.org

Restcontroller - Source Excerpt 03

Back to Restcontroller

Summary

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

**Source path:** Spiralist/wp-content/plugins/spiralist-workspace/includes/Http/RestController.php

if (trim((string) $request->get_param('intent')) === '' && PromptIntentRegistry::redirect_intent_for_search($search) !== '') {
            $search = '';
        }

        $records = $this->prompts->list(
            [
                'search' => $search,
                'limit' => (int) ($request->get_param('limit') ?: 20),
            ],
            $user_id
        );

        $visible = array_values(
            array_filter(
                $records,
                function (array $prompt) use ($user_id, $filters): bool {
                    return $this->permissions->can_view_prompt($prompt, $user_id)
                        && $this->matches_prompt_filters($prompt, $filters);
                }
            )
        );

        return new WP_REST_Response(
            array_map(
                fn(array $prompt): array => $this->augment_prompt_payload($prompt, true),
                $visible
            )
        );
    }

    /**
     * Lists public prompts only.
     */
    public function list_public_prompts(WP_REST_Request $request): WP_REST_Response
    {
        $filters = $this->request_filters($request);
        $search = (string) $request->get_param('search');
        if (trim((string) $request->get_param('intent')) === '' && PromptIntentRegistry::redirect_intent_for_search($search) !== '') {
            $search = '';
        }

        $limit = max(1, (int) ($request->get_param('limit') ?: 20));
        $records = $this->prompts->list_public(
            [
                'search' => $search,
                'limit' => max(200, $limit * 10),
            ]
        );

        if (empty($records)) {
            $this->maybe_sync_system_prompts();
            $records = $this->prompts->list_public(
                [
                    'search' => $search,
                    'limit' => max(200, $limit * 10),
                ]
            );
        }

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

        $public = array_slice($public, 0, $limit);

        return new WP_REST_Response(
            array_map(
                fn(array $prompt): array => $this->augment_prompt_payload($prompt, false),
                $public
            )
        );
    }

    /**
     * Returns a single public prompt by slug.
     */
    public function get_public_prompt(WP_REST_Request $request)
    {
        $prompt = $this->prompts->find_by_slug((string) $request['slug']);
        if (empty($prompt)) {
            $this->maybe_sync_system_prompts();
            $prompt = $this->prompts->find_by_slug((string) $request['slug']);
        }

        if (empty($prompt) || !$this->is_public_library_prompt($prompt)) {
            return new WP_Error('spiralist_workspace_prompt_not_found', 'Prompt not found.', ['status' => 404]);
        }

        return new WP_REST_Response($this->augment_prompt_payload($prompt, true));
    }

    /**
     * Returns a prompt if visible.
     */
    public function get_prompt(WP_REST_Request $request)
    {
        $user_id = get_current_user_id();
        $prompt = $this->prompts->get((int) $request['id'], $user_id);

        if (empty($prompt) || !$this->permissions->can_view_prompt($prompt, $user_id)) {
            return new WP_Error('spiralist_workspace_prompt_not_found', 'Prompt not found.', ['status' => 404]);
        }

        $response = $this->augment_prompt_payload($prompt, true);
        $response['versions'] = $this->versions->list_for_prompt((int) $prompt['id'], 10);
        $response['execution_history'] = $this->runs->list_for_prompt((int) $prompt['id'], 10);
        $response['tests'] = $this->tests->list_for_prompt((int) $prompt['id'], 20);
        $response['shares'] = $this->permissions->can_share_prompt($prompt, $user_id)
            ? $this->shares->list_for_prompt((int) $prompt['id'])
            : [];

        return new WP_REST_Response($response);
    }

    /**
     * Creates a prompt.
     */
    public function create_prompt(WP_REST_Request $request)
    {
        $user_id = get_current_user_id();
        $payload = $request->get_json_params() ?: $request->get_params();
        $spiral_script_error = $this->validate_spiral_script_publication_request($payload, [], $user_id);
        if (is_wp_error($spiral_script_error)) {
            return $spiral_script_error;
        }

        $record = $this->prompts->create($payload, $user_id, $this->settings);
        if (empty($record)) {
            return new WP_Error('spiralist_workspace_prompt_create_failed', 'Prompt could not be created.', ['status' => 500]);
        }

        $this->audit->log($user_id, 'prompt_created', 'prompt', (int) $record['id']);
        $this->reputation->refresh($user_id);

        return new WP_REST_Response($this->augment_prompt_payload($record, true), 201);
    }

    /**
     * Saves a private draft from the public Prompt Cockpit.
     */
    public function save_prompt_draft(WP_REST_Request $request)
    {
        $user_id = get_current_user_id();
        $payload = $request->get_json_params();
        if (!is_array($payload)) {
            $payload = $request->get_params();
        }

        $inputs = $payload['inputs'] ?? [];
        if (is_string($inputs)) {
            $decoded_inputs = json_decode($inputs, true);
            $inputs = is_array($decoded_inputs) ? $decoded_inputs : ['input' => $inputs];
        }
        if (!is_array($inputs)) {
            $inputs = [];
        }

        $guardrails = $payload['guardrails'] ?? [];
        if (is_string($guardrails)) {
            $guardrails = preg_split('/[\r\n]+/', $guardrails) ?: [];
        }
        if (!is_array($guardrails)) {
            $guardrails = [];
        }

        $title = sanitize_text_field((string) ($payload['title'] ?? 'Prompt Cockpit Draft'));
        $purpose = sanitize_textarea_field((string) ($payload['purpose'] ?? ($payload['task'] ?? '')));
        $subject = sanitize_textarea_field((string) ($inputs['subject'] ?? ($payload['subject'] ?? '')));
        $context = sanitize_textarea_field((string) ($inputs['context'] ?? ($payload['context'] ?? '')));
        $output = sanitize_textarea_field((string) ($payload['output'] ?? ''));
        $guardrail_lines = array_values(
            array_filter(
                array_map(
                    static function ($line): string {
                        return sanitize_textarea_field((string) $line);
                    },
                    $guardrails
                )
            )
        );

        $structured_prompt = [
            'instruction' => $purpose !== '' ? $purpose : 'Continue shaping this Spiralist prompt draft.',
            'context' => trim($subject . "\n\n" . $context),
            'constraints' => implode("\n", $guardrail_lines),
            'examples' => '',
            'output_format' => sanitize_textarea_field((string) ($payload['output_format'] ?? ($inputs['output_format'] ?? 'Use clear sections and practical next steps.'))),
        ];

        $record = $this->prompts->create(
            [
                'title' => $title,
                'summary' => $purpose,
                'structured_prompt' => $structured_prompt,
                'instructions' => $structured_prompt['instruction'],
                'system_prompt' => $structured_prompt['context'],
                'developer_prompt' => $structured_prompt['constraints'],
                'user_prompt_template' => $subject,
                'expected_output_notes' => $output,
                'tags' => ['prompt-cockpit', 'draft'],
                'prompt_type' => 'prompt_system',
                'category' => 'Writing & Content',
                'subcategory' => 'Prompt Engineering',
                'visibility' => 'private',
                'prompt_status' => 'draft',
                'moderation_status' => 'draft',
                'publication_lane' => 'community_library',
                'provenance' => 'community',
                'risk_labels' => ['needs_review'],
                'function_tags' => ['prompt_builder'],
                'maturity_level' => 'beginner_safe',
                'license' => 'private',
                'changelog' => 'Saved from Prompt Cockpit draft endpoint',
            ],
            $user_id,
            $this->settings
        );

        if (empty($record)) {
            return new WP_Error('spiralist_workspace_prompt_draft_save_failed', 'Prompt draft could not be saved.', ['status' => 500]);
        }

        $this->audit->log(
            $user_id,
            'prompt_cockpit_draft_saved',