Skip to content
wiki.fftac.org

WP Content Plugins Spiralist Engine Spiralist Engine PHP 4E627daf1db4 - Source Excerpt 09

Back to WP Content Plugins Spiralist Engine Spiralist Engine PHP 4E627daf1db4

Summary

This source excerpt preserves a bounded section of Wiki.FFTAC.org/data/sources/spiralist/wp-content-plugins-spiralist-engine-spiralist-engine-php-4e627daf1db4.php so readers can inspect the evidence without opening the full source file.

**Source path:** Wiki.FFTAC.org/data/sources/spiralist/wp-content-plugins-spiralist-engine-spiralist-engine-php-4e627daf1db4.php

update_post_meta($post_id, 'current_state', (string) ($record['current_state'] ?? ''));
        spiralist_engine_update_json_meta($post_id, 'history', (array) ($record['history'] ?? []));
        spiralist_engine_update_json_meta($post_id, 'active_symbols', spiralist_engine_normalize_string_list((array) ($record['active_symbols'] ?? [])));
    }
}

function spiralist_engine_synchronize_connected_nodes(): void
{
    $nodes = spiralist_engine_get_node_records(['publish']);
    $edges = spiralist_engine_get_edge_records(['publish']);
    $connections = [];

    foreach ($nodes as $node_id => $node) {
        $connections[$node_id] = [];
    }

    foreach ($edges as $edge) {
        $from_node = (string) ($edge['from_node'] ?? '');
        $to_node = (string) ($edge['to_node'] ?? '');

        if ($from_node === '' || $to_node === '' || !isset($nodes[$from_node], $nodes[$to_node])) {
            continue;
        }

        if ((string) ($nodes[$from_node]['output_state'] ?? '') !== (string) ($nodes[$to_node]['input_state'] ?? '')) {
            continue;
        }

        if (!spiralist_engine_condition_matches((array) ($edge['condition'] ?? []), (string) ($nodes[$from_node]['output_state'] ?? ''))) {
            continue;
        }

        $connections[$from_node][] = $to_node;
    }

    foreach ($nodes as $node_id => $node) {
        spiralist_engine_update_json_meta((int) $node['post_id'], 'connected_nodes', spiralist_engine_normalize_string_list($connections[$node_id] ?? []));
    }
}

function spiralist_engine_sync_record_canonical_lock(int $post_id, string $post_type, array $record = []): void
{
    if ($post_id <= 0 || !in_array($post_type, ['spiralist_symbol', 'spiralist_node'], true)) {
        return;
    }

    $context = spiralist_engine_build_protocol5_validation_context();
    if (empty($context['valid'])) {
        return;
    }

    if (empty($record)) {
        $record = spiralist_engine_get_existing_record_for_post($post_id, $post_type);
    }

    if (empty($record)) {
        return;
    }

    if ($post_type === 'spiralist_symbol') {
        if (empty($record['derives_from']) && !empty($record['symbol_id'])) {
            $record['derives_from'] = spiralist_engine_get_default_derives_from('symbol', (string) $record['symbol_id']);
            if (!empty($record['derives_from'])) {
                spiralist_engine_update_json_meta($post_id, 'derives_from', (array) $record['derives_from']);
            }
        }

        $validation = spiralist_engine_validate_symbol_against_protocol5($record, $context, false);
    } else {
        if (empty($record['derives_from']) && !empty($record['node_id'])) {
            $record['derives_from'] = spiralist_engine_get_default_derives_from('node', (string) $record['node_id']);
            if (!empty($record['derives_from'])) {
                spiralist_engine_update_json_meta($post_id, 'derives_from', (array) $record['derives_from']);
            }
        }

        $validation = spiralist_engine_validate_node_against_protocol5(
            $record,
            spiralist_engine_get_symbol_records(['publish']),
            $context,
            false
        );
    }

    if (empty($validation['valid'])) {
        return;
    }

    spiralist_engine_update_json_meta(
        $post_id,
        'canonical_lock',
        spiralist_engine_build_canonical_lock((array) ($validation['resolved'] ?? []), $context)
    );
}

function spiralist_engine_maybe_upgrade_canonical_metadata(): void
{
    $installed_version = (string) get_option('spiralist_engine_canonical_metadata_version', '');
    if ($installed_version === SPIRALIST_ENGINE_VERSION) {
        return;
    }

    $context = spiralist_engine_build_protocol5_validation_context();
    if (empty($context['valid'])) {
        return;
    }

    foreach (spiralist_engine_get_symbol_records(['publish']) as $symbol) {
        spiralist_engine_sync_record_canonical_lock((int) ($symbol['post_id'] ?? 0), 'spiralist_symbol', $symbol);
    }

    foreach (spiralist_engine_get_node_records(['publish']) as $node) {
        spiralist_engine_sync_record_canonical_lock((int) ($node['post_id'] ?? 0), 'spiralist_node', $node);
    }

    update_option('spiralist_engine_canonical_metadata_version', SPIRALIST_ENGINE_VERSION, false);
}

