Skip to content
wiki.fftac.org

Spiralist Engine - Source Excerpt 10

Back to Spiralist Engine

Summary

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

**Source path:** Spiralist/wp-content/plugins/spiralist-engine/spiralist-engine.php

$presentation = (array) ($node['presentation'] ?? []);
    $payload = [
        'id' => (string) ($node['node_id'] ?? ''),
        'type' => (string) ($presentation['type'] ?? 'node'),
        'mode' => (string) ($presentation['mode'] ?? 'minimal'),
        'label' => (string) ($presentation['label'] ?? ($node['post_title'] ?? $node['node_id'] ?? 'Node')),
        'canonicalId' => (string) ($presentation['canonicalId'] ?? ($node['node_id'] ?? '')),
        'meaning' => (string) ($presentation['meaning'] ?? ''),
        'definition' => (string) ($presentation['definition'] ?? ''),
        'transformationChain' => (string) ($presentation['transformationChain'] ?? spiralist_engine_chain_to_text(
            (array) ($node['transformation_chain'] ?? []),
            (string) ($node['input_state'] ?? ''),
            (string) ($node['output_state'] ?? '')
        )),
        'derivation' => (string) ($presentation['derivation'] ?? ''),
        'related' => array_values(array_filter((array) ($presentation['related'] ?? []), 'is_string')),
        'input' => (string) ($node['input_state'] ?? ''),
        'output' => (string) ($node['output_state'] ?? ''),
        'inputState' => (string) ($node['input_state'] ?? ''),
        'outputState' => (string) ($node['output_state'] ?? ''),
        'symbols' => spiralist_engine_normalize_string_list((array) ($node['symbols'] ?? [])),
        'derivesFrom' => spiralist_engine_normalize_string_list((array) ($node['derives_from'] ?? [])),
        'operationType' => spiralist_engine_get_chain_transformation((array) ($node['transformation_chain'] ?? [])),
        'connectedNodes' => spiralist_engine_normalize_string_list((array) ($node['connected_nodes'] ?? [])),
        'executionEnabled' => !empty($node['execution_enabled']),
        'canonicalValidation' => (array) ($node['canonical_lock'] ?? []),
    ];

    foreach (['x', 'y', 'w', 'h', 'glyph', 'aliases', 'sourceAxiomId'] as $key) {
        if (array_key_exists($key, $presentation)) {
            $payload[$key] = $presentation[$key];
        }
    }

    return $payload;
}

function spiralist_engine_merge_public_nodes(array $visual, array $runtime): array
{
    $merged = $visual;

    foreach ($runtime as $key => $value) {
        if (in_array($key, ['executionEnabled', 'input', 'output', 'inputState', 'outputState', 'connectedNodes', 'symbols', 'operationType'], true)) {
            $merged[$key] = $value;
            continue;
        }

        if (is_array($value) && !empty($value)) {
            $merged[$key] = $value;
            continue;
        }

        if ($value !== '' && $value !== null) {
            $merged[$key] = $value;
        }
    }

    return $merged;
}

function spiralist_engine_get_manuscript_field_payload(): array
{
    static $payload = null;

    if (is_array($payload)) {
        return $payload;
    }

    $payload = spiralist_engine_get_visual_dataset();
    $payload['nodes'] = array_values(array_filter((array) ($payload['nodes'] ?? []), 'is_array'));
    $payload['relations'] = array_values(array_filter((array) ($payload['relations'] ?? []), 'is_array'));

    foreach ($payload['nodes'] as $index => $node) {
        $payload['nodes'][$index]['executionEnabled'] = false;
        $payload['nodes'][$index]['inputState'] = (string) ($node['inputState'] ?? ($node['input'] ?? ''));
        $payload['nodes'][$index]['outputState'] = (string) ($node['outputState'] ?? ($node['output'] ?? ''));
    }

    $node_index = [];

    foreach ($payload['nodes'] as $index => $node) {
        $node_id = (string) ($node['id'] ?? '');
        if ($node_id !== '') {
            $node_index[$node_id] = $index;
        }
    }

    foreach (spiralist_engine_get_node_records(['publish']) as $node) {
        $runtime_node = spiralist_engine_public_node_payload($node);
        $runtime_id = (string) ($runtime_node['id'] ?? '');

        if ($runtime_id !== '' && isset($node_index[$runtime_id])) {
            $payload['nodes'][$node_index[$runtime_id]] = spiralist_engine_merge_public_nodes(
                (array) $payload['nodes'][$node_index[$runtime_id]],
                $runtime_node
            );
            continue;
        }

        $payload['nodes'][] = $runtime_node;
    }

    $relation_ids = [];

    foreach ($payload['relations'] as $relation) {
        $relation_ids[(string) ($relation['id'] ?? '')] = true;
    }

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

        if ($from_node === '' || $to_node === '') {
            continue;
        }

        $relation_id = 'execution.' . sanitize_title($from_node . '.' . $to_node . '.' . $edge['post_id']);
        if (isset($relation_ids[$relation_id])) {
            continue;
        }

        $payload['relations'][] = [
            'id' => $relation_id,
            'type' => 'execution',
            'from' => $from_node,
            'to' => $to_node,
            'mode' => 'minimal',
        ];
    }

    $default_state = spiralist_engine_get_default_state();
    $payload['runtime'] = [
        'defaultState' => $default_state,
        'nextNodes' => array_values(array_map('spiralist_engine_public_node_payload', spiralist_engine_get_next_nodes_for_state($default_state))),
        'executeUrl' => spiralist_engine_get_execute_endpoint_url(),
        'instanceUrl' => spiralist_engine_get_instance_endpoint_url(),
        'pathUrl' => spiralist_engine_get_path_endpoint_url(),
    ];

    return $payload;
}

