Skip to content
wiki.fftac.org

Installer - Source Excerpt 01

Back to Installer

Summary

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

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

<?php

namespace SpiralistWorkspace;

use SpiralistWorkspace\Auth\Roles;
use SpiralistWorkspace\Domain\PromptRepository;
use SpiralistWorkspace\Services\GovernanceMaintenance;
use SpiralistWorkspace\Web\FrontendController;

if (!defined('ABSPATH')) {
    exit;
}

/**
 * Installs and upgrades plugin storage.
 */
class Installer
{
    public const SCHEMA_VERSION = '5';

    /**
     * Returns a fully qualified table name.
     */
    public static function table(string $suffix): string
    {
        global $wpdb;

        $map = [
            'prompt_versions' => $wpdb->prefix . 'spiralist_workspace_prompt_versions',
            'prompt_permissions' => $wpdb->prefix . 'spiralist_workspace_prompt_permissions',
            'prompt_runs' => $wpdb->prefix . 'spiralist_workspace_prompt_runs',
            'conversations' => $wpdb->prefix . 'spiralist_workspace_conversations',
            'conversation_messages' => $wpdb->prefix . 'spiralist_workspace_conversation_messages',
            'audit_log' => $wpdb->prefix . 'spiralist_workspace_audit_log',
            'favorites' => $wpdb->prefix . 'spiralist_workspace_favorites',
            'prompt_tests' => $wpdb->prefix . 'spiralist_workspace_prompt_tests',
            'prompt_reviews' => $wpdb->prefix . 'spiralist_workspace_prompt_reviews',
            'prompt_appeals' => $wpdb->prefix . 'spiralist_workspace_prompt_appeals',
        ];

        return (string) ($map[$suffix] ?? '');
    }

    /**
     * Creates tables, roles, and rewrite rules.
     */
    public static function activate(): void
    {
        self::create_schema();
        PromptRepository::migrate_content_types();
        Roles::register();
        PromptRepository::register_post_type();
        PromptRepository::register_taxonomies();
        FrontendController::register_rewrites();

        update_option('spiralist_workspace_schema_version', self::SCHEMA_VERSION, false);
        flush_rewrite_rules(false);
    }

    /**
     * Flushes rewrites on deactivation.
     */
    public static function deactivate(): void
    {
        GovernanceMaintenance::unschedule();
        flush_rewrite_rules(false);
    }

    /**
     * Runs dbDelta for all custom tables.
     */
    public static function create_schema(): void
    {
        global $wpdb;

        require_once ABSPATH . 'wp-admin/includes/upgrade.php';

        $charset = $wpdb->get_charset_collate();

        $sql = [];
        $sql[] = 'CREATE TABLE ' . self::table('prompt_versions') . " (
            id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
            prompt_post_id bigint(20) unsigned NOT NULL,
            version_number int(11) unsigned NOT NULL,
            full_snapshot_json longtext NOT NULL,
            created_by_user_id bigint(20) unsigned NOT NULL,
            created_utc datetime NOT NULL,
            changelog text NULL,
            PRIMARY KEY  (id),
            UNIQUE KEY prompt_version (prompt_post_id, version_number),
            KEY created_by_user_id (created_by_user_id),
            KEY created_utc (created_utc)
        ) {$charset};";

