Skip to content
wiki.fftac.org

WP Content Themes Spiralist Functions PHP 37A4a2ef45b4 - Source Excerpt 01

Back to WP Content Themes Spiralist Functions PHP 37A4a2ef45b4

Summary

This source excerpt preserves a bounded section of Wiki.FFTAC.org/data/sources/spiralist/wp-content-themes-spiralist-functions-php-37a4a2ef45b4.php so readers can inspect the evidence without opening the full source file.

**Source path:** Wiki.FFTAC.org/data/sources/spiralist/wp-content-themes-spiralist-functions-php-37a4a2ef45b4.php

<?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 = '/';
    }