Boost performance of story data query (x15)
This commit is contained in:
parent
7d2fddaed9
commit
c73e64eb5e
43
CUSTOMIZE.md
43
CUSTOMIZE.md
@ -358,6 +358,23 @@ If the "Next Chapter" note above the chapter list is not enough and you want to
|
||||
* Filter: [fictioneer_filter_story_chapter_posts_query](FILTERS.md#apply_filters-fictioneer_filter_story_chapter_posts_query-query_args-story_id-chapter_ids-)
|
||||
|
||||
```php
|
||||
/**
|
||||
* Allows scheduled (future) chapters to be queried
|
||||
*
|
||||
* @since x.x.x
|
||||
*
|
||||
* @param array $statuses Statuses that are queried. Default ['publish].
|
||||
*
|
||||
* @return array The updated array of statuses.
|
||||
*/
|
||||
|
||||
function child_query_scheduled_chapters( $statuses ) {
|
||||
$statuses[] = 'future';
|
||||
|
||||
return $statuses;
|
||||
}
|
||||
add_filter( 'fictioneer_filter_get_story_data_queried_chapter_statuses', 'child_query_scheduled_chapters' );
|
||||
|
||||
/**
|
||||
* Shows scheduled (future) chapter in story chapter list
|
||||
*
|
||||
@ -405,6 +422,32 @@ function child_consider_scheduled_chapters_as_update( $statuses ) {
|
||||
return $statuses;
|
||||
}
|
||||
add_action( 'fictioneer_filter_chapters_added_statuses', 'child_consider_scheduled_chapters_as_update' );
|
||||
|
||||
// If you want scheduled chapters to be treated like published ones;
|
||||
// you still need a function or plugin to make them accessible or
|
||||
// they will lead to a 404 error page. Yes, that's a lot of filters.
|
||||
|
||||
/**
|
||||
* Adds the 'future' post status to an allowed statuses array
|
||||
*
|
||||
* @since x.x.x
|
||||
*
|
||||
* @param array $statuses Statuses that are queried. Default ['publish].
|
||||
*
|
||||
* @return array The updated array of statuses.
|
||||
*/
|
||||
|
||||
function child_treat_scheduled_chapters_as_published( $statuses ) {
|
||||
$statuses[] = 'future';
|
||||
|
||||
return $statuses;
|
||||
}
|
||||
add_filter( 'fictioneer_filter_chapter_list_statuses', 'child_treat_scheduled_chapters_as_published' );
|
||||
add_filter( 'fictioneer_filter_chapter_index_popup_menu_statuses', 'child_treat_scheduled_chapters_as_published' );
|
||||
add_filter( 'fictioneer_filter_chapter_nav_buttons_allowed_statuses', 'child_treat_scheduled_chapters_as_published' );
|
||||
add_filter( 'fictioneer_filter_get_story_data_indexed_chapter_statuses', 'child_treat_scheduled_chapters_as_published' );
|
||||
add_filter( 'fictioneer_filter_allowed_chapter_permalinks', 'child_treat_scheduled_chapters_as_published' );
|
||||
|
||||
```
|
||||
|
||||
## Modify or remove items from card footers
|
||||
|
38
FILTERS.md
38
FILTERS.md
@ -405,11 +405,45 @@ Filters the array of support links returned for the current post (or post ID if
|
||||
|
||||
---
|
||||
|
||||
### `apply_filters( 'fictioneer_filter_get_story_data_indexed_chapter_statuses', $statuses )`
|
||||
Filters the array of chapter statuses that can be appended to a story’s `indexed_chapter_ids` array in the `fictioneer_get_story_data()` function. By default, the statuses are `['publish']`.
|
||||
### `apply_filters( 'fictioneer_filter_get_story_data_indexed_chapter_statuses', $statuses, $story_id )`
|
||||
Filters the array of chapter statuses that can be appended to a story’s `indexed_chapter_ids` array in the `fictioneer_get_story_data()` function. These chapters are a subset of the queried chapters, which need to be filtered separately. By default, the statuses are `['publish']`.
|
||||
|
||||
**Parameters:**
|
||||
* $statuses (array) – Array of chapter statuses.
|
||||
* $story_id (int) – The story post ID.
|
||||
|
||||
**Example:**
|
||||
```php
|
||||
// Adds 'future' chapters to the indexed list in fictioneer_get_story_data()
|
||||
|
||||
function child_index_scheduled_chapters( $statuses ) {
|
||||
$statuses[] = 'future';
|
||||
|
||||
return $statuses;
|
||||
}
|
||||
add_filter( 'fictioneer_filter_get_story_data_indexed_chapter_statuses', 'child_index_scheduled_chapters' );
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `apply_filters( 'fictioneer_filter_get_story_data_queried_chapter_statuses', $statuses, $story_id )`
|
||||
Filters the array of queried chapter statuses in the `fictioneer_get_story_data()` function. These chapters may appear in lists but cannot necessarily be navigated to (for example, `'future'` chapters). By default, the statuses are `['publish']`.
|
||||
|
||||
**Parameters:**
|
||||
* $statuses (array) – Array of chapter statuses.
|
||||
* $story_id (int) – The story post ID.
|
||||
|
||||
**Example:**
|
||||
```php
|
||||
// Adds 'future' chapters to the query and visible list in fictioneer_get_story_data()
|
||||
|
||||
function child_query_scheduled_chapters( $statuses ) {
|
||||
$statuses[] = 'future';
|
||||
|
||||
return $statuses;
|
||||
}
|
||||
add_filter( 'fictioneer_filter_get_story_data_queried_chapter_statuses', 'child_query_scheduled_chapters' );
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
|
@ -344,6 +344,7 @@ if ( ! function_exists( 'fictioneer_get_story_data' ) ) {
|
||||
* Get collection of a story's data
|
||||
*
|
||||
* @since 4.3.0
|
||||
* @since 5.25.0 - Refactored with custom SQL query.
|
||||
*
|
||||
* @param int $story_id ID of the story.
|
||||
* @param boolean $show_comments Optional. Whether the comment count is needed.
|
||||
@ -354,6 +355,8 @@ if ( ! function_exists( 'fictioneer_get_story_data' ) ) {
|
||||
*/
|
||||
|
||||
function fictioneer_get_story_data( $story_id, $show_comments = true, $args = [] ) {
|
||||
global $wpdb;
|
||||
|
||||
$story_id = fictioneer_validate_id( $story_id, 'fcn_story' );
|
||||
$meta_cache = null;
|
||||
|
||||
@ -402,7 +405,6 @@ if ( ! function_exists( 'fictioneer_get_story_data' ) ) {
|
||||
}
|
||||
|
||||
// Setup
|
||||
$chapters = fictioneer_get_story_chapter_posts( $story_id );
|
||||
$tags = get_the_tags( $story_id );
|
||||
$fandoms = get_the_terms( $story_id, 'fcn_fandom' );
|
||||
$characters = get_the_terms( $story_id, 'fcn_character' );
|
||||
@ -416,8 +418,6 @@ if ( ! function_exists( 'fictioneer_get_story_data' ) ) {
|
||||
$visible_chapter_ids = [];
|
||||
$indexed_chapter_ids = [];
|
||||
|
||||
$allowed_indexed_statuses = apply_filters( 'fictioneer_filter_get_story_data_indexed_chapter_statuses', ['publish'] );
|
||||
|
||||
// Assign correct icon
|
||||
if ( $status != 'Ongoing' ) {
|
||||
switch ( $status ) {
|
||||
@ -436,29 +436,66 @@ if ( ! function_exists( 'fictioneer_get_story_data' ) ) {
|
||||
}
|
||||
}
|
||||
|
||||
// Count chapters, words, comments, etc.
|
||||
if ( ! empty( $chapters ) ) {
|
||||
foreach ( $chapters as $chapter ) {
|
||||
// This is about 50 times faster than using a meta query lol
|
||||
if ( ! get_post_meta( $chapter->ID, 'fictioneer_chapter_hidden', true ) ) {
|
||||
// Do not count non-chapters...
|
||||
if ( ! get_post_meta( $chapter->ID, 'fictioneer_chapter_no_chapter', true ) ) {
|
||||
$chapter_count += 1;
|
||||
$word_count += get_post_meta( $chapter->ID, '_word_count', true );
|
||||
}
|
||||
// Custom SQL query to count chapters, words, comments, etc.
|
||||
// This significantly faster than WP_Query (up to 15 times with 500 chapters)
|
||||
$queried_statuses = apply_filters( 'fictioneer_filter_get_story_data_queried_chapter_statuses', ['publish'], $story_id );
|
||||
$indexed_statuses = apply_filters( 'fictioneer_filter_get_story_data_indexed_chapter_statuses', ['publish'], $story_id );
|
||||
$chapter_ids = fictioneer_get_story_chapter_ids( $story_id );
|
||||
$chapters = [];
|
||||
|
||||
// ... but they are still listed!
|
||||
$visible_chapter_ids[] = $chapter->ID;
|
||||
if ( ! empty( $chapter_ids ) ) {
|
||||
$chapter_ids_placeholder = implode( ',', array_fill( 0, count( $chapter_ids ), '%d' ) );
|
||||
|
||||
// Indexed chapters (accounts for custom filters)
|
||||
if ( in_array( $chapter->post_status, $allowed_indexed_statuses ) ) {
|
||||
$indexed_chapter_ids[] = $chapter->ID;
|
||||
}
|
||||
$status_list = array_map( function( $status ) use ( $wpdb ) {
|
||||
return $wpdb->prepare( '%s', $status );
|
||||
}, $queried_statuses );
|
||||
|
||||
$status_list = implode( ',', $status_list );
|
||||
|
||||
$query = $wpdb->prepare(
|
||||
"SELECT
|
||||
c.ID as chapter_id,
|
||||
c.comment_count,
|
||||
SUM(CASE WHEN pm.meta_key = '_word_count' THEN CAST(pm.meta_value AS UNSIGNED) ELSE 0 END) AS word_count,
|
||||
MAX(CASE WHEN pm.meta_key = 'fictioneer_chapter_hidden' THEN pm.meta_value ELSE '' END) AS is_hidden,
|
||||
MAX(CASE WHEN pm.meta_key = 'fictioneer_chapter_no_chapter' THEN pm.meta_value ELSE '' END) AS is_no_chapter,
|
||||
c.post_status
|
||||
FROM {$wpdb->posts} c
|
||||
LEFT JOIN {$wpdb->postmeta} pm ON pm.post_id = c.ID
|
||||
WHERE c.ID IN ($chapter_ids_placeholder)
|
||||
AND c.post_status IN ($status_list)
|
||||
GROUP BY c.ID",
|
||||
...$chapter_ids // WHERE clause
|
||||
);
|
||||
|
||||
$chapters = $wpdb->get_results( $query );
|
||||
|
||||
usort( $chapters, function( $a, $b ) use ( $chapter_ids ) {
|
||||
$position_a = array_search( $a->chapter_id, $chapter_ids );
|
||||
$position_b = array_search( $b->chapter_id, $chapter_ids );
|
||||
return $position_a - $position_b;
|
||||
});
|
||||
}
|
||||
|
||||
foreach ( $chapters as $chapter ) {
|
||||
if ( empty( $chapter->is_hidden ) ) {
|
||||
// Do not count non-chapters...
|
||||
if ( empty( $chapter->is_no_chapter ) ) {
|
||||
$chapter_count++;
|
||||
$word_count += intval( $chapter->word_count );
|
||||
}
|
||||
|
||||
// Count ALL comments
|
||||
$comment_count += $chapter->comment_count;
|
||||
// ... but they are still listed!
|
||||
$visible_chapter_ids[] = $chapter->chapter_id;
|
||||
|
||||
// Indexed chapters (accounts for custom filters)
|
||||
if ( in_array( $chapter->post_status, $indexed_statuses ) ) {
|
||||
$indexed_chapter_ids[] = $chapter->chapter_id;
|
||||
}
|
||||
}
|
||||
|
||||
// Count ALL comments
|
||||
$comment_count += intval( $chapter->comment_count );
|
||||
}
|
||||
|
||||
// Add story word count
|
||||
|
Loading…
x
Reference in New Issue
Block a user