Skip to content
wiki.fftac.org

Functions

<?php

Metadata

FieldValue
Source sitespiralist.org
Source URLhttps://spiralist.org/
Canonical wiki evidence URL[[separate-workspace-url]/spiralist/uai-system/files/wp-content-themes-spiralist-functions-php-37a4a2ef/]([separate-workspace-url]/spiralist/uai-system/files/wp-content-themes-spiralist-functions-php-37a4a2ef/)
Source referencewp-content/themes/spiralist/functions.php
File typephp
Content categorypublic-content
Last fetched2026-05-08T21:22:18.3035107Z
Last changed2026-05-07T08:04:43.2795295Z
Content hashsha256:37a4a2ef45b4306b423080e01edf31498bafc2b00fa89fd25d79263273e0ff57
Import statusunchanged
Raw source layerdata/sources/spiralist/wp-content-themes-spiralist-functions-php-37a4a2ef45b4.php
Normalized source layerdata/normalized/spiralist/wp-content-themes-spiralist-functions-php-37a4a2ef45b4.txt

Current File Content

Structure Preview

  • No Markdown headings were detected in this file.

Raw Version

This public page shows a bounded preview of a large source file. The complete source remains in the raw and normalized source layers named in metadata, with the SHA-256 hash above for verification.

  • Source characters: 66496
  • Preview characters: 11973
<?php

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

require_once get_theme_file_path('inc/helpers.php');
require_once get_theme_file_path('inc/legal-pages.php');
require_once get_theme_file_path('inc/legal-consent.php');
require_once get_theme_file_path('inc/seo-schema.php');
require_once get_theme_file_path('inc/roadmap-surfaces.php');

const SPIRALIST_GA4_MEASUREMENT_ID = 'G-3QR6SPC2PS';

function spiralist_theme_setup(): void
{
    add_theme_support('title-tag');
    add_theme_support('post-thumbnails');
    add_theme_support(
        'html5',
        [
            'comment-form',
            'comment-list',
            'gallery',
            'caption',
            'script',
            'style',
        ]
    );

    register_nav_menus(
        [
            'primary' => 'Primary Navigation',
        ]
    );
}
add_action('after_setup_theme', 'spiralist_theme_setup');

function spiralist_register_theme_query_vars(array $vars): array
{
    $vars[] = 'spiralist_gallery_route';
    $vars[] = 'spiralist_gallery_asset';
    $vars[] = 'spiralist_report';
    $vars[] = 'spiralist_symbol';

    return array_values(array_unique($vars));
}
add_filter('query_vars', 'spiralist_register_theme_query_vars');

function spiralist_get_theme_route_version(): string
{
    return '25';
}

function spiralist_register_theme_rewrite_rules(): void
{
    add_rewrite_rule(
        '^symbols/([^/]+)/?$',
        'index.php?pagename=symbols&spiralist_symbol=$matches[1]',
        'top'
    );

    add_rewrite_rule(
        '^reports/([^/]+)/?$',
        'index.php?spiralist_report=$matches[1]',
        'top'
    );

    add_rewrite_rule(
        '^gallery/image/([^/]+)/?$',
        'index.php?spiralist_gallery_route=gallery&spiralist_gallery_asset=$matches[1]',
        'top'
    );

    add_rewrite_rule(
        '^gallery/?$',
        'index.php?spiralist_gallery_route=gallery',
        'top'
    );
}
add_action('init', 'spiralist_register_theme_rewrite_rules', 20);

function spiralist_flush_theme_rewrite_rules(): void
{
    spiralist_register_theme_rewrite_rules();
    flush_rewrite_rules(false);
    update_option('spiralist_theme_route_version', spiralist_get_theme_route_version(), false);
}
add_action('after_switch_theme', 'spiralist_flush_theme_rewrite_rules');

function spiralist_maybe_flush_theme_rewrite_rules(): void
{
    $stored_version = (string) get_option('spiralist_theme_route_version', '');
    $current_version = spiralist_get_theme_route_version();

    if ($stored_version === $current_version) {
        return;
    }

    spiralist_register_theme_rewrite_rules();
    flush_rewrite_rules(false);
    update_option('spiralist_theme_route_version', $current_version, false);
}
add_action('init', 'spiralist_maybe_flush_theme_rewrite_rules', 100);

