Use SQL to get chapter relationship metabox data

This commit is contained in:
Tetrakern 2024-11-05 21:10:00 +01:00
parent 1c9b1a8134
commit d6ca9bd79b
2 changed files with 90 additions and 30 deletions

View File

@ -867,3 +867,73 @@ if ( ! function_exists( 'fictioneer_sql_get_chapter_story_selection' ) ) {
); );
} }
} }
if ( ! function_exists( 'fictioneer_sql_get_story_chapter_relationship_data' ) ) {
/**
* Returns chapter objects for a story
*
* @since 5.26.0
*
* @global wpdb $wpdb WordPress database object.
*
* @param int $story_id Story ID.
*
* @return object[] Array of chapter data object similar to WP_Post.
*/
function fictioneer_sql_get_story_chapter_relationship_data( $story_id ) {
global $wpdb;
// Setup
$chapter_ids = fictioneer_get_story_chapter_ids( $story_id );
// Empty?
if ( empty( $chapter_ids ) ) {
return [];
}
// Prepare SQL query
$placeholders = implode( ',', array_fill( 0, count( $chapter_ids ), '%d' ) );
$values = array_merge( $chapter_ids, [ $story_id ] );
$sql = $wpdb->prepare(
"SELECT p.ID as ID, p.post_title as post_title, p.post_status as post_status, p.post_date_gmt as post_date_gmt,
pm_text_icon.meta_value as fictioneer_chapter_text_icon,
pm_icon.meta_value as fictioneer_chapter_icon,
pm_rating.meta_value as fictioneer_chapter_rating,
pm_warning.meta_value as fictioneer_chapter_warning,
pm_group.meta_value as fictioneer_chapter_group,
pm_hidden.meta_value as fictioneer_chapter_hidden,
pm_no_chapter.meta_value as fictioneer_chapter_no_chapter
FROM {$wpdb->posts} p
LEFT JOIN {$wpdb->postmeta} pm_text_icon ON (p.ID = pm_text_icon.post_id AND pm_text_icon.meta_key = 'fictioneer_chapter_text_icon')
LEFT JOIN {$wpdb->postmeta} pm_icon ON (p.ID = pm_icon.post_id AND pm_icon.meta_key = 'fictioneer_chapter_icon')
LEFT JOIN {$wpdb->postmeta} pm_rating ON (p.ID = pm_rating.post_id AND pm_rating.meta_key = 'fictioneer_chapter_rating')
LEFT JOIN {$wpdb->postmeta} pm_warning ON (p.ID = pm_warning.post_id AND pm_warning.meta_key = 'fictioneer_chapter_warning')
LEFT JOIN {$wpdb->postmeta} pm_group ON (p.ID = pm_group.post_id AND pm_group.meta_key = 'fictioneer_chapter_group')
LEFT JOIN {$wpdb->postmeta} pm_hidden ON (p.ID = pm_hidden.post_id AND pm_hidden.meta_key = 'fictioneer_chapter_hidden')
LEFT JOIN {$wpdb->postmeta} pm_no_chapter ON (p.ID = pm_no_chapter.post_id AND pm_no_chapter.meta_key = 'fictioneer_chapter_no_chapter')
WHERE p.post_type = 'fcn_chapter'
AND p.ID IN ($placeholders)
AND EXISTS (
SELECT 1
FROM {$wpdb->postmeta} pm
WHERE pm.post_id = p.ID AND pm.meta_key = 'fictioneer_chapter_story' AND pm.meta_value = %d
)
",
...$values
);
// Execute
$results = $wpdb->get_results( $sql );
// Restore order and return
$chapter_map = array_flip( $chapter_ids );
usort( $results, function( $a, $b ) use ( $chapter_map ) {
return $chapter_map[ $a->ID ] <=> $chapter_map[ $b->ID ];
});
return $results;
}
}

View File

