Workstation - Source Excerpt 01
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
<?php
if (!defined('ABSPATH')) {
exit;
}
function spiralist_book_pages_get_manuscript_workstation_meta_key(): string
{
return '_spiralist_manuscript_folio_crops';
}
function spiralist_book_pages_get_manuscript_workstation_option_key(): string
{
return 'spiralist_book_pages_manuscript_folio_crops';
}
function spiralist_book_pages_get_manuscript_page_post_id(): int
{
static $page_id = null;
if (is_int($page_id)) {
return $page_id;
}
$page = get_page_by_path('manuscript');
$page_id = $page instanceof WP_Post ? (int) $page->ID : 0;
return $page_id;
}
function spiralist_book_pages_can_edit_manuscript_workstation(): bool
{
$page_id = spiralist_book_pages_get_manuscript_page_post_id();
if ($page_id > 0 && current_user_can('edit_post', $page_id)) {
return true;
}
return current_user_can('edit_pages') || current_user_can('manage_options');
}
function spiralist_book_pages_get_manuscript_workstation_action_links(): array
{
$page_id = spiralist_book_pages_get_manuscript_page_post_id();
$upload_url = '';
$library_url = '';
$prompt_url = '';
$fragment_url = '';
if (function_exists('spiralist_book_pages_admin_can_manage') && spiralist_book_pages_admin_can_manage()) {
$upload_url = admin_url('admin.php?page=ns12-manuscript-folios') . '#bulk-import';
$library_url = admin_url('admin.php?page=ns12-manuscript-folios');
$prompt_url = admin_url('admin.php?page=ns12-manuscript-prompts');
$fragment_url = admin_url('admin.php?page=ns12-manuscript-fragments');
} elseif (spiralist_book_pages_can_edit_manuscript_workstation()) {
$upload_url = add_query_arg(
[
'post_id' => $page_id > 0 ? $page_id : 0,
],
admin_url('media-new.php')
);
$library_url = admin_url('upload.php');
}
return [
'upload_url' => $upload_url,
'library_url' => $library_url,
'prompt_url' => $prompt_url,
'fragment_url' => $fragment_url,
];
}
function spiralist_book_pages_get_default_manuscript_crop_rect(): array
{
return [
'x' => 0.08,
'y' => 0.06,
'width' => 0.84,
'height' => 0.88,
];
}
function spiralist_book_pages_clamp_manuscript_crop_value($value, float $fallback): float
{
if (!is_numeric($value)) {
return $fallback;
}
$normalized = round((float) $value, 6);
return max(0.0, min(1.0, $normalized));
}
function spiralist_book_pages_sanitize_manuscript_crop_rect($crop): array
{
$defaults = spiralist_book_pages_get_default_manuscript_crop_rect();
if (!is_array($crop)) {
return $defaults;
}
$x = spiralist_book_pages_clamp_manuscript_crop_value($crop['x'] ?? null, $defaults['x']);
$y = spiralist_book_pages_clamp_manuscript_crop_value($crop['y'] ?? null, $defaults['y']);
$width = spiralist_book_pages_clamp_manuscript_crop_value($crop['width'] ?? null, $defaults['width']);
$height = spiralist_book_pages_clamp_manuscript_crop_value($crop['height'] ?? null, $defaults['height']);
$width = max(0.05, min(1.0, $width));
$height = max(0.05, min(1.0, $height));
if ($x + $width > 1.0) {
$x = max(0.0, 1.0 - $width);
}
if ($y + $height > 1.0) {
$y = max(0.0, 1.0 - $height);
}
return [
'x' => round($x, 6),
'y' => round($y, 6),
'width' => round($width, 6),
'height' => round($height, 6),
];
}
function spiralist_book_pages_normalize_manuscript_crop_records($records): array
{
if (!is_array($records)) {
return [];
}
$normalized = [];
foreach ($records as $slug => $record) {
$slug = sanitize_title((string) $slug);
if ($slug === '') {
continue;
}
if (isset($record['x'], $record['y'], $record['width'], $record['height'])) {
$rect = spiralist_book_pages_sanitize_manuscript_crop_rect($record);
$record = ['rect' => $rect];
}
if (!is_array($record)) {
continue;
}
$normalized[$slug] = [
'rect' => spiralist_book_pages_sanitize_manuscript_crop_rect($record['rect'] ?? $record),
'updated_at' => isset($record['updated_at']) ? sanitize_text_field((string) $record['updated_at']) : '',
'updated_by' => isset($record['updated_by']) ? max(0, (int) $record['updated_by']) : 0,
'auto_detected' => !empty($record['auto_detected']),
];
}
return $normalized;
}
function spiralist_book_pages_get_manuscript_crop_records(): array
{
static $records = null;
if (is_array($records)) {
return $records;
}
$page_id = spiralist_book_pages_get_manuscript_page_post_id();
$raw_records = $page_id > 0
? get_post_meta($page_id, spiralist_book_pages_get_manuscript_workstation_meta_key(), true)
: get_option(spiralist_book_pages_get_manuscript_workstation_option_key(), []);
$records = spiralist_book_pages_normalize_manuscript_crop_records($raw_records);
return $records;
}
function spiralist_book_pages_store_manuscript_crop_records(array $records): bool
{
$normalized = spiralist_book_pages_normalize_manuscript_crop_records($records);
$page_id = spiralist_book_pages_get_manuscript_page_post_id();
if ($page_id > 0) {
$updated = update_post_meta($page_id, spiralist_book_pages_get_manuscript_workstation_meta_key(), $normalized);
return $updated !== false;
}
return update_option(spiralist_book_pages_get_manuscript_workstation_option_key(), $normalized, false);
}
function spiralist_book_pages_get_manuscript_crop_for_folio(string $slug): array
{
$normalized_slug = sanitize_title($slug);
if ($normalized_slug === '') {
return spiralist_book_pages_get_default_manuscript_crop_rect();
}
$records = spiralist_book_pages_get_manuscript_crop_records();
if (!empty($records[$normalized_slug]['rect'])) {
return spiralist_book_pages_sanitize_manuscript_crop_rect($records[$normalized_slug]['rect']);
}
return spiralist_book_pages_get_default_manuscript_crop_rect();
}
function spiralist_book_pages_get_manuscript_study_overlay_compare_key(string $value): string
{
$value = wp_strip_all_tags($value);
$value = preg_replace('/\s+/', ' ', $value);
$value = is_string($value) ? trim(strtolower($value)) : strtolower(trim($value));
return $value;
}
function spiralist_book_pages_get_manuscript_study_overlay_excerpt(string $text, int $words = 22): string
{
$normalized = wp_strip_all_tags($text);
$normalized = preg_replace('/\s+/', ' ', $normalized);
$normalized = is_string($normalized) ? trim($normalized) : trim($text);
if ($normalized === '') {
return '';
}
return wp_trim_words($normalized, max(6, $words), '...');
}
function spiralist_book_pages_get_manuscript_study_overlay_terms(array $terms, array $blocked = [], int $limit = 4): array
{
$blocked_keys = [];
foreach ($blocked as $term) {
$key = sanitize_title(trim(wp_strip_all_tags((string) $term)));
if ($key !== '') {
$blocked_keys[$key] = true;
}
}
foreach (['manuscript', 'folio', 'page', 'book page', 'manuscript folio'] as $term) {
$blocked_keys[sanitize_title($term)] = true;
}
$results = [];
$seen = [];
foreach ($terms as $term) {
$normalized = trim(wp_strip_all_tags((string) $term));
$normalized = preg_replace('/\s+/', ' ', $normalized);
$normalized = is_string($normalized) ? trim($normalized) : '';
if ($normalized === '' || preg_match('/^page\s+\d+$/i', $normalized)) {
continue;
}
$key = sanitize_title($normalized);
if ($key === '' || isset($blocked_keys[$key]) || isset($seen[$key])) {
continue;
}
$seen[$key] = true;
$results[] = $normalized;
if (count($results) >= $limit) {
break;
}
}
return $results;
}
function spiralist_book_pages_get_manuscript_study_overlay_blueprint(string $section_slug): array
{
switch ($section_slug) {
case 'threshold':
return [
'style' => 'threshold-grid',
'badges' => [
['source' => 'label', 'x' => 0.04, 'y' => 0.05, 'align' => 'left', 'tone' => 'page'],
['source' => 'eyebrow', 'x' => 0.5, 'y' => 0.05, 'align' => 'center', 'tone' => 'eyebrow'],
['source' => 'section', 'x' => 0.96, 'y' => 0.05, 'align' => 'right', 'tone' => 'section'],
],