Skip to content
wiki.fftac.org

Spiralist Engine - Source Excerpt 06

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

$input_state = sanitize_text_field((string) wp_unslash($_POST['spiralist_input_state'] ?? ''));
    $output_state = sanitize_text_field((string) wp_unslash($_POST['spiralist_output_state'] ?? ''));
    $transformation_chain = spiralist_engine_parse_json_field((string) wp_unslash($_POST['spiralist_transformation_chain'] ?? ''), 'transformation_chain');
    $derives_from = spiralist_engine_parse_array_field((string) wp_unslash($_POST['spiralist_node_derives_from'] ?? ''));
    $presentation = spiralist_engine_parse_json_field((string) wp_unslash($_POST['spiralist_presentation'] ?? ''), 'presentation');

    if ($node_id === '') {
        $errors[] = 'node_id is required.';
    }

    if (!$symbols['valid']) {
        $errors[] = $symbols['error'];
    }

    if (!$transformation_chain['valid']) {
        $errors[] = $transformation_chain['error'];
    }

    if (!$derives_from['valid']) {
        $errors[] = $derives_from['error'];
    }

    if (!$presentation['valid']) {
        $errors[] = $presentation['error'];
    }

    return [
        'valid' => empty($errors),
        'errors' => $errors,
        'record' => [
            'post_id' => $post->ID,
            'node_id' => $node_id,
            'symbols' => $symbols['valid'] ? $symbols['value'] : [],
            'input_state' => $input_state,
            'output_state' => $output_state,
            'transformation_chain' => $transformation_chain['valid'] ? $transformation_chain['value'] : [],
            'derives_from' => $derives_from['valid']
                ? $derives_from['value']
                : spiralist_engine_get_default_derives_from('node', $node_id),
            'connected_nodes' => spiralist_engine_read_json_meta($post->ID, 'connected_nodes', []),
            'presentation' => $presentation['valid'] ? $presentation['value'] : [],
            'canonical_lock' => spiralist_engine_read_json_meta($post->ID, 'canonical_lock', []),
        ],
    ];
}

function spiralist_engine_collect_edge_submission(WP_Post $post): array
{
    $errors = [];

    $from_node = spiralist_engine_sanitize_identifier((string) wp_unslash($_POST['spiralist_from_node'] ?? ''));
    $to_node = spiralist_engine_sanitize_identifier((string) wp_unslash($_POST['spiralist_to_node'] ?? ''));
    $condition = spiralist_engine_parse_json_field((string) wp_unslash($_POST['spiralist_condition'] ?? ''), 'condition');

    if ($from_node === '') {
        $errors[] = 'from_node is required.';
    }

    if ($to_node === '') {
        $errors[] = 'to_node is required.';
    }

    if (!$condition['valid']) {
        $errors[] = $condition['error'];
    }

    return [
        'valid' => empty($errors),
        'errors' => $errors,
        'record' => [
            'post_id' => $post->ID,
            'from_node' => $from_node,
            'to_node' => $to_node,
            'condition' => $condition['valid'] ? $condition['value'] : [],
        ],
    ];
}

function spiralist_engine_collect_instance_submission(WP_Post $post): array
{
    $errors = [];

    $user_id = max(0, (int) wp_unslash($_POST['spiralist_instance_user_id'] ?? 0));
    $current_node = spiralist_engine_sanitize_identifier((string) wp_unslash($_POST['spiralist_instance_current_node'] ?? ''));
    $current_state = sanitize_text_field((string) wp_unslash($_POST['spiralist_instance_current_state'] ?? ''));
    $history = spiralist_engine_parse_json_field((string) wp_unslash($_POST['spiralist_instance_history'] ?? ''), 'history', 'array');
    $active_symbols = spiralist_engine_parse_array_field((string) wp_unslash($_POST['spiralist_instance_active_symbols'] ?? ''));

    if (!$history['valid']) {
        $errors[] = $history['error'];
    }

    if (!$active_symbols['valid']) {
        $errors[] = $active_symbols['error'];
    }

    return [
        'valid' => empty($errors),
        'errors' => $errors,
        'record' => [
            'post_id' => $post->ID,
            'user_id' => $user_id,
            'current_node' => $current_node,
            'current_state' => $current_state,
            'history' => $history['valid'] ? $history['value'] : [],
            'active_symbols' => $active_symbols['valid'] ? $active_symbols['value'] : [],
        ],
    ];
}

