Roadmap Surfaces - Source Excerpt 02
Summary
This source excerpt preserves a bounded section of Spiralist/wp-content/themes/spiralist/inc/roadmap-surfaces.php so readers can inspect the evidence without opening the full source file.
**Source path:** Spiralist/wp-content/themes/spiralist/inc/roadmap-surfaces.php
function spiralist_register_contribution_content_types(): void
{
register_post_type(
'spiralist_contribution',
[
'labels' => [
'name' => 'Spiralist Contributions',
'singular_name' => 'Spiralist Contribution',
'menu_name' => 'Contributions',
'add_new_item' => 'Add Contribution',
'edit_item' => 'Edit Contribution',
'view_item' => 'View Contribution',
],
'public' => false,
'show_ui' => true,
'show_in_menu' => true,
'show_in_rest' => false,
'supports' => ['title', 'editor', 'author', 'excerpt'],
'menu_icon' => 'dashicons-feedback',
'rewrite' => false,
]
);
register_taxonomy(
'spiralist_contribution_type',
['spiralist_contribution'],
[
'label' => 'Contribution Types',
'public' => false,
'show_ui' => true,
'show_in_rest' => false,
'hierarchical' => true,
]
);
foreach (
[
'bug' => 'Bug',
'symbol-suggestion' => 'Symbol Suggestion',
'prompt-improvement' => 'Prompt Improvement',
'manuscript-annotation' => 'Manuscript Annotation',
] as $slug => $label
) {
if (!term_exists($slug, 'spiralist_contribution_type')) {
wp_insert_term($label, 'spiralist_contribution_type', ['slug' => $slug]);
}
}
}
add_action('init', 'spiralist_register_contribution_content_types', 9);
function spiralist_get_roadmap_endpoint_catalog(): array
{
$nonce = is_user_logged_in() ? wp_create_nonce('wp_rest') : '';
return [
[
'id' => 'manuscript-folio',
'label' => 'Unified Manuscript Folio',
'method' => 'GET',
'url' => rest_url('uaix/v1/manuscript-folio?slug=creation'),
'auth' => 'none',
'purpose' => 'Fetch one folio with image, transcript, symbols, glossary terms, and related prompts.',
],
[
'id' => 'prompt-draft-save',
'label' => 'Save Prompt Draft',
'method' => 'POST',
'url' => rest_url('uaix/v1/prompts/save'),
'auth' => 'wordpress_nonce',
'nonce' => $nonce,
'purpose' => 'Save a signed-in user prompt cockpit draft as a private Workspace prompt.',
],
[
'id' => 'contribute',
'label' => 'Structured Contribution',
'method' => 'POST',
'url' => rest_url('uaix/v1/contribute'),
'auth' => is_user_logged_in() ? 'wordpress_nonce' : 'rate_limited_public',
'nonce' => $nonce,
'purpose' => 'Submit structured bug, symbol, prompt, or manuscript feedback into the contribution queue.',
],
];
}
function spiralist_rest_get_builder_endpoints(): WP_REST_Response
{
return new WP_REST_Response(
[
'site' => home_url('/'),
'generated_at' => gmdate('c'),
'logged_in' => is_user_logged_in(),
'nonce' => is_user_logged_in() ? wp_create_nonce('wp_rest') : '',
'endpoints' => spiralist_get_roadmap_endpoint_catalog(),
]
);
}
function spiralist_find_folio_for_rest(WP_REST_Request $request): array
{
$slug = sanitize_title((string) $request->get_param('slug'));
$sequence = (int) $request->get_param('sequence');
if ($slug !== '' && function_exists('spiralist_book_pages_get_manuscript_page_asset_by_slug')) {
$page = spiralist_book_pages_get_manuscript_page_asset_by_slug($slug);
if (!empty($page)) {
return $page;
}
}
if ($slug !== '' && function_exists('spiralist_get_manuscript_page_asset_by_slug')) {
$page = spiralist_get_manuscript_page_asset_by_slug($slug);
if (!empty($page)) {
return $page;
}
}
if ($sequence > 0 && function_exists('spiralist_book_pages_get_manuscript_page_asset_by_sequence')) {
$page = spiralist_book_pages_get_manuscript_page_asset_by_sequence($sequence);
if (!empty($page)) {
return $page;
}
}
if ($sequence > 0 && function_exists('spiralist_get_manuscript_page_asset_by_sequence')) {
$page = spiralist_get_manuscript_page_asset_by_sequence($sequence);
if (!empty($page)) {
return $page;
}
}
$pages = function_exists('spiralist_book_pages_get_manuscript_page_assets')
? spiralist_book_pages_get_manuscript_page_assets()
: (function_exists('spiralist_get_manuscript_page_assets') ? spiralist_get_manuscript_page_assets() : []);
return is_array($pages) && !empty($pages[0]) && is_array($pages[0]) ? $pages[0] : [];
}
function spiralist_get_folio_sources_for_rest(array $page): array
{
if (function_exists('spiralist_book_pages_get_book_page_asset_source_urls')) {
return spiralist_book_pages_get_book_page_asset_source_urls($page, true);
}
$url = (string) ($page['url'] ?? '');
return [
'thumbnail_url' => $url,
'large_url' => $url,
'interactive_url' => $url,
'original_url' => $url,
];
}
function spiralist_match_symbols_for_folio(array $page): array
{
$keywords = array_values(array_filter(array_map('strval', (array) ($page['keywords'] ?? [])), 'strlen'));
$haystack = strtolower(
implode(
' ',
array_filter(
[
(string) ($page['title'] ?? ''),
(string) ($page['summary'] ?? ''),
(string) ($page['caption'] ?? ''),
implode(' ', $keywords),
]
)
)
);
$records = function_exists('spiralist_get_symbol_detail_records') ? spiralist_get_symbol_detail_records() : [];
$matches = [];
foreach ($records as $record) {
if (!is_array($record)) {
continue;
}
$terms = array_values(
array_filter(
array_map(
'strtolower',
[
(string) ($record['label'] ?? ''),
(string) ($record['canonicalId'] ?? ''),
(string) ($record['meaning'] ?? ''),
(string) ($record['category'] ?? ''),
]
),
'strlen'
)
);
$matched = false;
foreach ($terms as $term) {
if (strlen($term) >= 4 && strpos($haystack, $term) !== false) {
$matched = true;
break;
}
}
if (!$matched && count($matches) >= 5) {
continue;
}
if ($matched || count($matches) < 3) {
$matches[] = [
'id' => (string) ($record['canonicalId'] ?? ''),
'label' => (string) ($record['label'] ?? ''),
'meaning' => (string) ($record['meaning'] ?? ''),
'definition' => (string) ($record['definition'] ?? ''),
'url' => (string) ($record['url'] ?? ''),
];
}
if (count($matches) >= 8) {
break;
}
}
return $matches;
}
function spiralist_get_folio_related_prompts_for_rest(array $page): array
{
$records = function_exists('spiralist_get_manuscript_related_prompt_records')
? spiralist_get_manuscript_related_prompt_records($page)
: [];
$prompts = [];
foreach ($records as $record) {
if (!is_array($record)) {
continue;
}
$prompts[] = [
'id' => (int) ($record['id'] ?? 0),
'slug' => (string) ($record['slug'] ?? ''),
'title' => (string) ($record['title'] ?? 'Related prompt'),
'summary' => (string) ($record['summary'] ?? ''),
'url' => (string) ($record['url'] ?? ''),
'moderation_status' => (string) ($record['moderation_status'] ?? ''),
];
}
return $prompts;
}
function spiralist_rest_get_manuscript_folio(WP_REST_Request $request)
{
$page = spiralist_find_folio_for_rest($request);
if (empty($page)) {
return new WP_Error('spiralist_folio_not_found', 'No manuscript folio could be resolved.', ['status' => 404]);
}
$sources = spiralist_get_folio_sources_for_rest($page);
$symbols = spiralist_match_symbols_for_folio($page);
$route_url = function_exists('spiralist_book_pages_get_manuscript_folio_url')
? spiralist_book_pages_get_manuscript_folio_url($page)