Skip to content
wiki.fftac.org

Workstation - Source Excerpt 03

Back to Workstation

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)) {