        $sql[] = 'CREATE TABLE ' . self::table('prompt_permissions') . " (
            id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
            prompt_post_id bigint(20) unsigned NOT NULL,
            shared_with_user_id bigint(20) unsigned NOT NULL,
            granted_by_user_id bigint(20) unsigned NOT NULL,
            permission_type varchar(50) NOT NULL,
            created_utc datetime NOT NULL,
            PRIMARY KEY  (id),
            UNIQUE KEY prompt_share (prompt_post_id, shared_with_user_id, permission_type),
            KEY shared_with_user_id (shared_with_user_id),
            KEY granted_by_user_id (granted_by_user_id)
        ) {$charset};";

        $sql[] = 'CREATE TABLE ' . self::table('prompt_runs') . " (
            id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
            prompt_post_id bigint(20) unsigned NOT NULL,
            user_id bigint(20) unsigned NOT NULL,
            conversation_id bigint(20) unsigned NULL,
            version_number_used int(11) unsigned NOT NULL,
            model_used varchar(120) NOT NULL,
            request_payload_json longtext NOT NULL,
            response_payload_json longtext NULL,
            input_text longtext NULL,
            output_text longtext NULL,
            status varchar(50) NOT NULL,
            created_utc datetime NOT NULL,
            completed_utc datetime NULL,
            cost_estimate decimal(12,6) NOT NULL DEFAULT 0,
            token_usage_json longtext NULL,
            error_message text NULL,
            openai_response_id varchar(120) NULL,
            PRIMARY KEY  (id),
            KEY prompt_post_id (prompt_post_id),
            KEY user_id (user_id),
            KEY conversation_id (conversation_id),
            KEY status (status),
            KEY created_utc (created_utc)
        ) {$charset};";

        $sql[] = 'CREATE TABLE ' . self::table('conversations') . " (
            id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
            prompt_post_id bigint(20) unsigned NOT NULL,
            owner_user_id bigint(20) unsigned NOT NULL,
            title varchar(200) NOT NULL,
            visibility varchar(32) NOT NULL,
            created_utc datetime NOT NULL,
            updated_utc datetime NOT NULL,
            archived_utc datetime NULL,
            openai_reference varchar(120) NULL,
            conversation_settings_json longtext NULL,
            PRIMARY KEY  (id),
            KEY prompt_post_id (prompt_post_id),
            KEY owner_user_id (owner_user_id),
            KEY visibility (visibility),
            KEY updated_utc (updated_utc)
        ) {$charset};";

        $sql[] = 'CREATE TABLE ' . self::table('conversation_messages') . " (
            id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
            conversation_id bigint(20) unsigned NOT NULL,
            role varchar(20) NOT NULL,
            content longtext NOT NULL,
            created_utc datetime NOT NULL,
            openai_reference varchar(120) NULL,
            metadata_json longtext NULL,
            PRIMARY KEY  (id),
            KEY conversation_id (conversation_id),
            KEY role (role),
            KEY created_utc (created_utc)
        ) {$charset};";

        $sql[] = 'CREATE TABLE ' . self::table('audit_log') . " (
            id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
            actor_user_id bigint(20) unsigned NULL,
            event_type varchar(100) NOT NULL,
            object_type varchar(50) NOT NULL,
            object_id bigint(20) unsigned NULL,
            context_json longtext NULL,
            created_utc datetime NOT NULL,
            PRIMARY KEY  (id),
            KEY actor_user_id (actor_user_id),
            KEY event_type (event_type),
            KEY object_type (object_type),
            KEY created_utc (created_utc)
        ) {$charset};";

        $sql[] = 'CREATE TABLE ' . self::table('favorites') . " (
            id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
            prompt_post_id bigint(20) unsigned NOT NULL,
            user_id bigint(20) unsigned NOT NULL,
            created_utc datetime NOT NULL,
            PRIMARY KEY  (id),
            UNIQUE KEY favorite_prompt_user (prompt_post_id, user_id),
            KEY user_id (user_id),
            KEY created_utc (created_utc)
        ) {$charset};";

        $sql[] = 'CREATE TABLE ' . self::table('prompt_tests') . " (
            id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
            prompt_post_id bigint(20) unsigned NOT NULL,
            created_by_user_id bigint(20) unsigned NOT NULL,
            input_text longtext NOT NULL,
            expected_output_text longtext NOT NULL,
            variables_json longtext NULL,
            match_strategy varchar(32) NOT NULL,
            last_run_id bigint(20) unsigned NULL,
            last_result_status varchar(32) NULL,
            last_result_json longtext NULL,
            created_utc datetime NOT NULL,
            updated_utc datetime NOT NULL,
            PRIMARY KEY  (id),
            KEY prompt_post_id (prompt_post_id),
            KEY created_by_user_id (created_by_user_id),
            KEY last_run_id (last_run_id),
            KEY last_result_status (last_result_status),
            KEY created_utc (created_utc)
        ) {$charset};";

        $sql[] = 'CREATE TABLE ' . self::table('prompt_reviews') . " (
            id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
            prompt_post_id bigint(20) unsigned NOT NULL,
            reviewer_user_id bigint(20) unsigned NULL,
            review_kind varchar(20) NOT NULL,
            decision varchar(32) NOT NULL,
            reason text NULL,
            created_utc datetime NOT NULL,