diff --git a/FILTERS.md b/FILTERS.md index 4d77b1cf..9ca61de3 100644 --- a/FILTERS.md +++ b/FILTERS.md @@ -54,9 +54,9 @@ Filters the data to be returned as JSON by the `fictioneer_ajax_get_user_data()` --- ### `apply_filters( 'fictioneer_filter_allowed_chapter_permalinks', $statuses )` -Filters the array of chapter statuses that control whether the chapter permalink is rendered in the `fictioneer_story_chapters()` function. By default, the statuses only include `['publish']`. +Filters the array of chapter statuses that control whether the chapter permalink is rendered in the `fictioneer_prepare_chapter_groups()` function. By default, the statuses only include `['publish']`. -**Note:** `fictioneer_story_chapters()` is hooked as action into `fictioneer_story_after_content` (priority 43). +**Note:** Used by `fictioneer_story_chapters()`. **Parameters:** * $statuses (array) – Array of chapter statuses. diff --git a/includes/functions/_utility.php b/includes/functions/_utility.php index ce5427d3..946dff80 100644 --- a/includes/functions/_utility.php +++ b/includes/functions/_utility.php @@ -335,6 +335,88 @@ function fictioneer_get_story_chapter_posts( $story_id, $args = [], $full = fals return $chapter_posts; } +// ============================================================================= +// GROUP CHAPTERS +// ============================================================================= + +/** + * Groups and prepares chapters for a specific story + * + * Note: If chapter groups are disabled, all chapters will be + * withing the 'all_chapters' group. + * + * @since 5.25.0 + * + * @param int $story_id ID of the story. + * @param array $chapters Array of (reduced) WP_Post objects. + * + * @return array The grouped and prepared chapters. + */ + +function fictioneer_prepare_chapter_groups( $story_id, $chapters ) { + // Any chapters? + if ( empty( $chapters ) ) { + return []; + } + + // Setup + $chapter_groups = []; + $allowed_permalinks = apply_filters( 'fictioneer_filter_allowed_chapter_permalinks', ['publish'] ); + $enable_groups = get_option( 'fictioneer_enable_chapter_groups' ) && + ! get_post_meta( $story_id, 'fictioneer_story_disable_groups', true ); + + // Loop chapters... + foreach ( $chapters as $post ) { + $chapter_id = $post->ID; + + // Skip missing or not visible chapters + if ( ! $post || get_post_meta( $chapter_id, 'fictioneer_chapter_hidden', true ) ) { + continue; + } + + // Data + $group = get_post_meta( $chapter_id, 'fictioneer_chapter_group', true ); + $group = empty( $group ) ? fcntr( 'unassigned_group' ) : $group; + $group = $enable_groups ? $group : 'all_chapters'; + $group_key = sanitize_title( $group ); + + if ( ! array_key_exists( $group_key, $chapter_groups ) ) { + $chapter_groups[ $group_key ] = array( + 'group' => $group, + 'toggle_icon' => 'fa-solid fa-chevron-down', + 'data' => [], + 'count' => 0, + 'classes' => array( + '_group-' . sanitize_title( $group ), + "_story-{$story_id}" + ) + ); + } + + $chapter_groups[ $group_key ]['data'][] = array( + 'id' => $chapter_id, + 'story_id' => $story_id, + 'status' => $post->post_status, + 'link' => in_array( $post->post_status, $allowed_permalinks ) ? get_permalink( $post->ID ) : '', + 'timestamp' => get_the_time( 'U', $post ), + 'password' => ! empty( $post->post_password ), + 'list_date' => get_the_date( '', $post ), + 'grid_date' => get_the_time( get_option( 'fictioneer_subitem_date_format', "M j, 'y" ) ?: "M j, 'y", $post ), + 'icon' => fictioneer_get_icon_field( 'fictioneer_chapter_icon', $chapter_id ), + 'text_icon' => get_post_meta( $chapter_id, 'fictioneer_chapter_text_icon', true ), + 'prefix' => get_post_meta( $chapter_id, 'fictioneer_chapter_prefix', true ), + 'title' => fictioneer_get_safe_title( $chapter_id, 'story-chapter-list' ), + 'list_title' => get_post_meta( $chapter_id, 'fictioneer_chapter_list_title', true ), + 'words' => fictioneer_get_word_count( $chapter_id ), + 'warning' => get_post_meta( $chapter_id, 'fictioneer_chapter_warning', true ) + ); + + $chapter_groups[ $group_key ]['count'] += 1; + } + + return $chapter_groups; +} + // ============================================================================= // GET STORY DATA // ============================================================================= diff --git a/includes/functions/hooks/_story_hooks.php b/includes/functions/hooks/_story_hooks.php index 7c08401b..73fa190c 100644 --- a/includes/functions/hooks/_story_hooks.php +++ b/includes/functions/hooks/_story_hooks.php @@ -488,8 +488,6 @@ add_action( 'fictioneer_story_after_content', 'fictioneer_story_pages', 42 ); */ function fictioneer_story_chapters( $args ) { - global $post; - // Abort conditions... if ( $args['password_required'] ?? post_password_required() ) { return; @@ -513,8 +511,6 @@ function fictioneer_story_chapters( $args ) { $prefer_chapter_icon = get_option( 'fictioneer_override_chapter_status_icons' ); $hide_icons = get_post_meta( $story_id, 'fictioneer_story_hide_chapter_icons', true ) || get_option( 'fictioneer_hide_chapter_icons' ); - $enable_groups = get_option( 'fictioneer_enable_chapter_groups' ) && - ! get_post_meta( $story_id, 'fictioneer_story_disable_groups', true ); $disable_folding = get_post_meta( $story_id, 'fictioneer_story_disable_collapse', true ); $collapse_groups = get_option( 'fictioneer_collapse_groups_by_default' ); @@ -525,71 +521,14 @@ function fictioneer_story_chapters( $args ) {
$group, - 'toggle_icon' => 'fa-solid fa-chevron-down', - 'data' => [], - 'count' => 0, - 'classes' => array( - '_group-' . sanitize_title( $group ), - "_story-{$story_id}" - ) - ); - } - - $chapter_groups[ $group_key ]['data'][] = array( - 'id' => $chapter_id, - 'story_id' => $story_id, - 'status' => $post->post_status, - 'link' => in_array( $post->post_status, $allowed_permalinks ) ? get_permalink( $post->ID ) : '', - 'timestamp' => get_the_time( 'U' ), - 'password' => ! empty( $post->post_password ), - 'list_date' => get_the_date( '', $post ), - 'grid_date' => get_the_time( get_option( 'fictioneer_subitem_date_format', "M j, 'y" ) ?: "M j, 'y" ), - 'icon' => fictioneer_get_icon_field( 'fictioneer_chapter_icon', $chapter_id ), - 'text_icon' => get_post_meta( $chapter_id, 'fictioneer_chapter_text_icon', true ), - 'prefix' => get_post_meta( $chapter_id, 'fictioneer_chapter_prefix', true ), - 'title' => fictioneer_get_safe_title( $chapter_id, 'story-chapter-list' ), - 'list_title' => get_post_meta( $chapter_id, 'fictioneer_chapter_list_title', true ), - 'words' => fictioneer_get_word_count( $chapter_id ), - 'warning' => get_post_meta( $chapter_id, 'fictioneer_chapter_warning', true ) - ); - - $chapter_groups[ $group_key ]['count'] += 1; - } - - // Reset postdata - wp_reset_postdata(); - } - // Pre-collapse? if ( $collapse_groups && count( $chapter_groups ) > 1 ) { $group_classes[] = '_closed'; @@ -600,6 +539,7 @@ function fictioneer_story_chapters( $args ) { $group_index = 0; $has_groups = count( $chapter_groups ) > 1 && get_option( 'fictioneer_enable_chapter_groups' ); + // Loop over groups (or one group for all if disabled)... foreach ( $chapter_groups as $group ) { $group_index++;