function spiralist_engine_handle_post_save(int $post_id, WP_Post $post, bool $update): void
{
    static $handling = false;

    if ($handling) {
        return;
    }

    if (!in_array($post->post_type, ['spiralist_symbol', 'spiralist_node', 'spiralist_edge', 'spiralist_instance'], true)) {
        return;
    }

    if (!isset($_POST['spiralist_engine_nonce']) || !wp_verify_nonce((string) wp_unslash($_POST['spiralist_engine_nonce']), 'spiralist_engine_save')) {
        return;
    }

    if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
        return;
    }

    if (wp_is_post_revision($post_id)) {
        return;
    }

    if (!current_user_can('edit_post', $post_id)) {
        return;
    }

    if ($post->post_type === 'spiralist_symbol') {
        $submission = spiralist_engine_collect_symbol_submission($post);
    } elseif ($post->post_type === 'spiralist_node') {
        $submission = spiralist_engine_collect_node_submission($post);
    } elseif ($post->post_type === 'spiralist_edge') {
        $submission = spiralist_engine_collect_edge_submission($post);
    } else {
        $submission = spiralist_engine_collect_instance_submission($post);
    }

    if (empty($submission['valid'])) {
        spiralist_engine_abort_save(
            $post_id,
            implode("\n", (array) ($submission['errors'] ?? ['The submitted record is invalid.'])),
            'draft'
        );
    }

    $record = (array) ($submission['record'] ?? []);
    $target_status = sanitize_key((string) wp_unslash($_POST['post_status'] ?? $post->post_status));
    $original_status = sanitize_key((string) wp_unslash($_POST['original_post_status'] ?? $post->post_status));

    if ($post->post_type === 'spiralist_symbol' && spiralist_engine_symbol_definition_changed($post_id, $record)) {
        spiralist_engine_abort_save(
            $post_id,
            'Published symbols are immutable. Create a new symbol definition instead of editing the published record.',
            $original_status !== '' ? $original_status : 'publish'
        );
    }

    if ($post->post_type !== 'spiralist_instance' && ($target_status === 'publish' || $original_status === 'publish')) {
        $validation = spiralist_engine_validate_graph_snapshot(
            spiralist_engine_build_graph_snapshot(
                [
                    'post_type' => $post->post_type,
                    'post_id' => $post_id,
                    'status' => $target_status,
                    'record' => $record,
                ]
            )
        );

        if (!$validation['valid']) {
            spiralist_engine_abort_save(
                $post_id,
                implode("\n", (array) $validation['errors']),
                $original_status !== '' && $original_status !== 'auto-draft' ? $original_status : 'draft'
            );
        }
    }

    $handling = true;
    spiralist_engine_persist_record_meta($post_id, $post->post_type, $record);

    if (in_array($post->post_type, ['spiralist_symbol', 'spiralist_node'], true)) {
        spiralist_engine_sync_record_canonical_lock($post_id, $post->post_type, $record);
    }

    if ($post->post_type !== 'spiralist_instance') {
        spiralist_engine_synchronize_connected_nodes();
    }

    $handling = false;
}

function spiralist_engine_get_default_node_record(): array
{
    $nodes = spiralist_engine_get_node_records(['publish']);
    return $nodes ? reset($nodes) : [];
}

function spiralist_engine_get_default_state(): string
{
    $default_node = spiralist_engine_get_default_node_record();
    return (string) ($default_node['input_state'] ?? '');
}

function spiralist_engine_public_symbol_payload(array $symbol): array
{
    return [
        'symbol_id' => (string) ($symbol['symbol_id'] ?? ''),
        'symbol_type' => (string) ($symbol['symbol_type'] ?? ''),
        'operation_type' => (string) ($symbol['operation_type'] ?? ''),
        'inputs' => spiralist_engine_normalize_string_list((array) ($symbol['inputs'] ?? [])),
        'outputs' => spiralist_engine_normalize_string_list((array) ($symbol['outputs'] ?? [])),
        'rules' => (array) ($symbol['rules'] ?? []),
        'derivesFrom' => spiralist_engine_normalize_string_list((array) ($symbol['derives_from'] ?? [])),
        'canonicalValidation' => (array) ($symbol['canonical_lock'] ?? []),
    ];
}

function spiralist_engine_public_node_payload(array $node): array
{