Collaboration - Source Excerpt 02
Summary
This source excerpt preserves a bounded section of Spiralist/wp-content/plugins/ns12-manuscript/includes/collaboration.php so readers can inspect the evidence without opening the full source file.
**Source path:** Spiralist/wp-content/plugins/ns12-manuscript/includes/collaboration.php
$url .= rawurlencode($submission_slug) . '/';
}
return $url;
}
function spiralist_book_pages_user_can_collaborate(int $user_id = 0): bool
{
$user_id = $user_id > 0 ? $user_id : get_current_user_id();
if ($user_id <= 0) {
return false;
}
if (user_can($user_id, 'manage_options')) {
return true;
}
return user_can($user_id, spiralist_book_pages_get_collaboration_capability());
}
function spiralist_book_pages_get_collaboration_profile_user(string $profile_slug): ?WP_User
{
$profile_slug = sanitize_title($profile_slug);
if ($profile_slug === '') {
return null;
}
$user = get_user_by('slug', $profile_slug);
return $user instanceof WP_User ? $user : null;
}
function spiralist_book_pages_get_collaboration_notice_key(): string
{
return 'spiralist_book_pages_collaboration_notice_' . get_current_user_id();
}
function spiralist_book_pages_set_collaboration_notice(string $message, string $type = 'success'): void
{
if (get_current_user_id() <= 0) {
return;
}
set_transient(
spiralist_book_pages_get_collaboration_notice_key(),
[
'message' => sanitize_text_field($message),
'type' => $type === 'error' ? 'error' : 'success',
],
MINUTE_IN_SECONDS
);
}
function spiralist_book_pages_get_collaboration_notice(): array
{
if (get_current_user_id() <= 0) {
return [];
}
$notice = get_transient(spiralist_book_pages_get_collaboration_notice_key());
if (!is_array($notice)) {
return [];
}
delete_transient(spiralist_book_pages_get_collaboration_notice_key());
return $notice;
}
function spiralist_book_pages_get_collaboration_attachment_payload(int $attachment_id, string $preferred_alt = ''): array
{
$attachment_id = max(0, $attachment_id);
if ($attachment_id <= 0) {
return [];
}
if (!wp_attachment_is_image($attachment_id)) {
return [];
}
$image_url = wp_get_attachment_image_url($attachment_id, 'full');
if (!is_string($image_url) || $image_url === '') {
return [];
}
$thumbnail_url = wp_get_attachment_image_url($attachment_id, 'large');
if (!is_string($thumbnail_url) || $thumbnail_url === '') {
$thumbnail_url = $image_url;
}
$alt = trim($preferred_alt);
if ($alt === '') {
$alt = trim((string) get_post_meta($attachment_id, '_wp_attachment_image_alt', true));
}
return [
'id' => $attachment_id,
'url' => $image_url,
'thumbnail_url' => $thumbnail_url,
'alt' => $alt,
'caption' => (string) wp_get_attachment_caption($attachment_id),
];
}
function spiralist_book_pages_validate_collaboration_image_attachment(int $attachment_id)
{
$attachment_id = max(0, $attachment_id);
if ($attachment_id <= 0) {
return new WP_Error('spiralist_book_pages_missing_image', 'Upload a manuscript image before saving this page.');
}
$attachment = get_post($attachment_id);
if (!$attachment instanceof WP_Post || $attachment->post_type !== 'attachment') {
return new WP_Error('spiralist_book_pages_invalid_image', 'The selected manuscript image could not be found.');
}
if (!wp_attachment_is_image($attachment_id)) {
return new WP_Error('spiralist_book_pages_invalid_image_type', 'Choose an image file for this manuscript page.');
}
$image_url = wp_get_attachment_image_url($attachment_id, 'full');
if (!is_string($image_url) || $image_url === '') {
return new WP_Error('spiralist_book_pages_invalid_image', 'The selected manuscript image is no longer available.');
}
return $attachment_id;
}
function spiralist_book_pages_normalize_collaboration_copy($copy, ?WP_Post $submission = null): array
{
if (!is_array($copy)) {
return [];
}
$title = sanitize_text_field((string) ($copy['title'] ?? ($submission instanceof WP_Post ? $submission->post_title : '')));
$summary = sanitize_textarea_field((string) ($copy['summary'] ?? ''));
$alt = sanitize_text_field((string) ($copy['alt'] ?? ''));
$image_id = max(0, (int) ($copy['image_id'] ?? 0));
$attachment = spiralist_book_pages_get_collaboration_attachment_payload($image_id, $alt);
return [
'title' => $title,
'summary' => $summary,
'alt' => (string) ($attachment['alt'] ?? $alt),
'image_id' => $image_id,
'image_url' => (string) ($attachment['url'] ?? ''),
'thumbnail_url' => (string) ($attachment['thumbnail_url'] ?? ''),
'caption' => (string) ($attachment['caption'] ?? ''),
'updated_at' => sanitize_text_field((string) ($copy['updated_at'] ?? '')),
'submitted_at' => sanitize_text_field((string) ($copy['submitted_at'] ?? '')),
'approved_at' => sanitize_text_field((string) ($copy['approved_at'] ?? '')),
'version' => max(0, (int) ($copy['version'] ?? 0)),
];
}
function spiralist_book_pages_collaboration_copies_match(array $left, array $right): bool
{
foreach (['title', 'summary', 'alt'] as $field) {
if ((string) ($left[$field] ?? '') !== (string) ($right[$field] ?? '')) {
return false;
}
}
return max(0, (int) ($left['image_id'] ?? 0)) === max(0, (int) ($right['image_id'] ?? 0));
}
function spiralist_book_pages_generate_collaboration_share_token(): string
{
return wp_generate_password(32, false, false);
}
function spiralist_book_pages_ensure_collaboration_share_token(int $submission_id): string
{
$token = sanitize_text_field(
(string) get_post_meta($submission_id, spiralist_book_pages_get_collaboration_share_token_meta_key(), true)
);
if ($token === '') {
$token = spiralist_book_pages_generate_collaboration_share_token();
update_post_meta($submission_id, spiralist_book_pages_get_collaboration_share_token_meta_key(), $token);
}
return $token;
}
function spiralist_book_pages_get_collaboration_submission_record($submission): array
{
$post = $submission instanceof WP_Post ? $submission : get_post((int) $submission);
if (!$post instanceof WP_Post || $post->post_type !== spiralist_book_pages_get_collaboration_post_type()) {
return [];
}
$working_copy = spiralist_book_pages_normalize_collaboration_copy(
get_post_meta($post->ID, spiralist_book_pages_get_collaboration_working_copy_meta_key(), true),
$post
);
$public_copy = spiralist_book_pages_normalize_collaboration_copy(
get_post_meta($post->ID, spiralist_book_pages_get_collaboration_public_copy_meta_key(), true),
$post
);
$status = spiralist_book_pages_normalize_collaboration_status(
(string) get_post_meta($post->ID, spiralist_book_pages_get_collaboration_status_meta_key(), true)
);
if (!empty($public_copy)) {
$status = spiralist_book_pages_collaboration_copies_match($working_copy, $public_copy)
? 'published'
: ($status === 'pending_review' || $status === 'changes_requested' ? $status : 'published_with_draft');
}
$author = get_userdata((int) $post->post_author);
$share_token = spiralist_book_pages_ensure_collaboration_share_token($post->ID);
$submitted_at = sanitize_text_field(
(string) get_post_meta($post->ID, spiralist_book_pages_get_collaboration_submitted_at_meta_key(), true)
);
$approved_at = sanitize_text_field(
(string) get_post_meta($post->ID, spiralist_book_pages_get_collaboration_approved_at_meta_key(), true)
);
$public_version = max(
0,
(int) get_post_meta($post->ID, spiralist_book_pages_get_collaboration_public_version_meta_key(), true)
);
$record = [
'id' => $post->ID,
'slug' => (string) $post->post_name,
'status' => $status,
'status_label' => spiralist_book_pages_get_collaboration_status_label($status),
'status_description' => spiralist_book_pages_get_collaboration_status_description($status),
'status_tone' => spiralist_book_pages_get_collaboration_status_tone($status),
'working_copy' => $working_copy,
'public_copy' => $public_copy,
'live_copy' => !empty($public_copy) ? $public_copy : $working_copy,
'has_public_copy' => !empty($public_copy),
'has_pending_changes' => !empty($public_copy) && !spiralist_book_pages_collaboration_copies_match($working_copy, $public_copy),
'share_token' => $share_token,
'review_notes' => sanitize_textarea_field(
(string) get_post_meta($post->ID, spiralist_book_pages_get_collaboration_review_notes_meta_key(), true)
),
'submitted_at' => $submitted_at,