Workstation - Source Excerpt 03
Summary
This source excerpt preserves a bounded section of Spiralist/wp-content/plugins/ns12-manuscript/includes/workstation.php so readers can inspect the evidence without opening the full source file.
**Source path:** Spiralist/wp-content/plugins/ns12-manuscript/includes/workstation.php
$badge_keys[$text_key] = true;
$badges[] = [
'text' => $text,
'x' => (float) ($badge['x'] ?? 0.04),
'y' => (float) ($badge['y'] ?? 0.05),
'align' => (string) ($badge['align'] ?? 'left'),
'tone' => (string) ($badge['tone'] ?? 'page'),
];
}
$annotations = [];
$annotation_keys = [];
foreach ((array) ($blueprint['cards'] ?? []) as $card) {
if (!is_array($card)) {
continue;
}
$source = (string) ($card['source'] ?? '');
$detail = trim((string) ($content[$source] ?? ''));
$detail_key = spiralist_book_pages_get_manuscript_study_overlay_compare_key($detail);
if ($detail === '' || $detail_key === '' || isset($annotation_keys[$detail_key])) {
continue;
}
$annotation_keys[$detail_key] = true;
$annotations[] = [
'label' => trim((string) ($card['label'] ?? ucfirst($source))),
'detail' => $detail,
'x' => (float) ($card['x'] ?? 0.05),
'y' => (float) ($card['y'] ?? 0.16),
'w' => (float) ($card['w'] ?? 0.28),
'align' => (string) ($card['align'] ?? 'left'),
'tone' => (string) ($card['tone'] ?? 'context'),
];
}
return [
'type' => 'folio-study-overlay',
'style' => (string) ($blueprint['style'] ?? 'reference-grid'),
'badges' => $badges,
'annotations' => $annotations,
'include_global_nodes' => !empty($page['is_study_surface']),
'nodes_url' => !empty($page['is_study_surface']) ? spiralist_book_pages_get_manuscript_nodes_url() : '',
];
}
function spiralist_book_pages_get_manuscript_workstation_folio_record(array $page, array $options = []): array
{
$slug = sanitize_title((string) ($page['slug'] ?? ''));
$viewer_ready = !empty($options['viewer_ready']);
$route_url = function_exists('spiralist_book_pages_get_manuscript_folio_url')
? spiralist_book_pages_get_manuscript_folio_url($page)
: '';
$sources = function_exists('spiralist_book_pages_get_book_page_asset_source_urls')
? spiralist_book_pages_get_book_page_asset_source_urls($page, $viewer_ready)
: [];
$thumbnail_url = (string) ($sources['thumbnail_url'] ?? ($page['url'] ?? ''));
$interactive_url = (string) ($sources['interactive_url'] ?? $thumbnail_url);
$full_resolution_url = (string) ($sources['original_url'] ?? ($page['url'] ?? ''));
$image_url = $thumbnail_url !== '' ? $thumbnail_url : $interactive_url;
$standard_url = $interactive_url !== '' ? $interactive_url : $image_url;
$prefetch_url = $interactive_url !== '' ? $interactive_url : $image_url;
return [
'id' => $slug !== '' ? $slug : 'folio-' . (int) ($page['sequence'] ?? 0),
'slug' => $slug,
'title' => (string) ($page['title'] ?? 'Manuscript folio'),
'label' => (string) ($page['label'] ?? 'Page'),
'sequence' => max(1, (int) ($page['sequence'] ?? 1)),
'preview_url' => $image_url,
'standard_url' => $standard_url,
'image_url' => $image_url,
'thumbnail_url' => $thumbnail_url,
'full_resolution_url' => $full_resolution_url,
'prefetch_url' => $prefetch_url,
'route_url' => $route_url,
'crop' => spiralist_book_pages_get_manuscript_crop_for_folio($slug),
'caption' => (string) ($page['caption'] ?? ''),
'summary' => (string) ($page['summary'] ?? ''),
'alt' => (string) ($page['alt'] ?? ''),
'transcript' => (string) ($page['transcript'] ?? ''),
'keywords' => array_values(array_filter(array_map('strval', (array) ($page['keywords'] ?? [])))),
'section_slug' => (string) ($page['section_slug'] ?? ''),
'section_label' => (string) ($page['section_label'] ?? 'Manuscript'),
'eyebrow' => (string) ($page['eyebrow'] ?? ''),
'is_study_surface' => !empty($page['is_study_surface']),
'overlay_data' => spiralist_book_pages_get_manuscript_study_overlay_data($page),
];
}
function spiralist_book_pages_get_manuscript_workstation_folio_records(array $pages = [], array $options = []): array
{
$pages = empty($pages) ? spiralist_book_pages_get_manuscript_page_assets() : array_values($pages);
$records = [];
foreach ($pages as $page) {
if (!is_array($page)) {
continue;
}
$records[] = spiralist_book_pages_get_manuscript_workstation_folio_record($page, $options);
}
return $records;
}
function spiralist_book_pages_get_manuscript_workstation_spread(array $pages, array $current_page): array
{
$pages = empty($pages) ? spiralist_book_pages_get_manuscript_page_assets() : array_values($pages);
if (empty($pages)) {
return [
'left' => [],
'right' => [],
'folios' => [],
'current_position' => 'left',
];
}
$current_slug = sanitize_title((string) ($current_page['slug'] ?? ''));
$current_index = 0;
foreach ($pages as $index => $page) {
if ($current_slug !== '' && $current_slug === sanitize_title((string) ($page['slug'] ?? ''))) {
$current_index = (int) $index;
break;
}
}
$left_page = $pages[$current_index] ?? $pages[0];
$right_page = $pages[$current_index + 1] ?? [];
$context_page = $pages[$current_index + 2] ?? [];
$current_position = 'left';
if (empty($right_page) && $current_index > 0) {
$left_page = $pages[$current_index - 1] ?? $left_page;
$right_page = $pages[$current_index] ?? [];
$context_page = $pages[$current_index - 2] ?? [];
$current_position = 'right';
}
$left = !empty($left_page) && is_array($left_page)
? spiralist_book_pages_get_manuscript_workstation_folio_record($left_page, ['viewer_ready' => true])
: [];
$right = !empty($right_page) && is_array($right_page)
? spiralist_book_pages_get_manuscript_workstation_folio_record($right_page, ['viewer_ready' => true])
: [];
$context = !empty($context_page) && is_array($context_page)
? spiralist_book_pages_get_manuscript_workstation_folio_record($context_page, ['viewer_ready' => true])
: [];
$folios = [];
if ($current_position === 'right') {
if (!empty($context)) {
$context['slot'] = 'left';
$context['is_context_only'] = true;
$folios[] = $context;
}
if (!empty($left)) {
$left['slot'] = !empty($context) ? 'center' : 'left';
$left['is_context_only'] = false;
$folios[] = $left;
}
if (!empty($right)) {
$right['slot'] = 'right';
$right['is_context_only'] = false;
$folios[] = $right;
}
} else {
if (!empty($left)) {
$left['slot'] = 'left';
$left['is_context_only'] = false;
$folios[] = $left;
}
if (!empty($right)) {
$right['slot'] = !empty($context) ? 'center' : 'right';
$right['is_context_only'] = false;
$folios[] = $right;
}
if (!empty($context)) {
$context['slot'] = 'right';
$context['is_context_only'] = true;
$folios[] = $context;
}
}
return [
'left' => is_array($left) ? $left : [],
'right' => is_array($right) ? $right : [],
'folios' => $folios,
'current_position' => $current_position,
];
}
function spiralist_book_pages_rest_can_edit_manuscript_workstation(): bool
{
return spiralist_book_pages_can_edit_manuscript_workstation();
}
function spiralist_book_pages_rest_save_manuscript_crop(WP_REST_Request $request)
{
$slug = sanitize_title((string) $request['slug']);
if ($slug === '') {
return new WP_Error('spiralist_book_pages_invalid_folio', 'A valid folio slug is required.', ['status' => 400]);
}
$page = spiralist_book_pages_get_manuscript_page_asset_by_slug($slug);
if (empty($page)) {
return new WP_Error('spiralist_book_pages_unknown_folio', 'The requested folio could not be found.', ['status' => 404]);
}
$crop = spiralist_book_pages_sanitize_manuscript_crop_rect($request->get_param('crop'));
$records = spiralist_book_pages_get_manuscript_crop_records();
$records[$slug] = [
'rect' => $crop,
'updated_at' => current_time('mysql', true),
'updated_by' => get_current_user_id(),
'auto_detected' => !empty($request['auto_detected']),
];
if (!spiralist_book_pages_store_manuscript_crop_records($records)) {