Spiralist Engine - Source Excerpt 06
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'] === '') {