diff --git a/includes/functions/_helpers-query.php b/includes/functions/_helpers-query.php
index ad2cd4d0..719c91e6 100644
--- a/includes/functions/_helpers-query.php
+++ b/includes/functions/_helpers-query.php
@@ -710,6 +710,44 @@ if ( ! function_exists( 'fictioneer_sql_has_new_story_chapters' ) ) {
}
}
+if ( ! function_exists( 'fictioneer_get_co_authored_story_ids' ) ) {
+ /**
+ * Returns story IDs where the user is a co-author
+ *
+ * @since 5.26.0
+ *
+ * @global wpdb $wpdb WordPress database object.
+ *
+ * @param int $author_id User ID.
+ *
+ * @return int[] Array of story IDs.
+ */
+
+ function fictioneer_get_co_authored_story_ids( $author_id ) {
+ static $cache = [];
+
+ if ( isset( $cache[ $author_id ] ) ) {
+ return $cache[ $author_id ];
+ }
+
+ global $wpdb;
+
+ $story_ids = $wpdb->get_col(
+ $wpdb->prepare(
+ "SELECT post_id
+ FROM {$wpdb->postmeta}
+ WHERE meta_key = 'fictioneer_story_co_authors'
+ AND meta_value LIKE %s",
+ '%"' . $author_id . '"%'
+ )
+ );
+
+ $cache[ $author_id ] = $story_ids;
+
+ return $story_ids;
+ }
+}
+
if ( ! function_exists( 'fictioneer_sql_get_chapter_story_selection' ) ) {
/**
* Returns selectable stories for chapter assignments
@@ -729,7 +767,9 @@ if ( ! function_exists( 'fictioneer_sql_get_chapter_story_selection' ) ) {
// Setup
$stories = array( '0' => _x( '— Unassigned —', 'Chapter story select option.', 'fictioneer' ) );
+ $co_authored_stories = [];
$other_author = false;
+ $co_author = false;
// Prepare SQL query
$values = [];
@@ -743,6 +783,15 @@ if ( ! function_exists( 'fictioneer_sql_get_chapter_story_selection' ) ) {
if ( get_option( 'fictioneer_limit_chapter_stories_by_author' ) ) {
$sql .= " AND p.post_author = %d";
$values[] = $post_author_id;
+
+ $co_authored_stories = fictioneer_get_co_authored_story_ids( $post_author_id );
+
+ if ( ! empty( $co_authored_stories ) ) {
+ $placeholders = implode( ',', array_fill( 0, count( $co_authored_stories ), '%d' ) );
+ $sql .= " OR p.ID IN ($placeholders)";
+ $values = array_merge( $values, $co_authored_stories );
+ $co_author = true;
+ }
}
$sql .= " ORDER BY p.post_date DESC";
@@ -757,15 +806,24 @@ if ( ! function_exists( 'fictioneer_sql_get_chapter_story_selection' ) ) {
mysql2date( get_option( 'date_format' ), $story->post_date ),
mysql2date( get_option( 'time_format' ), $story->post_date )
);
+ $suffix = [];
if ( $story->post_status !== 'publish' ) {
- $stories[ $story->ID ] = sprintf(
- _x( '%s (%s)', 'Chapter story meta field option with status label.', 'fictioneer' ),
- $title,
- fictioneer_get_post_status_label( $story->post_status )
- );
- } else {
+ $suffix['status'] = fictioneer_get_post_status_label( $story->post_status );
+ }
+
+ if ( in_array( $story->ID, $co_authored_stories ) ) {
+ $suffix['co-authored'] = __( 'Co-Author', 'fictioneer' );
+ }
+
+ if ( empty( $suffix ) ) {
$stories[ $story->ID ] = $title;
+ } else {
+ $stories[ $story->ID ] = sprintf(
+ _x( '%1$s (%2$s)', 'Chapter story meta field option with notes.', 'fictioneer' ),
+ $title,
+ implode( ' | ', $suffix )
+ );
}
}
@@ -787,15 +845,16 @@ if ( ! function_exists( 'fictioneer_sql_get_chapter_story_selection' ) ) {
// Append to selection
$stories[ $current_story_id ] = sprintf(
- _x( '%s %s', 'Chapter story meta field mismatched option with author and/or status label.', 'fictioneer' ),
+ _x( '%1$s (%2$s)', 'Chapter story meta field mismatched option with notes.', 'fictioneer' ),
fictioneer_get_safe_title( $current_story_id, 'admin-render-chapter-data-metabox-current-suffix' ),
- ( ! empty( $suffix ) ? ' (' . implode( ' | ', $suffix ) . ')' : '' )
+ ! empty( $suffix ) ? implode( ' | ', $suffix ) : ''
);
}
return array(
'stories' => $stories,
- 'other_author' => $other_author
+ 'other_author' => $other_author,
+ 'co_author' => $co_author
);
}
}
diff --git a/includes/functions/_setup-meta-fields.php b/includes/functions/_setup-meta-fields.php
index 6b0c7e09..a27d220c 100644
--- a/includes/functions/_setup-meta-fields.php
+++ b/includes/functions/_setup-meta-fields.php
@@ -2062,7 +2062,7 @@ function fictioneer_render_story_data_metabox( $post ) {
);
$description = get_option( 'fictioneer_limit_chapter_stories_by_author' ) ?
- __( 'Select and order chapters assigned to the story (set in the chapter). The author of the chapter and the story must match.', 'fictioneer' ) :
+ __( 'Select and order chapters assigned to the story (set in the chapter). The author (or co-author) of the chapter and the story must match.', 'fictioneer' ) :
__( 'Select and order chapters assigned to the story (set in the chapter).', 'fictioneer' );
$output['fictioneer_story_chapters'] = fictioneer_get_metabox_relationships(
@@ -2700,6 +2700,8 @@ function fictioneer_render_chapter_data_metabox( $post ) {
$author_warning = $story_selection['other_author'] ? ' ' . __( 'Warning: The selected story belongs to another author. If you change the selection, you cannot go back.', 'fictioneer' ) : '';
+ $author_warning = $story_selection['co_author'] ? ' ' . __( 'Note: You are a co-author of the selected story, but only you can edit this chapter.', 'fictioneer' ) : $author_warning;
+
if ( get_option( 'fictioneer_enable_chapter_appending' ) ) {
$description = __( 'Select the story this chapter belongs to. Published and scheduled chapters are automatically appended to the story.', 'fictioneer' );
}
@@ -2949,7 +2951,9 @@ function fictioneer_save_chapter_metaboxes( $post_id ) {
$invalid_story = false;
if ( get_option( 'fictioneer_limit_chapter_stories_by_author' ) ) {
- $invalid_story = $story_author_id != $post_author_id;
+ $co_authored_stories = fictioneer_get_co_authored_story_ids( $post_author_id );
+
+ $invalid_story = $story_author_id != $post_author_id && ! in_array( $story_id, $co_authored_stories );
}
if ( $invalid_story && $current_story_id != $story_id ) {
diff --git a/includes/functions/_utility.php b/includes/functions/_utility.php
index 77e9cc8a..19855550 100644
--- a/includes/functions/_utility.php
+++ b/includes/functions/_utility.php
@@ -1590,9 +1590,14 @@ function fictioneer_append_chapter_to_story( $post_id, $story_id, $force = false
// Setup, continued
$chapter_author_id = get_post_field( 'post_author', $post_id );
$story_author_id = get_post_field( 'post_author', $story_id );
+ $co_authored_story_ids = fictioneer_get_co_authored_story_ids( $chapter_author_id );
// Abort if the author IDs do not match
- if ( $chapter_author_id != $story_author_id && ! $force ) {
+ if (
+ $chapter_author_id != $story_author_id &&
+ ! in_array( $story_id, $co_authored_story_ids ) &&
+ ! $force
+ ) {
return;
}