Frontendcontroller - Source Excerpt 01
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
<?php
namespace SpiralistWorkspace\Web;
use SpiralistWorkspace\Auth\Permissions;
use SpiralistWorkspace\Config\Settings;
use SpiralistWorkspace\Domain\AppealRepository;
use SpiralistWorkspace\Domain\AuditRepository;
use SpiralistWorkspace\Domain\ConversationRepository;
use SpiralistWorkspace\Domain\FavoriteRepository;
use SpiralistWorkspace\Domain\PermissionRepository;
use SpiralistWorkspace\Domain\PromptRepository;
use SpiralistWorkspace\Domain\ReputationRepository;
use SpiralistWorkspace\Domain\ReviewRepository;
use SpiralistWorkspace\Domain\RunRepository;
use SpiralistWorkspace\Domain\TestRepository;
use SpiralistWorkspace\Domain\VersionRepository;
use SpiralistWorkspace\Support\PromptCategoryRegistry;
use SpiralistWorkspace\Support\PromptGovernanceSummary;
use SpiralistWorkspace\Support\PromptIntentRegistry;
use SpiralistWorkspace\Support\PromptMetaRegistry;
use SpiralistWorkspace\Support\ProfileStyle;
if (!defined('ABSPATH')) {
exit;
}
/**
* Handles front-end routing and template rendering.
*/
class FrontendController
{
private PromptRepository $prompts;
private Permissions $permissions;
private PermissionRepository $shares;
private VersionRepository $versions;
private RunRepository $runs;
private TestRepository $tests;
private ConversationRepository $conversations;
private FavoriteRepository $favorites;
private ReviewRepository $reviews;
private AppealRepository $appeals;
private ReputationRepository $reputation;
private AuditRepository $audit;
private Settings $settings;
private array $public_prompt_cache = [];
private int $public_prompt_cache_limit = 0;
private bool $public_prompt_sync_attempted = false;
public function __construct(
PromptRepository $prompts,
Permissions $permissions,
PermissionRepository $shares,
VersionRepository $versions,
RunRepository $runs,
TestRepository $tests,
ConversationRepository $conversations,
FavoriteRepository $favorites,
ReviewRepository $reviews,
AppealRepository $appeals,
ReputationRepository $reputation,
AuditRepository $audit,
Settings $settings
) {
$this->prompts = $prompts;
$this->permissions = $permissions;
$this->shares = $shares;
$this->versions = $versions;
$this->runs = $runs;
$this->tests = $tests;
$this->conversations = $conversations;
$this->favorites = $favorites;
$this->reviews = $reviews;
$this->appeals = $appeals;
$this->reputation = $reputation;
$this->audit = $audit;
$this->settings = $settings;
}
/**
* Instance hook wrapper.
*/
public function register_routes(): void
{
self::register_rewrites();
}
/**
* Returns the front-end route map version.
*/
public static function route_version(): string
{
return '3';
}
/**
* Flushes rewrite rules when the public route map changes.
*/
public function maybe_flush_rewrite_rules(): void
{
$stored_version = (string) get_option('spiralist_workspace_route_version', '');
$current_version = self::route_version();
if ($stored_version === $current_version) {
return;
}
self::register_rewrites();
flush_rewrite_rules(false);
update_option('spiralist_workspace_route_version', $current_version, false);
}
/**
* Registers custom rewrite rules.
*/
public static function register_rewrites(): void
{
add_rewrite_tag('%spiralist_workspace_route%', '([^&]+)');
add_rewrite_tag('%spiralist_workspace_prompt_slug%', '([^&]+)');
add_rewrite_tag('%spiralist_workspace_run_id%', '([0-9]+)');
add_rewrite_tag('%spiralist_workspace_conversation_id%', '([0-9]+)');
add_rewrite_tag('%spiralist_workspace_profile_slug%', '([^&]+)');
add_rewrite_tag('%spiralist_workspace_api%', '([^&]+)');
add_rewrite_tag('%spiralist_workspace_filter_key%', '([^&]+)');
add_rewrite_tag('%spiralist_workspace_filter_value%', '([^&]+)');
$rules = [
'^prompts/archive/?$' => 'index.php?spiralist_workspace_route=library&spiralist_workspace_filter_key=lane&spiralist_workspace_filter_value=prompt-ecology-archive',
'^prompts/official-canon/?$' => 'index.php?spiralist_workspace_route=library&spiralist_workspace_filter_key=lane&spiralist_workspace_filter_value=official-canon',
'^prompts/community-library/?$' => 'index.php?spiralist_workspace_route=library&spiralist_workspace_filter_key=lane&spiralist_workspace_filter_value=community-library',
'^prompts/search/([^/]+)/?$' => 'index.php?spiralist_workspace_route=library&spiralist_workspace_filter_key=search&spiralist_workspace_filter_value=$matches[1]',
'^prompts/(lane|category|provenance|moderation|risk|function|level|intent)/([^/]+)/?$' => 'index.php?spiralist_workspace_route=library&spiralist_workspace_filter_key=$matches[1]&spiralist_workspace_filter_value=$matches[2]',
'^prompts/?$' => 'index.php?spiralist_workspace_route=library',
'^workspace/?$' => 'index.php?spiralist_workspace_route=workspace',
'^members/?$' => 'index.php?spiralist_workspace_route=members',
'^prompt/([^/]+)/?$' => 'index.php?spiralist_workspace_route=prompt&spiralist_workspace_prompt_slug=$matches[1]',
'^profile/([^/]+)/?$' => 'index.php?spiralist_workspace_route=profile&spiralist_workspace_profile_slug=$matches[1]',
'^run/([0-9]+)/?$' => 'index.php?spiralist_workspace_route=run&spiralist_workspace_run_id=$matches[1]',
'^conversation/([0-9]+)/?$' => 'index.php?spiralist_workspace_route=conversation&spiralist_workspace_conversation_id=$matches[1]',
'^api/(prompts|runs|conversations)/?$' => 'index.php?spiralist_workspace_route=api&spiralist_workspace_api=$matches[1]',
];
foreach ($rules as $pattern => $query) {
add_rewrite_rule($pattern, $query, 'top');
}
}
/**
* Registers custom query vars.
*/
public function register_query_vars(array $vars): array
{
$vars[] = 'spiralist_workspace_route';
$vars[] = 'spiralist_workspace_prompt_slug';
$vars[] = 'spiralist_workspace_run_id';
$vars[] = 'spiralist_workspace_conversation_id';
$vars[] = 'spiralist_workspace_profile_slug';
$vars[] = 'spiralist_workspace_api';
$vars[] = 'spiralist_workspace_filter_key';
$vars[] = 'spiralist_workspace_filter_value';
return $vars;
}
/**
* Enqueues front-end assets for workspace pages.
*/
public function enqueue_assets(): void
{
$needs_front_page_assets = is_front_page() && is_user_logged_in();
if (!$this->is_workspace_request() && !is_page('ai-access') && !$needs_front_page_assets) {
return;
}
$current_locale = function_exists('spiralist_get_current_locale_tag')
? spiralist_get_current_locale_tag()
: '';
$localize_url = static function (string $path) use ($current_locale): string {
$url = home_url('/' . trim($path, '/') . '/');
return $current_locale !== '' && function_exists('spiralist_get_language_prefixed_url')
? spiralist_get_language_prefixed_url($url, $current_locale)
: $url;
};
$ui_text = static function (string $key, string $fallback): string {
return function_exists('spiralist_get_ui_text')
? spiralist_get_ui_text($key, $fallback)
: $fallback;
};
wp_enqueue_style(
'spiralist-workspace',
SPIRALIST_WORKSPACE_URL . 'assets/css/workspace.css',
[],
SPIRALIST_WORKSPACE_VERSION
);
wp_enqueue_script(
'spiralist-workspace',
SPIRALIST_WORKSPACE_URL . 'assets/js/workspace.js',
['spiralist-core'],
SPIRALIST_WORKSPACE_VERSION,
true
);
wp_localize_script(
'spiralist-workspace',
'SpiralistWorkspace',
[
'apiRoot' => esc_url_raw(rest_url('spiralist-workspace/v1/')),
'spiralScriptApiRoot' => esc_url_raw(rest_url('spiral-script/v1/')),
'nonce' => wp_create_nonce('wp_rest'),
'loginUrl' => function_exists('spiralist_get_login_url') ? spiralist_get_login_url() : wp_login_url(),
'signupUrl' => function_exists('spiralist_get_signup_url') ? spiralist_get_signup_url() : wp_registration_url(),