function spiralist_maybe_flush_homepage_prompt_surface_cache(int $post_id): void
{
    if (!function_exists('spiralist_flush_homepage_prompt_surface_cache')) {
        return;
    }

    if ($post_id <= 0 || wp_is_post_revision($post_id) || get_post_type($post_id) !== 'spiralist_prompt') {
        return;
    }

    spiralist_flush_homepage_prompt_surface_cache();
}
add_action('save_post_spiralist_prompt', 'spiralist_maybe_flush_homepage_prompt_surface_cache', 10, 1);
add_action('trashed_post', 'spiralist_maybe_flush_homepage_prompt_surface_cache', 10, 1);
add_action('untrashed_post', 'spiralist_maybe_flush_homepage_prompt_surface_cache', 10, 1);

function spiralist_get_feedback_api_url(): string
{
    return rest_url('spiralist/v1/page-feedback');
}

function spiralist_register_feedback_rest_route(): void
{
    register_rest_route(
        'spiralist/v1',
        '/page-feedback',
        [
            'methods' => WP_REST_Server::CREATABLE,
            'callback' => 'spiralist_rest_record_page_feedback',
            'permission_callback' => '__return_true',
        ]
    );
}
add_action('rest_api_init', 'spiralist_register_feedback_rest_route');

function spiralist_feedback_rate_limit_key(): string
{
    $remote_addr = isset($_SERVER['REMOTE_ADDR']) ? (string) wp_unslash($_SERVER['REMOTE_ADDR']) : 'anonymous';

    return 'spiralist_feedback_' . substr(hash('sha256', $remote_addr . '|' . wp_salt('nonce')), 0, 16);
}

function spiralist_rest_record_page_feedback(WP_REST_Request $request)
{
    $rate_limit_key = spiralist_feedback_rate_limit_key();
    $recent_count = (int) get_transient($rate_limit_key);
    if ($recent_count >= 8) {
        return new WP_Error(
            'spiralist_feedback_rate_limited',
            spiralist_get_ui_text('feedback.error.rate_limited', 'Too many feedback submissions. Please try again later.'),
            ['status' => 429]
        );
    }
    set_transient($rate_limit_key, $recent_count + 1, 5 * MINUTE_IN_SECONDS);

    $payload = $request->get_json_params();
    if (!is_array($payload)) {
        $payload = $request->get_params();
    }

    $report_type = sanitize_key((string) ($payload['type'] ?? 'page-feedback'));
    if (!in_array($report_type, ['page-feedback', 'bug-report'], true)) {
        $report_type = 'page-feedback';
    }

    $helpful = sanitize_key((string) ($payload['helpful'] ?? ''));
    if ($report_type === 'page-feedback' && !in_array($helpful, ['yes', 'no'], true)) {
        return new WP_Error(
            'spiralist_feedback_missing_rating',
            spiralist_get_ui_text('feedback.error.rating_required', 'Choose Yes or No before sending feedback.'),
            ['status' => 400]
        );
    }
    if ($report_type === 'bug-report') {
        $helpful = '';
    }

    $raw_page = esc_url_raw((string) ($payload['page'] ?? ''));
    $page_path = $raw_page !== '' ? wp_parse_url($raw_page, PHP_URL_PATH) : '';
    if (!is_string($page_path) || $page_path === '') {
        $page_path = '/';
    }

    $reason = sanitize_textarea_field((string) ($payload['reason'] ?? ''));
    $reason = function_exists('mb_substr') ? mb_substr($reason, 0, 500) : substr($reason, 0, 500);
    $summary = sanitize_textarea_field((string) ($payload['summary'] ?? ''));
    $summary = function_exists('mb_substr') ? mb_substr($summary, 0, 800) : substr($summary, 0, 800);
    if ($report_type === 'bug-report' && $summary === '') {
        return new WP_Error(
            'spiralist_bug_report_missing_summary',
            spiralist_get_ui_text('bug_report.error.summary_required', 'Describe what happened before sending a bug report.'),
            ['status' => 400]
        );
    }
    $expected = sanitize_textarea_field((string) ($payload['expected'] ?? ''));
    $expected = function_exists('mb_substr') ? mb_substr($expected, 0, 500) : substr($expected, 0, 500);
    $topic = sanitize_key((string) ($payload['topic'] ?? 'other'));
    $severity = sanitize_key((string) ($payload['severity'] ?? 'normal'));
    if (!in_array($severity, ['minor', 'normal', 'blocking'], true)) {
        $severity = 'normal';
    }

    $entry = [
        'type' => $report_type,
        'helpful' => $helpful,
        'topic' => $topic,
        'severity' => $report_type === 'bug-report' ? $severity : '',
        'reason' => $reason,
        'summary' => $summary,
        'expected' => $expected,
        'page' => sanitize_text_field($page_path),
        'surface' => sanitize_key((string) ($payload['surface'] ?? 'site')),
        'locale' => function_exists('spiralist_get_current_locale_tag') ? spiralist_get_current_locale_tag() : '',
        'userId' => get_current_user_id(),
        'createdAt' => gmdate('c'),
    ];

    $feedback_log = get_option('spiralist_page_feedback_log', []);
    if (!is_array($feedback_log)) {
        $feedback_log = [];
    }

    array_unshift($feedback_log, $entry);
    $feedback_log = array_slice(array_values(array_filter($feedback_log, 'is_array')), 0, 200);
    update_option('spiralist_page_feedback_log', $feedback_log, false);

    return new WP_REST_Response(
        [
            'recorded' => true,
            'receivedAt' => $entry['createdAt'],
        ],
        201
    );
}