@ -1128,6 +1128,7 @@ add_action( 'wp_ajax_fictioneer_ajax_query_relationship_posts', 'fictioneer_ajax
* Render HTML for selected story chapters * Render HTML for selected story chapters
* *
* @since 5.8.0 * @since 5.8.0
* @since 5.26.0 - Use custom chapter objects.
* *
* @param array $selected Currently selected chapters. * @param array $selected Currently selected chapters.
* @param string $meta_key The meta key. * @param string $meta_key The meta key.
@ -1137,11 +1138,15 @@ add_action( 'wp_ajax_fictioneer_ajax_query_relationship_posts', 'fictioneer_ajax
function fictioneer_callback_relationship_chapters( $selected, $meta_key, $args = [] ) { function fictioneer_callback_relationship_chapters( $selected, $meta_key, $args = [] ) {
// Build HTML // Build HTML
foreach ( $selected as $chapter ) { foreach ( $selected as $chapter ) {
$title = fictioneer_get_safe_title( $chapter, 'admin-callback-relationship-chapters' ); $title = fictioneer_sanitize_safe_title(
$chapter->post_title,
get_date_from_gmt( $chapter->post_date_gmt, get_option( 'date_format' ) ),
get_date_from_gmt( $chapter->post_date_gmt, get_option( 'time_format' ) )
);
$classes = ['fictioneer-meta-field__relationships-item', 'fictioneer-meta-field__relationships-values-item']; $classes = ['fictioneer-meta-field__relationships-item', 'fictioneer-meta-field__relationships-values-item'];
$label = fictioneer_get_post_status_label( $chapter->post_status ); $label = fictioneer_get_post_status_label( $chapter->post_status );
if ( get_post_meta( $chapter->ID, 'fictioneer_chapter_hidden', true ) ) { if ( $chapter->fictioneer_chapter_hidden ) {
$title = "{$title} (" . _x( 'Unlisted', 'Chapter assignment flag.', 'fictioneer' ) . ")"; $title = "{$title} (" . _x( 'Unlisted', 'Chapter assignment flag.', 'fictioneer' ) . ")";
} }
@ -1274,29 +1279,31 @@ function fictioneer_ajax_get_relationship_chapters( $post_id, $meta_key ) {
* *
* @since 5.8.0 * @since 5.8.0
* *
* @param WP_Post $chapter The chapter post. * @param WP_Post|object $chapter The chapter post or similar object.
* *
* @return string HTML for the chapter info. * @return string HTML for the chapter info.
*/ */
function fictioneer_get_relationship_chapter_details( $chapter ) { function fictioneer_get_relationship_chapter_details( $chapter ) {
// Setup // Setup
$text_icon = get_post_meta( $chapter->ID, 'fictioneer_chapter_text_icon', true ); $text_icon = $chapter->fictioneer_chapter_text_icon ?? '';
$icon = fictioneer_get_icon_field( 'fictioneer_chapter_icon', $chapter->ID ); $icon = fictioneer_get_icon_field( 'fictioneer_chapter_icon', null, $chapter->fictioneer_chapter_icon ?? '' );
$rating = get_post_meta( $chapter->ID, 'fictioneer_chapter_rating', true ); $rating = $chapter->fictioneer_chapter_rating ?? '';
$warning = get_post_meta( $chapter->ID, 'fictioneer_chapter_warning', true ); $warning = $chapter->fictioneer_chapter_warning ?? '';
$group = get_post_meta( $chapter->ID, 'fictioneer_chapter_group', true ); $group = $chapter->fictioneer_chapter_group ?? '';
$date_local = get_date_from_gmt( $chapter->post_date_gmt, get_option( 'date_format' ) );
$time_local = get_date_from_gmt( $chapter->post_date_gmt, get_option( 'time_format' ) );
$flags = []; $flags = [];
$info = []; $info = [];
// Build // Build
$info[] = empty( $text_icon ) ? sprintf( '<i class="%s"></i>', $icon ) : "<strong>{$text_icon}</strong>"; $info[] = empty( $text_icon ) ? sprintf( '<i class="%s"></i>', $icon ) : "<strong>{$text_icon}</strong>";
if ( get_post_meta( $chapter->ID, 'fictioneer_chapter_hidden', true ) ) { if ( $chapter->fictioneer_chapter_hidden ?? 0 ) {
$flags[] = _x( 'Unlisted', 'Chapter assignment flag.', 'fictioneer' ); $flags[] = _x( 'Unlisted', 'Chapter assignment flag.', 'fictioneer' );
} }
if ( get_post_meta( $chapter->ID, 'fictioneer_chapter_no_chapter', true ) ) { if ( $chapter->fictioneer_chapter_no_chapter ?? 0 ) {
$flags[] = _x( 'No Chapter', 'Chapter assignment flag.', 'fictioneer' ); $flags[] = _x( 'No Chapter', 'Chapter assignment flag.', 'fictioneer' );
} }
@ -1307,8 +1314,8 @@ function fictioneer_get_relationship_chapter_details( $chapter ) {
$info[] = sprintf( $info[] = sprintf(
_x( '<strong>Date:</strong>&nbsp;%1$s at %2$s', 'Chapter assignment info.', 'fictioneer' ), _x( '<strong>Date:</strong>&nbsp;%1$s at %2$s', 'Chapter assignment info.', 'fictioneer' ),
get_the_date( '', $chapter->ID ), $date_local,
get_the_time( '', $chapter->ID ) $time_local
); );
if ( ! empty( $group ) ) { if ( ! empty( $group ) ) {
@ -2044,23 +2051,6 @@ function fictioneer_render_story_data_metabox( $post ) {
); );
// Chapters // Chapters
$chapter_ids = fictioneer_get_story_chapter_ids( $post->ID );
$chapters = empty( $chapter_ids ) ? [] : get_posts(
array(
'post_type' => 'fcn_chapter',
'post_status' => 'any',
'post__in' => $chapter_ids ?: [0], // Must not be empty!
'orderby' => 'post__in',
'posts_per_page' => -1,
'meta_key' => 'fictioneer_chapter_story',
'meta_value' => $post->ID,
'update_post_meta_cache' => true,
'update_post_term_cache' => false, // Improve performance
'no_found_rows' => true // Improve performance
)
);
$description = get_option( 'fictioneer_limit_chapter_stories_by_author' ) ? $description = get_option( 'fictioneer_limit_chapter_stories_by_author' ) ?
__( '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). 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' ); __( 'Select and order chapters assigned to the story (set in the chapter).', 'fictioneer' );
@ -2068,7 +2058,7 @@ function fictioneer_render_story_data_metabox( $post ) {
$output['fictioneer_story_chapters'] = fictioneer_get_metabox_relationships( $output['fictioneer_story_chapters'] = fictioneer_get_metabox_relationships(
$post, $post,
'fictioneer_story_chapters', 'fictioneer_story_chapters',
$chapters, fictioneer_sql_get_story_chapter_relationship_data( $post->ID ),
'fictioneer_callback_relationship_chapters', 'fictioneer_callback_relationship_chapters',
array( array(
'label' => _x( 'Chapters', 'Story chapters meta field label.', 'fictioneer' ), 'label' => _x( 'Chapters', 'Story chapters meta field label.', 'fictioneer' ),