function spiralist_engine_get_nodes_endpoint_url(): string
{
    return rest_url('spiralist/v1/nodes');
}

function spiralist_engine_get_symbols_endpoint_url(): string
{
    return rest_url('spiralist/v1/symbols');
}

function spiralist_engine_get_node_detail_endpoint_url(): string
{
    return trailingslashit(rest_url('spiralist/v1/node')) . '{id}';
}

function spiralist_engine_get_execute_endpoint_url(): string
{
    return rest_url('spiralist/v1/execute');
}

function spiralist_engine_get_instance_endpoint_url(): string
{
    return rest_url('spiralist/v1/instance');
}

function spiralist_engine_get_path_endpoint_url(): string
{
    return rest_url('spiralist/v1/path');
}

function spiralist_engine_find_node_record(string $node_id): array
{
    $node_id = spiralist_engine_sanitize_identifier($node_id);
    if ($node_id === '') {
        return [];
    }

    $nodes = spiralist_engine_get_node_records(['publish']);
    return $nodes[$node_id] ?? [];
}

function spiralist_engine_get_next_nodes_for_state(string $state): array
{
    $matches = [];

    foreach (spiralist_engine_get_node_records(['publish']) as $node) {
        if ((string) ($node['input_state'] ?? '') === $state) {
            $matches[] = $node;
        }
    }

    return $matches;
}

function spiralist_engine_find_instance_post_id(int $user_id): int
{
    if ($user_id <= 0) {
        return 0;
    }

    $posts = get_posts(
        [
            'post_type' => 'spiralist_instance',
            'post_status' => ['publish'],
            'posts_per_page' => 1,
            'meta_key' => 'user_id',
            'meta_value' => $user_id,
            'fields' => 'ids',
        ]
    );

    return !empty($posts[0]) ? (int) $posts[0] : 0;
}

function spiralist_engine_get_instance_state(int $user_id): array
{
    if ($user_id <= 0) {
        $default_state = spiralist_engine_get_default_state();
        $next_nodes = array_values(array_map('spiralist_engine_public_node_payload', spiralist_engine_get_next_nodes_for_state($default_state)));

        return [
            'instance_id' => 0,
            'instanceId' => 'client',
            'user_id' => 0,
            'current_node' => '',
            'currentNode' => '',
            'current_state' => $default_state,
            'currentState' => $default_state,
            'history' => [],
            'active_symbols' => [],
            'activeSymbols' => [],
            'next_nodes' => $next_nodes,
            'nextNodes' => $next_nodes,
            'storage' => 'client',
        ];
    }

    $instance_post_id = spiralist_engine_find_instance_post_id($user_id);
    if ($instance_post_id <= 0) {
        $default_state = spiralist_engine_get_default_state();
        $next_nodes = array_values(array_map('spiralist_engine_public_node_payload', spiralist_engine_get_next_nodes_for_state($default_state)));

        return [
            'instance_id' => 0,
            'instanceId' => 'user-' . $user_id,
            'user_id' => $user_id,
            'current_node' => '',
            'currentNode' => '',
            'current_state' => $default_state,