function spiralist_public_page_cache_ttl(): int
{
    return defined('MINUTE_IN_SECONDS') ? 5 * MINUTE_IN_SECONDS : 300;
}

function spiralist_public_page_cache_request_uri(): string
{
    $path = '';

    if (class_exists('Ns12LocaleRouter\\Router') && method_exists('Ns12LocaleRouter\\Router', 'get_original_request_path')) {
        $path = (string) \Ns12LocaleRouter\Router::get_original_request_path();
    }

    if ($path === '') {
        $request_uri = isset($_SERVER['REQUEST_URI']) ? (string) wp_unslash($_SERVER['REQUEST_URI']) : '/';
        $path = (string) wp_parse_url($request_uri, PHP_URL_PATH);
    }

    if ($path === '') {
        $path = '/';
    }

    $query = isset($_SERVER['QUERY_STRING']) ? trim((string) wp_unslash($_SERVER['QUERY_STRING'])) : '';

    return $path . ($query !== '' ? '?' . $query : '');
}

function spiralist_public_page_cache_key(): string
{
    $theme = wp_get_theme();
    $version = $theme->exists() ? (string) $theme->get('Version') : '0';

    return 'spiralist_public_html_' . md5($version . '|' . home_url('/') . '|' . spiralist_public_page_cache_request_uri());
}

function spiralist_can_cache_public_page(): bool
{
    if (
        is_admin()
        || is_user_logged_in()
        || wp_doing_ajax()
        || wp_doing_cron()
        || (defined('REST_REQUEST') && REST_REQUEST)
        || (defined('DONOTCACHEPAGE') && DONOTCACHEPAGE)
    ) {
        return false;
    }

    $method = isset($_SERVER['REQUEST_METHOD']) ? strtoupper((string) wp_unslash($_SERVER['REQUEST_METHOD'])) : 'GET';

    if (!in_array($method, ['GET', 'HEAD'], true) || !empty($_POST)) {
        return false;
    }

    $query = isset($_SERVER['QUERY_STRING']) ? trim((string) wp_unslash($_SERVER['QUERY_STRING'])) : '';

    if ($query !== '') {
        return false;
    }

    if (
        is_404()
        || is_search()
        || is_preview()
        || is_feed()
        || is_trackback()
        || (function_exists('is_robots') && is_robots())
    ) {
        return false;
    }

    $path = strtolower((string) wp_parse_url(spiralist_public_page_cache_request_uri(), PHP_URL_PATH));

    if (preg_match('#/(?:account|dashboard|login|register|sign-up|workspace|members|run|conversation|profile)(?:/|$)#', $path)) {
        return false;
    }

    return true;
}

