Restcontroller - Source Excerpt 07
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
)
);
return new WP_REST_Response(array_map(fn(array $prompt): array => $this->augment_prompt_payload($prompt, false), $public));
}
/**
* Returns the canonical prompt category hierarchy.
*/
public function categories(): WP_REST_Response
{
return new WP_REST_Response(
[
'domains' => PromptCategoryRegistry::for_api(),
'subcategory_count' => count(PromptCategoryRegistry::subcategories()),
'intents' => PromptIntentRegistry::for_api(),
'intent_count' => count(PromptIntentRegistry::for_api()),
'facets' => PromptMetaRegistry::for_api(),
]
);
}
/**
* Returns the current participant trust and cooldown state.
*/
public function get_my_reputation(): WP_REST_Response
{
return new WP_REST_Response($this->reputation->get(get_current_user_id()));
}
/**
* Returns the current user's profile style settings.
*/
public function get_profile_style(): WP_REST_Response
{
$user_id = get_current_user_id();
$user = wp_get_current_user();
return new WP_REST_Response(
array_merge(
ProfileStyle::get($user_id),
[
'scope_class' => ProfileStyle::scope_class($user_id),
'profile_url' => $user instanceof \WP_User && $user->user_nicename !== ''
? home_url('/profile/' . rawurlencode($user->user_nicename) . '/')
: '',
]
)
);
}
/**
* Updates the current user's sanitized profile style.
*/
public function update_profile_style(WP_REST_Request $request): WP_REST_Response
{
$user_id = get_current_user_id();
$style_prompt = (string) $request->get_param('style_prompt');
$custom_css = (string) $request->get_param('custom_css');
$result = ProfileStyle::update($user_id, $style_prompt, $custom_css);
$user = wp_get_current_user();
$result['scope_class'] = ProfileStyle::scope_class($user_id);
$result['profile_url'] = $user instanceof \WP_User && $user->user_nicename !== ''
? home_url('/profile/' . rawurlencode($user->user_nicename) . '/')
: '';
return new WP_REST_Response($result);
}
/**
* Returns the latest scheduled governance-maintenance result.
*/
public function get_governance_maintenance_status(): WP_REST_Response
{
return new WP_REST_Response(
[
'scheduled' => (bool) wp_next_scheduled(GovernanceMaintenance::HOOK),
'next_run_utc' => $this->scheduled_utc(GovernanceMaintenance::HOOK),
'last_run' => $this->governance_maintenance->status(),
]
);
}
/**
* Runs governance maintenance immediately for admins.
*/
public function run_governance_maintenance(WP_REST_Request $request): WP_REST_Response
{
$limit = (int) ($request->get_param('limit') ?: 250);
return new WP_REST_Response(
[
'ok' => true,
'scheduled' => (bool) wp_next_scheduled(GovernanceMaintenance::HOOK),
'result' => $this->governance_maintenance->run($limit),
'next_run_utc' => $this->scheduled_utc(GovernanceMaintenance::HOOK),
]
);
}
/**
* Returns one immutable prompt version.
*/
public function get_prompt_version(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]);
}
$version = $this->versions->get_for_prompt((int) $request['id'], (int) $request['version']);
if (empty($version)) {
return new WP_Error('spiralist_workspace_version_not_found', 'Version not found.', ['status' => 404]);
}
return new WP_REST_Response($version);
}
/**
* Returns a field-level diff between two prompt versions.
*/
public function diff_prompt_versions(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]);
}
$diff = $this->versions->diff((int) $request['id'], (int) $request['left'], (int) $request['right']);
return empty($diff)
? new WP_Error('spiralist_workspace_version_not_found', 'Version diff could not be built.', ['status' => 404])
: new WP_REST_Response($diff);
}
/**
* Rolls a prompt back by creating a new version from an older snapshot.
*/
public function rollback_prompt_version(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_edit_prompt($prompt, $user_id)) {
return new WP_Error('spiralist_workspace_prompt_forbidden', 'Prompt not found.', ['status' => 404]);
}
$version = $this->versions->get_for_prompt((int) $request['id'], (int) $request['version']);
$snapshot = (array) ($version['snapshot'] ?? []);
if (empty($snapshot)) {
return new WP_Error('spiralist_workspace_version_not_found', 'Version not found.', ['status' => 404]);
}
$snapshot['changelog'] = 'Rolled back to version ' . (int) $request['version'];
$updated = $this->prompts->update((int) $request['id'], $snapshot, $user_id);
$this->audit->log($user_id, 'prompt_version_rolled_back', 'prompt', (int) $request['id'], ['version' => (int) $request['version']]);
return new WP_REST_Response($this->prompts->for_api($updated, true));
}
/**
* Looks up a user by login or email.
*/
public function find_user(WP_REST_Request $request)
{
$query = trim((string) $request->get_param('q'));
if ($query === '' || strlen($query) < 3 || strpos($query, '@') !== false) {
return new WP_Error('spiralist_workspace_user_not_found', 'User not found.', ['status' => 404]);
}
$target = get_user_by('login', sanitize_user($query, true));
if (!$target instanceof \WP_User) {
return new WP_Error('spiralist_workspace_user_not_found', 'User not found.', ['status' => 404]);
}
return new WP_REST_Response(
[
'id' => (int) $target->ID,
'display_name' => $target->display_name,
'user_login' => $target->user_login,
]
);
}
/**
* Permission callback for logged-in actions.
*/
public function require_logged_in(): bool
{
return is_user_logged_in();
}
/**
* Permission callback for prompt creation.
*/
public function require_prompt_create(): bool
{
return is_user_logged_in() && current_user_can('create_prompts');
}
/**
* Permission callback for browser-originated Prompt Cockpit draft saves.
*
* WordPress REST cookie authentication normally validates X-WP-Nonce. This
* endpoint performs an explicit nonce check as well because it creates
* private prompt records for the signed-in user and should not be callable
* by a cross-site form post.
*/
public function require_prompt_draft_save(WP_REST_Request $request): bool
{
if (!is_user_logged_in() || !current_user_can('create_prompts')) {
return false;
}
$nonce = (string) $request->get_header('X-WP-Nonce');
if ($nonce === '') {
$nonce = (string) $request->get_param('_wpnonce');
}
return $nonce !== '' && wp_verify_nonce($nonce, 'wp_rest') !== false;
}
/**
* Permission callback for admin actions.
*/
public function require_workspace_admin(): bool
{
return is_user_logged_in() && ($this->permissions->is_admin(get_current_user_id()));
}
/**
* Permission callback for share-target lookups.
*/
public function require_share_lookup(): bool
{
$user_id = get_current_user_id();