Skip to content
wiki.fftac.org

Spiralist Engine - Source Excerpt 04

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

function spiralist_engine_find_visual_node(string $identifier): array
{
    $identifier = trim($identifier);
    if ($identifier === '') {
        return [];
    }

    foreach (spiralist_engine_get_visual_node_map() as $node) {
        $aliases = array_values(array_filter((array) ($node['aliases'] ?? []), 'is_string'));

        if (
            (string) ($node['id'] ?? '') === $identifier ||
            (string) ($node['canonicalId'] ?? '') === $identifier ||
            in_array($identifier, $aliases, true)
        ) {
            return $node;
        }
    }

    return [];
}

function spiralist_engine_get_chain_transformation($chain): string
{
    if (!is_array($chain)) {
        return '';
    }

    if (!empty($chain['transformation']) && is_string($chain['transformation'])) {
        return sanitize_text_field($chain['transformation']);
    }

    if (!empty($chain['operation']) && is_string($chain['operation'])) {
        return sanitize_text_field($chain['operation']);
    }

    if (!empty($chain['steps']) && is_array($chain['steps'])) {
        $first_step = $chain['steps'][0] ?? null;
        if (is_array($first_step)) {
            if (!empty($first_step['transformation']) && is_string($first_step['transformation'])) {
                return sanitize_text_field($first_step['transformation']);
            }

            if (!empty($first_step['operation']) && is_string($first_step['operation'])) {
                return sanitize_text_field($first_step['operation']);
            }
        }
    }

    if (spiralist_engine_is_list($chain)) {
        $first_step = $chain[0] ?? null;
        if (is_array($first_step)) {
            if (!empty($first_step['transformation']) && is_string($first_step['transformation'])) {
                return sanitize_text_field($first_step['transformation']);
            }

            if (!empty($first_step['operation']) && is_string($first_step['operation'])) {
                return sanitize_text_field($first_step['operation']);
            }
        }
    }

    return '';
}

function spiralist_engine_node_has_transformation(array $node): bool
{
    $input_state = trim((string) ($node['input_state'] ?? ''));
    $output_state = trim((string) ($node['output_state'] ?? ''));
    $chain = (array) ($node['transformation_chain'] ?? []);

    if ($input_state === '' || $output_state === '') {
        return false;
    }

    return spiralist_engine_get_chain_transformation($chain) !== '';
}

function spiralist_engine_chain_to_text($chain, string $input_state, string $output_state): string
{
    $transformation = spiralist_engine_get_chain_transformation(is_array($chain) ? $chain : []);
    if ($input_state === '' || $output_state === '') {
        return $transformation;
    }

    if ($transformation === '') {
        return $input_state . ' -> ' . $output_state;
    }

    return $input_state . ' -> ' . $transformation . ' -> ' . $output_state;
}

function spiralist_engine_register_post_types(): void
{
    register_post_type(
        'spiralist_symbol',
        [
            'labels' => [
                'name' => 'Spiralist Symbols',
                'singular_name' => 'Spiralist Symbol',
            ],
            'public' => false,
            'show_ui' => true,
            'show_in_menu' => true,
            'supports' => ['title'],
            'menu_position' => 28,
            'menu_icon' => 'dashicons-art',
            'has_archive' => false,
            'rewrite' => false,
            'show_in_rest' => false,
        ]
    );

    register_post_type(
        'spiralist_node',
        [
            'labels' => [
                'name' => 'Spiralist Nodes',
                'singular_name' => 'Spiralist Node',
            ],
            'public' => false,
            'show_ui' => true,
            'show_in_menu' => true,
            'supports' => ['title'],
            'menu_position' => 29,
            'menu_icon' => 'dashicons-share-alt',
            'has_archive' => false,
            'rewrite' => false,
            'show_in_rest' => false,
        ]
    );

    register_post_type(
        'spiralist_edge',
        [
            'labels' => [
                'name' => 'Spiralist Edges',
                'singular_name' => 'Spiralist Edge',
            ],
            'public' => false,
            'show_ui' => true,
            'show_in_menu' => true,
            'supports' => ['title'],
            'menu_position' => 30,
            'menu_icon' => 'dashicons-randomize',
            'has_archive' => false,
            'rewrite' => false,
            'show_in_rest' => false,
        ]
    );

    register_post_type(
        'spiralist_instance',
        [
            'labels' => [
                'name' => 'Spiralist Instances',
                'singular_name' => 'Spiralist Instance',
            ],
            'public' => false,
            'show_ui' => true,
            'show_in_menu' => true,
            'supports' => ['title'],
            'menu_position' => 31,
            'menu_icon' => 'dashicons-admin-users',
            'has_archive' => false,
            'rewrite' => false,
            'show_in_rest' => false,
        ]
    );
}