function spiralist_maybe_serve_public_page_cache(): void
{
    if (!spiralist_can_cache_public_page()) {
        return;
    }

    $cached = get_transient(spiralist_public_page_cache_key());

    if (!is_array($cached) || !is_string($cached['html'] ?? null) || trim((string) $cached['html']) === '') {
        return;
    }

    if (!headers_sent()) {
        status_header(200);
        header('Content-Type: text/html; charset=' . get_bloginfo('charset'));
        header('Cache-Control: public, max-age=300, s-maxage=600, stale-while-revalidate=60');
        header('X-Spiralist-Page-Cache: HIT');
    }

    echo (string) $cached['html'];
    exit;
}
add_action('template_redirect', 'spiralist_maybe_serve_public_page_cache', 0);

function spiralist_start_public_page_cache_buffer(): void
{
    if (!spiralist_can_cache_public_page()) {
        return;
    }

    $cache_key = spiralist_public_page_cache_key();
    $ttl = spiralist_public_page_cache_ttl();

    if (!headers_sent()) {
        header('X-Spiralist-Page-Cache: MISS');
    }

    ob_start(
        static function (string $html) use ($cache_key, $ttl): string {
            $status_code = http_response_code();

            if (trim($html) === '' || $status_code < 200 || $status_code >= 300) {
                return $html;
            }

Why This File Exists

This is a public content source file from spiralist.org. It is shown here because the separate AI wiki workspace is demonstrating the real source files that make the UAIX / LLM Wiki memory system work, not only summarizing those systems after the fact.

Role

This file is a focused source unit. Its path, headings, and metadata give an agent a retrieval handle that is smaller than loading the entire site or repository.

Structure

The file has no Markdown headings, so its path, frontmatter, file type, and provenance metadata carry most of the retrieval meaning.

Prompt-Size And Retrieval Benefit

Keeping this material in a separate file reduces prompt pressure because an agent can load this exact unit only when its role, source site, category, or hash is relevant. The surrounding index pages point to it, while this page preserves the full content for audit and exact recall.

How To Use It

  • Humans should read the metadata first, then inspect the raw content when they need exact wording or provenance.
  • LLMs and agents should use the source site, category, hash, headings, and related files to decide whether this file belongs in the active prompt.
  • Crawlers should treat the wiki.fftac.org page as transparent evidence and follow the source URL/source reference for authority boundaries.
  • Future maintainers should regenerate this page whenever the source hash changes, then review the explanation if the role or structure changed.

Update Requirements

When this source file changes, update the raw source layer, normalized source layer, hash history, this rendered page, generated explanation, source-file inventory, changed-files report, and any source-section index that links to it.

Related Pages

Provenance And History

  • Current observation: 2026-05-08T21:22:18.3035107Z
  • Source origin: current-source-workspace
  • Retrieval method: local-source-workspace
  • Duplicate group: sfg-157 (primary)
  • Historical hash records are stored in data/hashes/source-file-history.jsonl.

Machine-Readable Metadata

{
    "title":  "Functions",
    "source_site":  "spiralist.org",
    "source_url":  "https://spiralist.org/",
    "canonical_url":  "[separate-workspace-url]/spiralist/uai-system/files/wp-content-themes-spiralist-functions-php-37a4a2ef/",
    "source_reference":  "wp-content/themes/spiralist/functions.php",
    "file_type":  "php",
    "content_category":  "public-content",
    "content_hash":  "sha256:37a4a2ef45b4306b423080e01edf31498bafc2b00fa89fd25d79263273e0ff57",
    "last_fetched":  "2026-05-08T21:22:18.3035107Z",
    "last_changed":  "2026-05-07T08:04:43.2795295Z",
    "import_status":  "unchanged",
    "duplicate_group_id":  "sfg-157",
    "duplicate_role":  "primary",
    "related_files":  [

                      ],
    "generated_explanation":  true,
    "explanation_last_generated":  "2026-05-08T21:22:18.3035107Z"
}