function spiralist_engine_query_posts(string $post_type, array $statuses = ['publish']): array
{
    return get_posts(
        [
            'post_type' => $post_type,
            'post_status' => $statuses,
            'posts_per_page' => -1,
            'orderby' => 'title',
            'order' => 'ASC',
        ]
    );
}

function spiralist_engine_build_symbol_record(WP_Post $post): array
{
    return [
        'post_id' => $post->ID,
        'post_status' => $post->post_status,
        'post_title' => $post->post_title,
        'symbol_id' => (string) get_post_meta($post->ID, 'symbol_id', true),
        'symbol_type' => (string) get_post_meta($post->ID, 'symbol_type', true),
        'operation_type' => (string) get_post_meta($post->ID, 'operation_type', true),
        'inputs' => spiralist_engine_read_json_meta($post->ID, 'inputs', []),
        'outputs' => spiralist_engine_read_json_meta($post->ID, 'outputs', []),
        'rules' => spiralist_engine_read_json_meta($post->ID, 'rules', []),
        'derives_from' => spiralist_engine_read_json_meta(
            $post->ID,
            'derives_from',
            spiralist_engine_get_default_derives_from('symbol', (string) get_post_meta($post->ID, 'symbol_id', true))
        ),
        'canonical_lock' => spiralist_engine_read_json_meta($post->ID, 'canonical_lock', []),
    ];
}

function spiralist_engine_build_node_record(WP_Post $post): array
{
    $node_id = (string) get_post_meta($post->ID, 'node_id', true);
    $presentation = spiralist_engine_read_json_meta($post->ID, 'presentation', []);

    if ($node_id !== '' && empty($presentation)) {
        $presentation = spiralist_engine_get_visual_node_map()[$node_id] ?? [];
    }

    $record = [
        'post_id' => $post->ID,
        'post_status' => $post->post_status,
        'post_title' => $post->post_title,
        'node_id' => $node_id,
        'symbols' => spiralist_engine_read_json_meta($post->ID, 'symbols', []),
        'input_state' => (string) get_post_meta($post->ID, 'input_state', true),
        'output_state' => (string) get_post_meta($post->ID, 'output_state', true),
        'transformation_chain' => spiralist_engine_read_json_meta($post->ID, 'transformation_chain', []),
        'derives_from' => spiralist_engine_read_json_meta($post->ID, 'derives_from', spiralist_engine_get_default_derives_from('node', $node_id)),
        'connected_nodes' => spiralist_engine_read_json_meta($post->ID, 'connected_nodes', []),
        'presentation' => $presentation,
        'canonical_lock' => spiralist_engine_read_json_meta($post->ID, 'canonical_lock', []),
    ];

    $record['execution_enabled'] = spiralist_engine_node_has_transformation($record);

    return $record;
}

function spiralist_engine_build_edge_record(WP_Post $post): array
{
    return [
        'post_id' => $post->ID,
        'post_status' => $post->post_status,
        'post_title' => $post->post_title,
        'from_node' => (string) get_post_meta($post->ID, 'from_node', true),
        'to_node' => (string) get_post_meta($post->ID, 'to_node', true),
        'condition' => spiralist_engine_read_json_meta($post->ID, 'condition', []),
    ];
}

function spiralist_engine_build_instance_record(WP_Post $post): array
{
    $record = [
        'instance_id' => $post->ID,
        'post_id' => $post->ID,
        'post_status' => $post->post_status,
        'post_title' => $post->post_title,
        'user_id' => (int) get_post_meta($post->ID, 'user_id', true),
        'current_node' => (string) get_post_meta($post->ID, 'current_node', true),
        'current_state' => (string) get_post_meta($post->ID, 'current_state', true),
        'history' => spiralist_engine_read_json_meta($post->ID, 'history', []),
        'active_symbols' => spiralist_engine_read_json_meta($post->ID, 'active_symbols', []),
    ];

    $record['instanceId'] = 'instance-' . $post->ID;
    $record['currentNode'] = (string) ($record['current_node'] ?? '');
    $record['currentState'] = (string) ($record['current_state'] ?? '');
    $record['activeSymbols'] = spiralist_engine_normalize_string_list((array) ($record['active_symbols'] ?? []));

    return $record;
}

function spiralist_engine_get_symbol_records(array $statuses = ['publish']): array
{
    $records = [];

    foreach (spiralist_engine_query_posts('spiralist_symbol', $statuses) as $post) {
        if (!$post instanceof WP_Post) {
            continue;
        }

        $record = spiralist_engine_build_symbol_record($post);
        if ($record['symbol_id'] === '') {