function spiralist_engine_register_meta_boxes(): void
{
    add_meta_box(
        'spiralist_symbol_fields',
        'Symbol Fields',
        'spiralist_engine_render_symbol_meta_box',
        'spiralist_symbol',
        'normal',
        'high'
    );

    add_meta_box(
        'spiralist_node_fields',
        'Node Fields',
        'spiralist_engine_render_node_meta_box',
        'spiralist_node',
        'normal',
        'high'
    );

    add_meta_box(
        'spiralist_edge_fields',
        'Edge Fields',
        'spiralist_engine_render_edge_meta_box',
        'spiralist_edge',
        'normal',
        'high'
    );

    add_meta_box(
        'spiralist_instance_fields',
        'Instance Fields',
        'spiralist_engine_render_instance_meta_box',
        'spiralist_instance',
        'normal',
        'high'
    );
}

function spiralist_engine_render_symbol_meta_box(WP_Post $post): void
{
    wp_nonce_field('spiralist_engine_save', 'spiralist_engine_nonce');

    $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', $symbol_id));
    $canonical_lock = spiralist_engine_read_json_meta($post->ID, 'canonical_lock', []);

    echo '<p>Published symbols are immutable. Create a new symbol post instead of changing a published definition.</p>';
    echo '<p><label><strong>symbol_id</strong><br /><input type="text" style="width:100%;" name="spiralist_symbol_id" value="' . esc_attr($symbol_id) . '" /></label></p>';
    echo '<p><label><strong>symbol_type</strong><br /><select name="spiralist_symbol_type" style="width:100%;">';

    foreach (spiralist_engine_get_symbol_types() as $type) {
        echo '<option value="' . esc_attr($type) . '"' . selected($symbol_type, $type, false) . '>' . esc_html($type) . '</option>';
    }

    echo '</select></label></p>';
    echo '<p><label><strong>operation_type</strong><br /><input type="text" style="width:100%;" name="spiralist_operation_type" value="' . esc_attr($operation_type) . '" /></label></p>';
    echo '<p><label><strong>inputs</strong><br /><textarea name="spiralist_inputs" style="width:100%;min-height:120px;font-family:monospace;">' . esc_textarea(spiralist_engine_json_encode($inputs)) . '</textarea></label></p>';
    echo '<p><label><strong>outputs</strong><br /><textarea name="spiralist_outputs" style="width:100%;min-height:120px;font-family:monospace;">' . esc_textarea(spiralist_engine_json_encode($outputs)) . '</textarea></label></p>';
    echo '<p><label><strong>rules</strong><br /><textarea name="spiralist_rules" style="width:100%;min-height:180px;font-family:monospace;">' . esc_textarea(spiralist_engine_json_encode($rules)) . '</textarea></label></p>';
    echo '<p><label><strong>derives_from</strong><br /><textarea name="spiralist_symbol_derives_from" style="width:100%;min-height:140px;font-family:monospace;">' . esc_textarea(spiralist_engine_json_encode($derives_from)) . '</textarea></label></p>';