Collaboration - Source Excerpt 04
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
return new WP_Error('spiralist_book_pages_forbidden', 'You are not allowed to edit this manuscript page.');
}
$post_id = $submission_id > 0
? wp_update_post(
[
'ID' => $submission_id,
'post_title' => (string) $payload['title'],
'post_excerpt' => (string) ($payload['summary'] ?? ''),
],
true
)
: wp_insert_post(
[
'post_type' => spiralist_book_pages_get_collaboration_post_type(),
'post_status' => 'private',
'post_author' => $user_id,
'post_title' => (string) $payload['title'],
'post_excerpt' => (string) ($payload['summary'] ?? ''),
],
true
);
if (is_wp_error($post_id) || !$post_id) {
return new WP_Error('spiralist_book_pages_save_failed', 'The manuscript page could not be saved.');
}
$post_id = (int) $post_id;
$public_copy = !empty($existing['public_copy']) ? (array) $existing['public_copy'] : [];
$working_copy = [
'title' => (string) $payload['title'],
'summary' => (string) ($payload['summary'] ?? ''),
'alt' => (string) ($payload['alt'] ?? ''),
'image_id' => max(0, (int) ($payload['image_id'] ?? 0)),
'updated_at' => gmdate('c'),
];
$status = 'draft';
if ($operation === 'submit') {
$status = 'pending_review';
$working_copy['submitted_at'] = gmdate('c');
update_post_meta($post_id, spiralist_book_pages_get_collaboration_submitted_at_meta_key(), $working_copy['submitted_at']);
} elseif (!empty($public_copy)) {
$status = spiralist_book_pages_collaboration_copies_match($working_copy, $public_copy)
? 'published'
: 'published_with_draft';
} elseif ((string) ($existing['status'] ?? '') === 'changes_requested') {
$status = 'changes_requested';
}
update_post_meta($post_id, spiralist_book_pages_get_collaboration_working_copy_meta_key(), $working_copy);
update_post_meta($post_id, spiralist_book_pages_get_collaboration_status_meta_key(), $status);
spiralist_book_pages_ensure_collaboration_share_token($post_id);
$saved_record = spiralist_book_pages_get_collaboration_submission_record($post_id);
return !empty($saved_record)
? $saved_record
: new WP_Error('spiralist_book_pages_save_failed', 'The manuscript page was saved, but the updated record could not be reloaded.');
}
function spiralist_book_pages_approve_collaboration_submission(int $submission_id, int $reviewer_id)
{
$record = spiralist_book_pages_get_collaboration_submission_record($submission_id);
if (empty($record)) {
return new WP_Error('spiralist_book_pages_missing_submission', 'The selected manuscript page could not be found.');
}
$working_copy = (array) ($record['working_copy'] ?? []);
if (empty($working_copy) || max(0, (int) ($working_copy['image_id'] ?? 0)) <= 0) {
return new WP_Error('spiralist_book_pages_missing_working_copy', 'This manuscript page does not have a reviewable working version yet.');
}
$approved_at = gmdate('c');
$public_version = max(0, (int) ($record['public_version'] ?? 0)) + 1;
$public_copy = $working_copy;
$public_copy['approved_at'] = $approved_at;
$public_copy['version'] = $public_version;
update_post_meta($submission_id, spiralist_book_pages_get_collaboration_public_copy_meta_key(), $public_copy);
update_post_meta($submission_id, spiralist_book_pages_get_collaboration_status_meta_key(), 'published');
update_post_meta($submission_id, spiralist_book_pages_get_collaboration_approved_at_meta_key(), $approved_at);
update_post_meta($submission_id, spiralist_book_pages_get_collaboration_public_version_meta_key(), $public_version);
update_post_meta($submission_id, spiralist_book_pages_get_collaboration_review_notes_meta_key(), '');
update_post_meta($submission_id, '_spiralist_ms_approved_by', $reviewer_id);
$approved_record = spiralist_book_pages_get_collaboration_submission_record($submission_id);
return !empty($approved_record)
? $approved_record
: new WP_Error('spiralist_book_pages_approve_failed', 'The manuscript page was approved, but the refreshed public record could not be loaded.');
}
function spiralist_book_pages_request_collaboration_changes(int $submission_id, string $review_notes = '')
{
$record = spiralist_book_pages_get_collaboration_submission_record($submission_id);
if (empty($record)) {
return new WP_Error('spiralist_book_pages_missing_submission', 'The selected manuscript page could not be found.');
}
update_post_meta($submission_id, spiralist_book_pages_get_collaboration_status_meta_key(), 'changes_requested');
update_post_meta(
$submission_id,
spiralist_book_pages_get_collaboration_review_notes_meta_key(),
sanitize_textarea_field($review_notes)
);
$updated_record = spiralist_book_pages_get_collaboration_submission_record($submission_id);
return !empty($updated_record)
? $updated_record
: new WP_Error('spiralist_book_pages_review_failed', 'The change request was saved, but the refreshed manuscript page record could not be loaded.');
}
function spiralist_book_pages_set_collaborator_access(int $user_id, bool $allowed): bool
{
$user = get_userdata($user_id);
if (!$user instanceof WP_User) {
return false;
}
$capability = spiralist_book_pages_get_collaboration_capability();
$upload_grant_meta_key = spiralist_book_pages_get_collaboration_upload_grant_meta_key();
if ($allowed) {
$had_upload_cap = user_can($user, 'upload_files');
$user->add_cap($capability);
if (!$had_upload_cap) {
$user->add_cap('upload_files');
update_user_meta($user_id, $upload_grant_meta_key, '1');
} else {
delete_user_meta($user_id, $upload_grant_meta_key);
}
} else {
$user->remove_cap($capability);
if ((string) get_user_meta($user_id, $upload_grant_meta_key, true) === '1') {
$user->remove_cap('upload_files');
delete_user_meta($user_id, $upload_grant_meta_key);
}
}
return true;
}
function spiralist_book_pages_get_collaborator_management_records(): array
{
$records = [];
foreach (get_users(['orderby' => 'display_name', 'order' => 'ASC']) as $user) {
if (!$user instanceof WP_User) {
continue;
}
$submissions = spiralist_book_pages_get_collaboration_user_records((int) $user->ID);
$pending = 0;
foreach ($submissions as $submission) {
if ((string) ($submission['status'] ?? '') === 'pending_review') {
$pending++;
}
}
$records[] = [
'id' => (int) $user->ID,
'display_name' => (string) $user->display_name,
'email' => (string) $user->user_email,
'slug' => sanitize_title((string) $user->user_nicename),
'roles' => array_values(array_map('strval', (array) $user->roles)),
'can_collaborate' => spiralist_book_pages_user_can_collaborate((int) $user->ID),
'submission_count' => count($submissions),
'pending_count' => $pending,
'profile_url' => spiralist_book_pages_get_manuscript_profile_url($user),
'edit_url' => get_edit_user_link((int) $user->ID),
];
}
return $records;
}
function spiralist_book_pages_collaboration_robots(array $robots): array
{
if (!spiralist_book_pages_is_manuscript_studio_surface() && !spiralist_book_pages_is_manuscript_profile_surface()) {
return $robots;
}
$robots['noindex'] = true;
$robots['nofollow'] = true;
$robots['noarchive'] = true;
return $robots;
}
add_filter('wp_robots', 'spiralist_book_pages_collaboration_robots');
function spiralist_book_pages_handle_frontend_submission_action(): void
{
if (!is_user_logged_in() || !spiralist_book_pages_user_can_collaborate()) {
wp_die('You are not allowed to submit manuscript pages.');
}
check_admin_referer('spiralist_book_pages_frontend_submission');
$operation = sanitize_key((string) wp_unslash($_POST['submission_operation'] ?? 'save'));
$submission_id = max(0, (int) wp_unslash($_POST['submission_id'] ?? 0));
$payload = spiralist_book_pages_prepare_collaboration_submission_payload($submission_id);
if (is_wp_error($payload)) {
spiralist_book_pages_set_collaboration_notice($payload->get_error_message(), 'error');
wp_safe_redirect(
$submission_id > 0