2023-01-21 01:31:34 +01:00
< ? php
2023-08-03 13:17:32 +02:00
// =============================================================================
// GET SHORTCODE TRANSIENT
// =============================================================================
if ( ! function_exists ( 'fictioneer_shortcode_query' ) ) {
/**
* Returns query for shortcode
*
* @ since 5.4 . 9
*
* @ param array $args Query arguments .
*
* @ return WP_Query The query result .
*/
function fictioneer_shortcode_query ( $args ) {
// Query
2023-08-06 04:11:42 +02:00
$result = new WP_Query ( $args );
2023-08-03 13:17:32 +02:00
2023-08-05 18:26:50 +02:00
// Prime author cache
2023-08-06 21:33:37 +02:00
if (
get_option ( 'fictioneer_show_authors' ) &&
! empty ( $result -> posts ) &&
function_exists ( 'update_post_author_caches' )
) {
2023-08-05 18:26:50 +02:00
update_post_author_caches ( $result -> posts );
}
2023-08-03 13:17:32 +02:00
return $result ;
}
}
2023-01-21 01:31:34 +01:00
// =============================================================================
// SHORTCODE-BASED RELATIONSHIPS
// =============================================================================
/**
* Register relationships for posts with certain shortcodes
*
2024-01-26 17:45:59 +01:00
* @ since 5.0 . 0
2024-04-16 14:02:03 +02:00
*
* @ param int $post_id The ID of the saved post .
* @ param WP_Post $post The saved post object .
2023-01-21 01:31:34 +01:00
*/
function fictioneer_update_shortcode_relationships ( $post_id , $post ) {
2024-08-17 17:27:09 +02:00
// Prevent multi-fire
if ( fictioneer_multi_save_guard ( $post_id ) ) {
2023-08-05 12:12:07 +02:00
return ;
}
2023-01-21 01:31:34 +01:00
// Setup
$registry = fictioneer_get_relationship_registry ();
2023-09-17 01:45:50 +02:00
// Look for blog shortcode
if ( str_contains ( $post -> post_content , 'fictioneer_blog' ) ) {
$registry [ 'always' ][ $post_id ] = 'shortcode' ;
} else {
unset ( $registry [ 'always' ][ $post_id ] );
}
2024-04-16 14:02:03 +02:00
// Look for story data shortcode
if (
str_contains ( $post -> post_content , 'fictioneer_story_data' ) ||
str_contains ( $post -> post_content , 'fictioneer_story_comments' ) ||
str_contains ( $post -> post_content , 'fictioneer_story_actions' ) ||
str_contains ( $post -> post_content , 'fictioneer_story_section' ) ||
str_contains ( $post -> post_content , 'fictioneer_subscribe_button' )
) {
$registry [ 'always' ][ $post_id ] = 'shortcode' ;
} else {
unset ( $registry [ 'always' ][ $post_id ] );
}
2023-09-17 01:45:50 +02:00
// Look for article cards shortcode
if ( str_contains ( $post -> post_content , 'fictioneer_article_cards' ) ) {
$registry [ 'always' ][ $post_id ] = 'shortcode' ;
} else {
unset ( $registry [ 'always' ][ $post_id ] );
}
2023-01-21 01:31:34 +01:00
// Look for showcase shortcode
if ( str_contains ( $post -> post_content , 'fictioneer_showcase' ) ) {
$registry [ 'always' ][ $post_id ] = 'shortcode' ;
} else {
unset ( $registry [ 'always' ][ $post_id ] );
}
// Look for post-related shortcode
2024-10-07 02:17:33 +02:00
if ( str_contains ( $post -> post_content , 'fictioneer_latest_posts' ) ) {
2023-01-21 01:31:34 +01:00
$registry [ 'ref_posts' ][ $post_id ] = 'shortcode' ;
} else {
unset ( $registry [ 'ref_posts' ][ $post_id ] );
}
// Look for chapter-related shortcodes
if (
str_contains ( $post -> post_content , 'fictioneer_chapter_list' ) ||
2024-10-07 02:17:33 +02:00
str_contains ( $post -> post_content , 'fictioneer_latest_chapters' )
2023-01-21 01:31:34 +01:00
) {
$registry [ 'ref_chapters' ][ $post_id ] = 'shortcode' ;
} else {
unset ( $registry [ 'ref_chapters' ][ $post_id ] );
}
// Look for story-related shortcodes
if (
2024-10-07 02:17:33 +02:00
str_contains ( $post -> post_content , 'fictioneer_latest_stories' ) ||
str_contains ( $post -> post_content , 'fictioneer_latest_updates' )
2023-01-21 01:31:34 +01:00
) {
$registry [ 'ref_stories' ][ $post_id ] = 'shortcode' ;
} else {
unset ( $registry [ 'ref_stories' ][ $post_id ] );
}
// Look for recommendation-related shortcodes
2024-10-07 02:17:33 +02:00
if ( str_contains ( $post -> post_content , 'fictioneer_latest_recommendations' ) ) {
2023-01-21 01:31:34 +01:00
$registry [ 'ref_recommendations' ][ $post_id ] = 'shortcode' ;
} else {
unset ( $registry [ 'ref_recommendations' ][ $post_id ] );
}
// Update database
fictioneer_save_relationship_registry ( $registry );
}
2023-02-08 20:43:53 +01:00
2023-02-08 20:54:54 +01:00
if ( FICTIONEER_RELATIONSHIP_PURGE_ASSIST ) {
2023-02-08 20:43:53 +01:00
add_action ( 'save_post' , 'fictioneer_update_shortcode_relationships' , 10 , 2 );
}
2023-01-21 01:31:34 +01:00
2023-09-16 22:59:43 +02:00
// =============================================================================
// GET SHORTCODE DEFAULT ARGS
// =============================================================================
2023-09-16 23:41:30 +02:00
/**
* Returns sanitized arguments extracted from shortcode attributes
*
* @ since 5.7 . 3
*
* @ param array $attr Attributes passed to the shortcode .
* @ param int $def_count Default for the 'count' argument .
*
* @ return array The extracted arguments .
*/
2023-09-16 22:59:43 +02:00
function fictioneer_get_default_shortcode_args ( $attr , $def_count = - 1 ) {
//--- Sanitize attributes ----------------------------------------------------
$attr = is_array ( $attr ) ?
array_map ( 'sanitize_text_field' , $attr ) : sanitize_text_field ( $attr );
//--- Extract arguments ------------------------------------------------------
2024-05-14 18:40:52 +02:00
$seamless_default = get_theme_mod ( 'card_image_style' , 'default' ) === 'seamless' ;
$thumbnail_default = get_theme_mod ( 'card_image_style' , 'default' ) !== 'none' ;
2024-10-06 23:17:22 +02:00
$uid = wp_unique_id ( 'shortcode-id-' );
2023-09-16 22:59:43 +02:00
$args = array (
2024-10-06 23:17:22 +02:00
'uid' => $uid ,
2024-01-28 00:11:56 +01:00
'type' => $attr [ 'type' ] ? ? 'default' ,
2023-09-16 22:59:43 +02:00
'count' => max ( - 1 , intval ( $attr [ 'count' ] ? ? $def_count ) ),
'offset' => max ( 0 , intval ( $attr [ 'offset' ] ? ? 0 ) ),
2024-02-04 02:50:09 +01:00
'order' => $attr [ 'order' ] ? ? '' ,
'orderby' => $attr [ 'orderby' ] ? ? '' ,
2023-09-16 22:59:43 +02:00
'page' => max ( 1 , get_query_var ( 'page' ) ? : get_query_var ( 'paged' ) ),
'posts_per_page' => absint ( $attr [ 'per_page' ] ? ? 0 ) ? : get_option ( 'posts_per_page' ),
'post_ids' => fictioneer_explode_list ( $attr [ 'post_ids' ] ? ? '' ),
2023-09-17 01:28:14 +02:00
'author' => sanitize_title ( $attr [ 'author' ] ? ? '' ),
2023-09-16 22:59:43 +02:00
'author_ids' => fictioneer_explode_list ( $attr [ 'author_ids' ] ? ? '' ),
'excluded_authors' => fictioneer_explode_list ( $attr [ 'exclude_author_ids' ] ? ? '' ),
'excluded_tags' => fictioneer_explode_list ( $attr [ 'exclude_tag_ids' ] ? ? '' ),
'excluded_cats' => fictioneer_explode_list ( $attr [ 'exclude_cat_ids' ] ? ? '' ),
'taxonomies' => fictioneer_get_shortcode_taxonomies ( $attr ),
'relation' => strtolower ( $attr [ 'rel' ] ? ? 'and' ) === 'or' ? 'OR' : 'AND' ,
'ignore_sticky' => filter_var ( $attr [ 'ignore_sticky' ] ? ? 0 , FILTER_VALIDATE_BOOLEAN ),
'ignore_protected' => filter_var ( $attr [ 'ignore_protected' ] ? ? 0 , FILTER_VALIDATE_BOOLEAN ),
2024-09-20 23:41:37 +02:00
'only_protected' => filter_var ( $attr [ 'only_protected' ] ? ? 0 , FILTER_VALIDATE_BOOLEAN ),
2024-04-14 14:42:54 +02:00
'vertical' => filter_var ( $attr [ 'vertical' ] ? ? 0 , FILTER_VALIDATE_BOOLEAN ),
2024-05-14 18:40:52 +02:00
'seamless' => filter_var ( $attr [ 'seamless' ] ? ? $seamless_default , FILTER_VALIDATE_BOOLEAN ),
2024-04-14 14:42:54 +02:00
'aspect_ratio' => sanitize_css_aspect_ratio ( $attr [ 'aspect_ratio' ] ? ? '' ),
2024-05-14 18:40:52 +02:00
'thumbnail' => filter_var ( $attr [ 'thumbnail' ] ? ? $thumbnail_default , FILTER_VALIDATE_BOOLEAN ),
2024-04-18 16:09:27 +02:00
'lightbox' => filter_var ( $attr [ 'lightbox' ] ? ? 1 , FILTER_VALIDATE_BOOLEAN ),
2024-05-29 00:01:31 +02:00
'words' => filter_var ( $attr [ 'words' ] ? ? 1 , FILTER_VALIDATE_BOOLEAN ),
'date' => filter_var ( $attr [ 'date' ] ? ? 1 , FILTER_VALIDATE_BOOLEAN ),
2024-08-21 22:53:24 +02:00
'date_format' => sanitize_text_field ( $attr [ 'date_format' ] ? ? '' ),
'nested_date_format' => sanitize_text_field ( $attr [ 'nested_date_format' ] ? ? '' ),
2024-08-18 22:39:22 +02:00
'footer' => filter_var ( $attr [ 'footer' ] ? ? 1 , FILTER_VALIDATE_BOOLEAN ),
'footer_author' => filter_var ( $attr [ 'footer_author' ] ? ? 1 , FILTER_VALIDATE_BOOLEAN ),
2024-08-18 22:09:18 +02:00
'footer_chapters' => filter_var ( $attr [ 'footer_chapters' ] ? ? 1 , FILTER_VALIDATE_BOOLEAN ),
2024-08-18 21:34:32 +02:00
'footer_words' => filter_var ( $attr [ 'footer_words' ] ? ? 1 , FILTER_VALIDATE_BOOLEAN ),
'footer_date' => filter_var ( $attr [ 'footer_date' ] ? ? 1 , FILTER_VALIDATE_BOOLEAN ),
'footer_comments' => filter_var ( $attr [ 'footer_comments' ] ? ? 1 , FILTER_VALIDATE_BOOLEAN ),
'footer_status' => filter_var ( $attr [ 'footer_status' ] ? ? 1 , FILTER_VALIDATE_BOOLEAN ),
'footer_rating' => filter_var ( $attr [ 'footer_rating' ] ? ? 1 , FILTER_VALIDATE_BOOLEAN ),
2024-10-06 23:17:22 +02:00
'classes' => esc_attr ( wp_strip_all_tags ( $attr [ 'classes' ] ? ? $attr [ 'class' ] ? ? '' ) ) . " { $uid } " ,
2024-08-14 15:17:42 +02:00
'infobox' => filter_var ( $attr [ 'infobox' ] ? ? 1 , FILTER_VALIDATE_BOOLEAN ),
2024-09-06 01:26:42 +02:00
'source' => filter_var ( $attr [ 'source' ] ? ? 1 , FILTER_VALIDATE_BOOLEAN ),
2024-09-07 00:28:36 +02:00
'splide' => sanitize_text_field ( $attr [ 'splide' ] ? ? '' ),
'cache' => filter_var ( $attr [ 'cache' ] ? ? 1 , FILTER_VALIDATE_BOOLEAN )
2023-09-16 22:59:43 +02:00
);
//--- Fixes ------------------------------------------------------------------
// Update count if limited to post IDs
if ( ! empty ( $args [ 'post_ids' ] ) ) {
2024-04-14 14:42:54 +02:00
$args [ 'count' ] = count ( $args [ 'post_ids' ] );
2023-09-16 22:59:43 +02:00
}
2024-09-06 01:26:42 +02:00
// Prepare Splide JSON
if ( ! empty ( $args [ 'splide' ] ) ) {
$args [ 'splide' ] = str_replace ( " ' " , '"' , $args [ 'splide' ] );
if ( ! fictioneer_is_valid_json ( $args [ 'splide' ] ) ) {
$args [ 'splide' ] = false ;
} else {
$splide = json_decode ( $args [ 'splide' ], true );
2024-10-07 20:13:09 +02:00
// Turn arrows off by default
2024-09-06 01:26:42 +02:00
if ( ! preg_match ( '/"arrows"\s*:\s*true/' , $args [ 'splide' ] ) ) {
$splide [ 'arrows' ] = false ;
}
2024-10-07 20:13:09 +02:00
// Change default arrow SVG path
2024-10-07 19:47:35 +02:00
if ( ! isset ( $splide [ 'arrowPath' ] ) ) {
$splide [ 'arrowPath' ] = 'M31.89 18.24c0.98 0.98 0.98 2.56 0 3.54l-15 15c-0.98 0.98-2.56 0.98-3.54 0s-0.98-2.56 0-3.54L26.45 20 13.23 6.76c-0.98-0.98-0.98-2.56 0-3.54s2.56-0.98 3.54 0l15 15' ;
}
2024-09-06 01:26:42 +02:00
$args [ 'splide' ] = json_encode ( $splide );
}
}
2023-09-16 22:59:43 +02:00
//--- Finish -----------------------------------------------------------------
return $args ;
}
2023-03-08 23:02:54 +01:00
// =============================================================================
// GET SHORTCODE TAXONOMIES
// =============================================================================
/**
* Extract taxonomies from shortcode attributes
*
2024-01-26 17:45:59 +01:00
* @ since 5.2 . 0
2023-03-08 23:02:54 +01:00
*
2023-08-09 10:19:20 +02:00
* @ param array $attr Attributes of the shortcode .
2023-03-08 23:02:54 +01:00
*
* @ return array Array of found taxonomies .
*/
function fictioneer_get_shortcode_taxonomies ( $attr ) {
// Setup
$taxonomies = [];
// Tags
if ( ! empty ( $attr [ 'tags' ] ) ) {
$taxonomies [ 'tags' ] = fictioneer_explode_list ( $attr [ 'tags' ] );
}
// Categories
if ( ! empty ( $attr [ 'categories' ] ) ) {
$taxonomies [ 'categories' ] = fictioneer_explode_list ( $attr [ 'categories' ] );
}
// Fandoms
if ( ! empty ( $attr [ 'fandoms' ] ) ) {
$taxonomies [ 'fandoms' ] = fictioneer_explode_list ( $attr [ 'fandoms' ] );
}
// Characters
if ( ! empty ( $attr [ 'characters' ] ) ) {
$taxonomies [ 'characters' ] = fictioneer_explode_list ( $attr [ 'characters' ] );
}
// Genres
if ( ! empty ( $attr [ 'genres' ] ) ) {
$taxonomies [ 'genres' ] = fictioneer_explode_list ( $attr [ 'genres' ] );
}
// Return
return $taxonomies ;
}
2023-03-08 23:24:41 +01:00
// =============================================================================
// GET SHORTCODE TAX QUERY
// =============================================================================
/**
* Get shortcode Tax Query
*
2024-01-26 17:45:59 +01:00
* @ since 5.2 . 0
2023-03-08 23:24:41 +01:00
*
2023-08-09 10:19:20 +02:00
* @ param array $args Arguments of the shortcode partial .
2023-03-08 23:24:41 +01:00
*
* @ return array Tax Query .
*/
function fictioneer_get_shortcode_tax_query ( $args ) {
// Setup
$tax_query = [];
// Are there taxonomies?
if ( ! empty ( $args [ 'taxonomies' ] ) ) {
// Relationship?
if ( count ( $args [ 'taxonomies' ] ) > 1 ) {
$tax_query [ 'relation' ] = $args [ 'relation' ];
}
// Tags?
if ( ! empty ( $args [ 'taxonomies' ][ 'tags' ] ) ) {
$tax_query [] = array (
'taxonomy' => 'post_tag' ,
'field' => 'name' ,
'terms' => $args [ 'taxonomies' ][ 'tags' ]
);
}
// Categories?
if ( ! empty ( $args [ 'taxonomies' ][ 'categories' ] ) ) {
$tax_query [] = array (
'taxonomy' => 'category' ,
'field' => 'name' ,
'terms' => $args [ 'taxonomies' ][ 'categories' ]
);
}
// Fandoms?
if ( ! empty ( $args [ 'taxonomies' ][ 'fandoms' ] ) ) {
$tax_query [] = array (
'taxonomy' => 'fcn_fandom' ,
'field' => 'name' ,
'terms' => $args [ 'taxonomies' ][ 'fandoms' ]
);
}
// Characters?
if ( ! empty ( $args [ 'taxonomies' ][ 'characters' ] ) ) {
$tax_query [] = array (
'taxonomy' => 'fcn_character' ,
'field' => 'name' ,
'terms' => $args [ 'taxonomies' ][ 'characters' ]
);
}
// Genres?
if ( ! empty ( $args [ 'taxonomies' ][ 'genres' ] ) ) {
$tax_query [] = array (
'taxonomy' => 'fcn_genre' ,
'field' => 'name' ,
'terms' => $args [ 'taxonomies' ][ 'genres' ]
);
}
}
// Return
return $tax_query ;
}
2024-10-09 19:30:37 +02:00
// =============================================================================
// SPLIDE
// =============================================================================
/**
* Returns inline script to initialize Splide ASAP
*
* Note : The script tag is only returned once in case multiple sliders
* are active since only one is needed .
*
* @ since 5.25 . 0
2024-11-28 15:24:19 +01:00
* @ since 5.26 . 1 - Use wp_print_inline_script_tag () .
2024-10-09 19:30:37 +02:00
*
* @ return string The inline script .
*/
function fictioneer_get_splide_inline_init () {
static $done = null ;
if ( $done ) {
return '' ;
}
$done = true ;
2024-11-28 15:24:19 +01:00
return wp_get_inline_script_tag (
'document.addEventListener("DOMContentLoaded",()=>{document.querySelectorAll(".splide:not(.no-auto-splide, .is-initialized)").forEach(e=>{e.querySelector(".splide__list")&&"undefined"!=typeof Splide&&(e.classList.remove("_splide-placeholder"),new Splide(e).mount())})});' ,
array (
'id' => 'fictioneer-iife-splide' ,
'class' => 'temp-script' ,
'type' => 'text/javascript' ,
'data-jetpack-boost' => 'ignore' ,
'data-no-optimize' => '1' ,
'data-no-defer' => '1' ,
'data-no-minify' => '1'
)
);
2024-10-09 19:30:37 +02:00
}
2023-01-21 01:31:34 +01:00
// =============================================================================
// SHOWCASE SHORTCODE
// =============================================================================
/**
* Shortcode to display showcase
*
2024-01-26 17:45:59 +01:00
* @ since 5.0 . 0
2023-01-21 01:31:34 +01:00
*
2023-09-16 23:41:30 +02:00
* @ param string $attr [ 'for' ] What the showcase is for . Allowed are chapters ,
* collections , recommendations , and stories .
* @ param string | null $attr [ 'count' ] Optional . Maximum number of items . Default 8.
* @ param string | null $attr [ 'author' ] Optional . Limit posts to a specific author .
* @ param string | null $attr [ 'order' ] Optional . Order direction . Default 'DESC' .
* @ param string | null $attr [ 'orderby' ] Optional . Order argument . Default 'date' .
* @ param string | null $attr [ 'post_ids' ] Optional . Limit posts to specific post IDs .
* @ param string | null $attr [ 'ignore_protected' ] Optional . Whether to ignore protected posts . Default false .
2024-09-20 23:41:37 +02:00
* @ param string | null $attr [ 'only_protected' ] Optional . Whether to query only protected posts . Default false .
2023-09-16 23:41:30 +02:00
* @ param string | null $attr [ 'author_ids' ] Optional . Only include posts by these author IDs .
* @ param string | null $attr [ 'exclude_author_ids' ] Optional . Exclude posts with these author IDs .
* @ param string | null $attr [ 'exclude_tag_ids' ] Optional . Exclude posts with these tags .
* @ param string | null $attr [ 'exclude_cat_ids' ] Optional . Exclude posts with these categories .
* @ param string | null $attr [ 'categories' ] Optional . Limit posts to specific category names .
* @ param string | null $attr [ 'tags' ] Optional . Limit posts to specific tag names .
* @ param string | null $attr [ 'fandoms' ] Optional . Limit posts to specific fandom names .
* @ param string | null $attr [ 'genres' ] Optional . Limit posts to specific genre names .
* @ param string | null $attr [ 'characters' ] Optional . Limit posts to specific character names .
* @ param string | null $attr [ 'rel' ] Optional . Relationship between taxonomies . Default 'AND' .
2024-04-25 14:18:57 +02:00
* @ param string | null $attr [ 'vertical' ] Optional . Whether to show the vertical variant .
2024-05-15 09:49:51 +02:00
* @ param string | null $attr [ 'seamless' ] Optional . Whether to render the image seamless . Default false ( Customizer ) .
2024-09-06 13:16:01 +02:00
* @ param string | null $attr [ 'aspect_ratio' ] Optional . Aspect ratio of the item . Default empty .
2024-09-06 01:26:42 +02:00
* @ param string | null $attr [ 'height' ] Optional . Override the item height . Default empty .
2024-09-06 16:40:32 +02:00
* @ param string | null $attr [ 'min_width' ] Optional . Override the item minimum width . Default empty .
2024-04-25 14:18:57 +02:00
* @ param string | null $attr [ 'lightbox' ] Optional . Whether the thumbnail is opened in the lightbox . Default true .
2024-05-15 09:49:51 +02:00
* @ param string | null $attr [ 'thumbnail' ] Optional . Whether to show the thumbnail . Default true ( Customizer ) .
2023-09-16 23:41:30 +02:00
* @ param string | null $attr [ 'class' ] Optional . Additional CSS classes , separated by whitespace .
2024-10-06 03:48:54 +02:00
* @ param string | null $args [ 'splide' ] Optional . Configuration JSON for the Splide slider . Default empty .
* @ param string | null $args [ 'quality' ] Optional . Size of the images . Default 'medium' .
2023-01-21 01:31:34 +01:00
*
2024-01-29 14:52:56 +01:00
* @ return string The captured shortcode HTML .
2023-01-21 01:31:34 +01:00
*/
function fictioneer_shortcode_showcase ( $attr ) {
// Abort if...
2023-08-28 10:43:04 +02:00
if ( empty ( $attr [ 'for' ] ) ) {
return '' ;
}
2023-01-21 01:31:34 +01:00
2023-09-16 22:59:43 +02:00
// Defaults
$args = fictioneer_get_default_shortcode_args ( $attr , 8 );
2023-01-21 01:31:34 +01:00
2024-10-06 03:48:54 +02:00
// Height/Width/Quality
2024-09-06 01:26:42 +02:00
$args [ 'height' ] = sanitize_text_field ( $attr [ 'height' ] ? ? '' );
2024-09-06 16:40:32 +02:00
$args [ 'min_width' ] = sanitize_text_field ( $attr [ 'min_width' ] ? ? '' );
2024-10-06 03:48:54 +02:00
$args [ 'quality' ] = sanitize_text_field ( $attr [ 'quality' ] ? ? 'medium' );
2024-09-06 01:26:42 +02:00
2023-09-16 22:59:43 +02:00
// Specifics
$args [ 'no_cap' ] = filter_var ( $attr [ 'no_cap' ] ? ? 0 , FILTER_VALIDATE_BOOLEAN );
2023-09-16 21:44:12 +02:00
2023-01-21 01:31:34 +01:00
switch ( $attr [ 'for' ] ) {
case 'collections' :
2023-09-16 22:59:43 +02:00
$args [ 'post_type' ] = 'fcn_collection' ;
2023-01-21 01:31:34 +01:00
break ;
case 'chapters' :
2023-09-16 22:59:43 +02:00
$args [ 'post_type' ] = 'fcn_chapter' ;
2023-01-21 01:31:34 +01:00
break ;
case 'stories' :
2023-09-16 22:59:43 +02:00
$args [ 'post_type' ] = 'fcn_story' ;
2023-01-21 01:31:34 +01:00
break ;
case 'recommendations' :
2023-09-16 22:59:43 +02:00
$args [ 'post_type' ] = 'fcn_recommendation' ;
2023-01-21 01:31:34 +01:00
break ;
}
// Abort if...
2023-09-16 22:59:43 +02:00
if ( ! isset ( $args [ 'post_type' ] ) ) {
2023-08-22 22:51:47 +02:00
return '' ;
}
2023-01-21 01:31:34 +01:00
2024-09-06 01:26:42 +02:00
// Extra classes
if ( $args [ 'splide' ] ? ? 0 ) {
2024-10-06 23:53:02 +02:00
$args [ 'classes' ] .= ' splide _splide-placeholder' ;
2024-09-06 01:26:42 +02:00
}
2023-08-06 04:57:12 +02:00
// Transient?
2024-10-13 14:15:20 +02:00
$transient_enabled = fictioneer_enable_shortcode_transients ( 'fictioneer_showcase' );
if ( $transient_enabled && $args [ 'cache' ] ) {
2023-09-16 02:20:07 +02:00
$base = serialize ( $args ) . serialize ( $attr );
2023-09-16 22:59:43 +02:00
$type = $args [ 'post_type' ];
2023-08-06 04:57:12 +02:00
$transient_key = " fictioneer_shortcode_showcase_ { $type } _html_ " . md5 ( $base );
$transient = get_transient ( $transient_key );
if ( ! empty ( $transient ) ) {
return $transient ;
}
}
2023-01-21 01:31:34 +01:00
// Buffer
ob_start ();
2023-08-06 04:57:12 +02:00
2023-01-21 01:31:34 +01:00
get_template_part ( 'partials/_showcase' , null , $args );
2023-08-06 04:57:12 +02:00
$html = fictioneer_minify_html ( ob_get_clean () );
2024-09-06 01:26:42 +02:00
if ( ( $args [ 'splide' ] ? ? 0 ) && strpos ( $args [ 'classes' ], 'no-auto-splide' ) === false ) {
2024-10-09 19:30:37 +02:00
$html .= fictioneer_get_splide_inline_init ();
2024-09-06 01:26:42 +02:00
}
2024-10-13 14:15:20 +02:00
if ( $transient_enabled && $args [ 'cache' ] ) {
2023-08-06 04:57:12 +02:00
set_transient ( $transient_key , $html , FICTIONEER_SHORTCODE_TRANSIENT_EXPIRATION );
}
2023-06-10 18:43:58 +02:00
// Return minified buffer
2023-08-06 04:57:12 +02:00
return $html ;
2023-01-21 01:31:34 +01:00
}
add_shortcode ( 'fictioneer_showcase' , 'fictioneer_shortcode_showcase' );
// =============================================================================
// LATEST CHAPTERS SHORTCODE
// =============================================================================
/**
* Shortcode to show latest chapters
*
* @ since 3.0
*
2023-09-16 23:41:30 +02:00
* @ param string | null $attr [ 'count' ] Optional . Maximum number of items . Default 4.
* @ param string | null $attr [ 'author' ] Optional . Limit posts to a specific author .
* @ param string | null $attr [ 'type' ] Optional . Choose between 'default' , 'simple' , and 'compact' .
* @ param string | null $attr [ 'order' ] Optional . Order argument . Default 'DESC' .
* @ param string | null $attr [ 'orderby' ] Optional . Orderby argument . Default 'date' .
* @ param string | null $attr [ 'spoiler' ] Optional . Whether to show spoiler content .
2024-08-21 22:53:24 +02:00
* @ param string | null $attr [ 'source' ] Optional . Whether to show the author and story .
2023-09-16 23:41:30 +02:00
* @ param string | null $attr [ 'post_ids' ] Optional . Limit posts to specific post IDs .
* @ param string | null $attr [ 'ignore_protected' ] Optional . Whether to ignore protected posts . Default false .
2024-09-20 23:41:37 +02:00
* @ param string | null $attr [ 'only_protected' ] Optional . Whether to query only protected posts . Default false .
2023-09-16 23:41:30 +02:00
* @ param string | null $attr [ 'author_ids' ] Optional . Only include posts by these author IDs .
* @ param string | null $attr [ 'exclude_author_ids' ] Optional . Exclude posts with these author IDs .
* @ param string | null $attr [ 'exclude_tag_ids' ] Optional . Exclude posts with these tags .
* @ param string | null $attr [ 'exclude_cat_ids' ] Optional . Exclude posts with these categories .
* @ param string | null $attr [ 'categories' ] Optional . Limit posts to specific category names .
* @ param string | null $attr [ 'tags' ] Optional . Limit posts to specific tag names .
* @ param string | null $attr [ 'fandoms' ] Optional . Limit posts to specific fandom names .
* @ param string | null $attr [ 'genres' ] Optional . Limit posts to specific genre names .
* @ param string | null $attr [ 'characters' ] Optional . Limit posts to specific character names .
* @ param string | null $attr [ 'rel' ] Optional . Relationship between taxonomies . Default 'AND' .
2024-04-25 14:18:57 +02:00
* @ param string | null $attr [ 'vertical' ] Optional . Whether to show the vertical variant .
2024-05-15 09:49:51 +02:00
* @ param string | null $attr [ 'seamless' ] Optional . Whether to render the image seamless . Default false ( Customizer ) .
2024-04-25 14:18:57 +02:00
* @ param string | null $attr [ 'aspect_ratio' ] Optional . Aspect ratio for the image . Only with vertical .
* @ param string | null $attr [ 'lightbox' ] Optional . Whether the thumbnail is opened in the lightbox . Default true .
2024-05-15 09:49:51 +02:00
* @ param string | null $attr [ 'thumbnail' ] Optional . Whether to show the thumbnail . Default true ( Customizer ) .
2024-08-21 22:53:24 +02:00
* @ param string | null $attr [ 'date_format' ] Optional . String to override the date format . Default empty .
* @ param string | null $attr [ 'footer' ] Optional . Whether to show the footer ( if any ) . Default true .
* @ param string | null $attr [ 'footer_author' ] Optional . Whether to show the chapter author . Default true .
* @ param string | null $attr [ 'footer_date' ] Optional . Whether to show the chapter date . Default true .
* @ param string | null $attr [ 'footer_words' ] Optional . Whether to show the chapter word count . Default true .
* @ param string | null $attr [ 'footer_comments' ] Optional . Whether to show the chapter comment count . Default true .
* @ param string | null $attr [ 'footer_status' ] Optional . Whether to show the chapter status . Default true .
* @ param string | null $attr [ 'footer_rating' ] Optional . Whether to show the story / chapter age rating . Default true .
2023-09-16 23:41:30 +02:00
* @ param string | null $attr [ 'class' ] Optional . Additional CSS classes , separated by whitespace .
2024-09-06 01:26:42 +02:00
* @ param string | null $args [ 'splide' ] Configuration JSON for the Splide slider . Default empty .
2023-01-21 01:31:34 +01:00
*
2024-01-29 14:52:56 +01:00
* @ return string The captured shortcode HTML .
2023-01-21 01:31:34 +01:00
*/
function fictioneer_shortcode_latest_chapters ( $attr ) {
2023-09-16 22:59:43 +02:00
// Defaults
$args = fictioneer_get_default_shortcode_args ( $attr , 4 );
2023-01-21 01:31:34 +01:00
2023-09-16 22:59:43 +02:00
// Specifics
$args [ 'simple' ] = false ;
2024-04-18 02:18:36 +02:00
$args [ 'spoiler' ] = filter_var ( $attr [ 'spoiler' ] ? ? 0 , FILTER_VALIDATE_BOOLEAN );
2023-03-08 23:02:54 +01:00
2023-09-16 22:59:43 +02:00
// Type
$type = sanitize_text_field ( $attr [ 'type' ] ? ? 'default' );
2023-09-16 21:44:12 +02:00
2024-09-06 01:26:42 +02:00
// Extra classes
if ( $args [ 'splide' ] ? ? 0 ) {
2024-10-06 23:53:02 +02:00
$args [ 'classes' ] .= ' splide _splide-placeholder' ;
2024-09-06 01:26:42 +02:00
}
2023-08-06 04:57:12 +02:00
// Transient?
2024-10-13 14:15:20 +02:00
$transient_enabled = fictioneer_enable_shortcode_transients ( 'fictioneer_latest_chapters' );
if ( $transient_enabled && $args [ 'cache' ] ) {
2023-09-16 02:20:07 +02:00
$base = serialize ( $args ) . serialize ( $attr );
2023-08-06 04:57:12 +02:00
$transient_key = " fictioneer_shortcode_latest_chapters_ { $type } _html_ " . md5 ( $base );
$transient = get_transient ( $transient_key );
if ( ! empty ( $transient ) ) {
return $transient ;
}
}
2023-01-21 01:31:34 +01:00
// Buffer
ob_start ();
switch ( $type ) {
case 'compact' :
2023-03-08 23:02:54 +01:00
get_template_part ( 'partials/_latest-chapters-compact' , null , $args );
2023-01-21 01:31:34 +01:00
break ;
2024-08-21 22:53:24 +02:00
case 'list' :
get_template_part ( 'partials/_latest-chapters-list' , null , $args );
break ;
2023-01-21 01:31:34 +01:00
default :
2023-03-08 23:02:54 +01:00
$args [ 'simple' ] = $type == 'simple' ;
get_template_part ( 'partials/_latest-chapters' , null , $args );
2023-01-21 01:31:34 +01:00
}
2023-08-06 04:57:12 +02:00
$html = fictioneer_minify_html ( ob_get_clean () );
2024-09-06 01:26:42 +02:00
if ( ( $args [ 'splide' ] ? ? 0 ) && strpos ( $args [ 'classes' ], 'no-auto-splide' ) === false ) {
2024-10-09 19:30:37 +02:00
$html .= fictioneer_get_splide_inline_init ();
2024-09-06 01:26:42 +02:00
}
2024-10-13 14:15:20 +02:00
if ( $transient_enabled && $args [ 'cache' ] ) {
2023-08-06 04:57:12 +02:00
set_transient ( $transient_key , $html , FICTIONEER_SHORTCODE_TRANSIENT_EXPIRATION );
}
2023-06-10 18:43:58 +02:00
// Return minified buffer
2023-08-06 04:57:12 +02:00
return $html ;
2023-01-21 01:31:34 +01:00
}
add_shortcode ( 'fictioneer_latest_chapters' , 'fictioneer_shortcode_latest_chapters' );
// =============================================================================
// LATEST STORIES SHORTCODE
// =============================================================================
/**
* Shortcode to show latest stories
*
* @ since 3.0
*
2023-09-16 23:41:30 +02:00
* @ param string | null $attr [ 'count' ] Optional . Maximum number of items . Default 4.
* @ param string | null $attr [ 'author' ] Optional . Limit posts to a specific author .
* @ param string | null $attr [ 'type' ] Optional . Choose between 'default' and 'compact' .
* @ param string | null $attr [ 'order' ] Optional . Order argument . Default 'DESC' .
* @ param string | null $attr [ 'orderby' ] Optional . Orderby argument . Default 'date' .
* @ param string | null $attr [ 'post_ids' ] Optional . Limit posts to specific post IDs .
* @ param string | null $attr [ 'ignore_protected' ] Optional . Whether to ignore protected posts . Default false .
2024-09-20 23:41:37 +02:00
* @ param string | null $attr [ 'only_protected' ] Optional . Whether to query only protected posts . Default false .
2023-09-16 23:41:30 +02:00
* @ param string | null $attr [ 'author_ids' ] Optional . Only include posts by these author IDs .
* @ param string | null $attr [ 'exclude_author_ids' ] Optional . Exclude posts with these author IDs .
* @ param string | null $attr [ 'exclude_tag_ids' ] Optional . Exclude posts with these tags .
* @ param string | null $attr [ 'exclude_cat_ids' ] Optional . Exclude posts with these categories .
* @ param string | null $attr [ 'categories' ] Optional . Limit posts to specific category names .
* @ param string | null $attr [ 'tags' ] Optional . Limit posts to specific tag names .
* @ param string | null $attr [ 'fandoms' ] Optional . Limit posts to specific fandom names .
* @ param string | null $attr [ 'genres' ] Optional . Limit posts to specific genre names .
* @ param string | null $attr [ 'characters' ] Optional . Limit posts to specific character names .
* @ param string | null $attr [ 'rel' ] Optional . Relationship between taxonomies . Default 'AND' .
2024-04-25 14:18:57 +02:00
* @ param string | null $attr [ 'vertical' ] Optional . Whether to show the vertical variant .
2024-05-15 09:49:51 +02:00
* @ param string | null $attr [ 'seamless' ] Optional . Whether to render the image seamless . Default false ( Customizer ) .
2024-04-25 14:18:57 +02:00
* @ param string | null $attr [ 'aspect_ratio' ] Optional . Aspect ratio for the image . Only with vertical .
* @ param string | null $attr [ 'lightbox' ] Optional . Whether the thumbnail is opened in the lightbox . Default true .
2024-05-15 09:49:51 +02:00
* @ param string | null $attr [ 'thumbnail' ] Optional . Whether to show the thumbnail . Default true ( Customizer ) .
2024-08-21 22:53:24 +02:00
* @ param string | null $attr [ 'date_format' ] Optional . String to override the date format . Default empty .
* @ param string | null $attr [ 'terms' ] Optional . Either 'inline' , 'pills' , 'none' , or 'false' ( only in list type ) .
* Default 'inline' .
* @ param string | null $attr [ 'max_terms' ] Optional . Maximum number of shown taxonomies . Default 10.
* @ param string | null $attr [ 'footer' ] Optional . Whether to show the footer ( if any ) . Default true .
* @ param string | null $attr [ 'footer_author' ] Optional . Whether to show the story author . Default true .
* @ param string | null $attr [ 'footer_date' ] Optional . Whether to show the story date . Default true .
* @ param string | null $attr [ 'footer_words' ] Optional . Whether to show the story word count . Default true .
* @ param string | null $attr [ 'footer_chapters' ] Optional . Whether to show the story chapter count . Default true .
* @ param string | null $attr [ 'footer_status' ] Optional . Whether to show the story status . Default true .
* @ param string | null $attr [ 'footer_rating' ] Optional . Whether to show the story age rating . Default true .
2024-11-26 12:11:30 +01:00
* @ param string | null $attr [ 'footer_comments' ] Optional . Whether to show the post comment count . Default false .
2023-09-16 23:41:30 +02:00
* @ param string | null $attr [ 'class' ] Optional . Additional CSS classes , separated by whitespace .
2024-09-06 01:26:42 +02:00
* @ param string | null $args [ 'splide' ] Configuration JSON for the Splide slider . Default empty .
2023-01-21 01:31:34 +01:00
*
2024-01-29 14:52:56 +01:00
* @ return string The captured shortcode HTML .
2023-01-21 01:31:34 +01:00
*/
function fictioneer_shortcode_latest_stories ( $attr ) {
2023-09-16 22:59:43 +02:00
// Defaults
$args = fictioneer_get_default_shortcode_args ( $attr , 4 );
2023-09-16 02:20:07 +02:00
2023-09-16 21:44:12 +02:00
// Type
2023-09-16 22:59:43 +02:00
$type = sanitize_text_field ( $attr [ 'type' ] ? ? 'default' );
2023-09-16 21:44:12 +02:00
2024-11-26 12:11:30 +01:00
// Comments
$args [ 'footer_comments' ] = filter_var ( $attr [ 'footer_comments' ] ? ? 0 , FILTER_VALIDATE_BOOLEAN );
2024-08-21 22:53:24 +02:00
// Terms
$args [ 'terms' ] = fictioneer_sanitize_query_var ( $attr [ 'terms' ] ? ? 0 , [ 'inline' , 'pills' , 'none' , 'false' ], 'inline' );
2024-08-23 23:12:24 +02:00
$args [ 'max_terms' ] = absint ( ( $attr [ 'max_terms' ] ? ? 10 ) ? : 10 );
2024-08-21 22:53:24 +02:00
2024-09-06 01:26:42 +02:00
// Extra classes
if ( $args [ 'splide' ] ? ? 0 ) {
2024-10-06 23:53:02 +02:00
$args [ 'classes' ] .= ' splide _splide-placeholder' ;
2024-09-06 01:26:42 +02:00
}
2023-08-06 04:57:12 +02:00
// Transient?
2024-10-13 14:15:20 +02:00
$transient_enabled = fictioneer_enable_shortcode_transients ( 'fictioneer_latest_stories' );
if ( $transient_enabled && $args [ 'cache' ] ) {
2023-09-16 02:20:07 +02:00
$base = serialize ( $args ) . serialize ( $attr );
2023-08-06 04:57:12 +02:00
$transient_key = " fictioneer_shortcode_latest_stories_ { $type } _html_ " . md5 ( $base );
$transient = get_transient ( $transient_key );
if ( ! empty ( $transient ) ) {
return $transient ;
}
}
2023-01-21 01:31:34 +01:00
// Buffer
ob_start ();
switch ( $type ) {
case 'compact' :
2023-03-08 11:36:26 +01:00
get_template_part ( 'partials/_latest-stories-compact' , null , $args );
2023-01-21 01:31:34 +01:00
break ;
2024-08-21 22:53:24 +02:00
case 'list' :
get_template_part ( 'partials/_latest-stories-list' , null , $args );
break ;
2023-01-21 01:31:34 +01:00
default :
2023-03-08 11:36:26 +01:00
get_template_part ( 'partials/_latest-stories' , null , $args );
2023-01-21 01:31:34 +01:00
}
2023-08-06 04:57:12 +02:00
$html = fictioneer_minify_html ( ob_get_clean () );
2024-09-06 01:26:42 +02:00
if ( ( $args [ 'splide' ] ? ? 0 ) && strpos ( $args [ 'classes' ], 'no-auto-splide' ) === false ) {
2024-10-09 19:30:37 +02:00
$html .= fictioneer_get_splide_inline_init ();
2024-09-06 01:26:42 +02:00
}
2024-10-13 14:15:20 +02:00
if ( $transient_enabled && $args [ 'cache' ] ) {
2023-08-06 04:57:12 +02:00
set_transient ( $transient_key , $html , FICTIONEER_SHORTCODE_TRANSIENT_EXPIRATION );
}
2023-06-10 18:43:58 +02:00
// Return minified buffer
2023-08-06 04:57:12 +02:00
return $html ;
2023-01-21 01:31:34 +01:00
}
add_shortcode ( 'fictioneer_latest_stories' , 'fictioneer_shortcode_latest_stories' );
// =============================================================================
// LATEST UPDATES SHORTCODE
// =============================================================================
/**
* Shortcode to show latest story updates
*
2024-01-26 17:45:59 +01:00
* @ since 4.3 . 0
2023-01-21 01:31:34 +01:00
*
2023-09-16 23:41:30 +02:00
* @ param string | null $attr [ 'count' ] Optional . Maximum number of items . Default 4.
* @ param string | null $attr [ 'author' ] Optional . Limit posts to a specific author .
2024-07-24 12:33:11 +02:00
* @ param string | null $attr [ 'type' ] Optional . Choose between 'default' , 'simple' , 'single' , and 'compact' .
2024-07-25 00:31:41 +02:00
* @ param string | null $attr [ 'single' ] Optional . Whether to show only one chapter item . Default false .
2023-09-16 23:41:30 +02:00
* @ param string | null $attr [ 'post_ids' ] Optional . Limit posts to specific post IDs .
* @ param string | null $attr [ 'ignore_protected' ] Optional . Whether to ignore protected posts . Default false .
2024-09-20 23:41:37 +02:00
* @ param string | null $attr [ 'only_protected' ] Optional . Whether to query only protected posts . Default false .
2023-09-16 23:41:30 +02:00
* @ param string | null $attr [ 'exclude_tag_ids' ] Optional . Exclude posts with these tags .
* @ param string | null $attr [ 'author_ids' ] Optional . Only include posts by these author IDs .
* @ param string | null $attr [ 'exclude_author_ids' ] Optional . Exclude posts with these author IDs .
* @ param string | null $attr [ 'exclude_cat_ids' ] Optional . Exclude posts with these categories .
* @ param string | null $attr [ 'categories' ] Optional . Limit posts to specific category names .
* @ param string | null $attr [ 'tags' ] Optional . Limit posts to specific tag names .
* @ param string | null $attr [ 'fandoms' ] Optional . Limit posts to specific fandom names .
* @ param string | null $attr [ 'genres' ] Optional . Limit posts to specific genre names .
* @ param string | null $attr [ 'characters' ] Optional . Limit posts to specific character names .
* @ param string | null $attr [ 'rel' ] Optional . Relationship between taxonomies . Default 'AND' .
2024-04-14 15:54:35 +02:00
* @ param string | null $attr [ 'vertical' ] Optional . Whether to show the vertical variant .
2024-05-15 09:49:51 +02:00
* @ param string | null $attr [ 'seamless' ] Optional . Whether to render the image seamless . Default false ( Customizer ) .
2024-04-14 15:54:35 +02:00
* @ param string | null $attr [ 'aspect_ratio' ] Optional . Aspect ratio for the image . Only with vertical .
2024-04-25 14:18:57 +02:00
* @ param string | null $attr [ 'lightbox' ] Optional . Whether the thumbnail is opened in the lightbox . Default true .
2024-05-15 09:49:51 +02:00
* @ param string | null $attr [ 'thumbnail' ] Optional . Whether to show the thumbnail . Default true ( Customizer ) .
2024-05-29 00:01:31 +02:00
* @ param string | null $attr [ 'words' ] Optional . Whether to show the word count of chapter items . Default true .
* @ param string | null $attr [ 'date' ] Optional . Whether to show the date of chapter items . Default true .
2024-08-21 22:53:24 +02:00
* @ param string | null $attr [ 'date_format' ] Optional . String to override the date format . Default empty .
* @ param string | null $attr [ 'nested_date_format' ] Optional . String to override any nested date formats . Default empty .
* @ param string | null $attr [ 'terms' ] Optional . Either 'inline' , 'pills' , 'none' , or 'false' ( only in list type ) .
* Default 'inline' .
* @ param string | null $attr [ 'max_terms' ] Optional . Maximum number of shown taxonomies . Default 10.
* @ param string | null $attr [ 'footer' ] Optional . Whether to show the footer ( if any ) . Default true .
* @ param string | null $attr [ 'footer_author' ] Optional . Whether to show the story author . Default true .
* @ param string | null $attr [ 'footer_date' ] Optional . Whether to show the story date . Default true .
* @ param string | null $attr [ 'footer_words' ] Optional . Whether to show the story word count . Default true .
* @ param string | null $attr [ 'footer_chapters' ] Optional . Whether to show the story chapter count . Default true .
* @ param string | null $attr [ 'footer_status' ] Optional . Whether to show the story status . Default true .
* @ param string | null $attr [ 'footer_rating' ] Optional . Whether to show the story / chapter age rating . Default true .
2024-11-26 12:11:30 +01:00
* @ param string | null $attr [ 'footer_comments' ] Optional . Whether to show the post comment count . Default false .
2023-09-16 23:41:30 +02:00
* @ param string | null $attr [ 'class' ] Optional . Additional CSS classes , separated by whitespace .
2024-09-06 01:26:42 +02:00
* @ param string | null $args [ 'splide' ] Configuration JSON for the Splide slider . Default empty .
2023-01-21 01:31:34 +01:00
*
2024-01-29 14:52:56 +01:00
* @ return string The captured shortcode HTML .
2023-01-21 01:31:34 +01:00
*/
function fictioneer_shortcode_latest_story_updates ( $attr ) {
2023-09-16 22:59:43 +02:00
// Defaults
$args = fictioneer_get_default_shortcode_args ( $attr , 4 );
2024-07-25 00:31:41 +02:00
$args [ 'single' ] = filter_var ( $attr [ 'single' ] ? ? 0 , FILTER_VALIDATE_BOOLEAN );
2023-09-16 02:20:07 +02:00
2024-11-26 12:11:30 +01:00
// Comments
$args [ 'footer_comments' ] = filter_var ( $attr [ 'footer_comments' ] ? ? 0 , FILTER_VALIDATE_BOOLEAN );
2023-09-16 21:44:12 +02:00
// Type
2023-09-16 22:59:43 +02:00
$type = sanitize_text_field ( $attr [ 'type' ] ? ? 'default' );
2023-09-16 21:44:12 +02:00
2024-08-21 22:53:24 +02:00
// Terms
$args [ 'terms' ] = fictioneer_sanitize_query_var ( $attr [ 'terms' ] ? ? 0 , [ 'inline' , 'pills' , 'none' , 'false' ], 'inline' );
2024-08-23 23:12:24 +02:00
$args [ 'max_terms' ] = absint ( ( $attr [ 'max_terms' ] ? ? 10 ) ? : 10 );
2024-08-21 22:53:24 +02:00
2024-09-06 01:26:42 +02:00
// Extra classes
if ( $args [ 'splide' ] ? ? 0 ) {
2024-10-06 23:53:02 +02:00
$args [ 'classes' ] .= ' splide _splide-placeholder ' ;
2024-09-06 01:26:42 +02:00
}
2023-08-06 04:57:12 +02:00
// Transient?
2024-10-13 14:15:20 +02:00
$transient_enabled = fictioneer_enable_shortcode_transients ( 'fictioneer_latest_updates' );
if ( $transient_enabled && $args [ 'cache' ] ) {
2023-09-16 02:20:07 +02:00
$base = serialize ( $args ) . serialize ( $attr );
2023-08-06 04:57:12 +02:00
$transient_key = " fictioneer_shortcode_latest_updates_ { $type } _html_ " . md5 ( $base );
$transient = get_transient ( $transient_key );
if ( ! empty ( $transient ) ) {
return $transient ;
}
}
2023-01-21 01:31:34 +01:00
// Buffer
ob_start ();
switch ( $type ) {
case 'compact' :
2023-03-08 23:02:54 +01:00
get_template_part ( 'partials/_latest-updates-compact' , null , $args );
2023-01-21 01:31:34 +01:00
break ;
2024-08-21 22:53:24 +02:00
case 'list' :
get_template_part ( 'partials/_latest-updates-list' , null , $args );
break ;
2023-01-21 01:31:34 +01:00
default :
2023-03-08 23:02:54 +01:00
get_template_part ( 'partials/_latest-updates' , null , $args );
2023-01-21 01:31:34 +01:00
}
2023-08-06 04:57:12 +02:00
$html = fictioneer_minify_html ( ob_get_clean () );
2024-09-06 01:26:42 +02:00
if ( ( $args [ 'splide' ] ? ? 0 ) && strpos ( $args [ 'classes' ], 'no-auto-splide' ) === false ) {
2024-10-09 19:30:37 +02:00
$html .= fictioneer_get_splide_inline_init ();
2024-09-06 01:26:42 +02:00
}
2024-10-13 14:15:20 +02:00
if ( $transient_enabled && $args [ 'cache' ] ) {
2023-08-06 04:57:12 +02:00
set_transient ( $transient_key , $html , FICTIONEER_SHORTCODE_TRANSIENT_EXPIRATION );
}
2023-06-10 18:43:58 +02:00
// Return minified buffer
2023-08-06 04:57:12 +02:00
return $html ;
2023-01-21 01:31:34 +01:00
}
add_shortcode ( 'fictioneer_latest_updates' , 'fictioneer_shortcode_latest_story_updates' );
// =============================================================================
// LATEST RECOMMENDATIONS SHORTCODE
// =============================================================================
/**
* Shortcode to show latest recommendations
*
2024-01-26 17:45:59 +01:00
* @ since 4.0 . 0
2023-01-21 01:31:34 +01:00
*
2023-09-16 23:41:30 +02:00
* @ param string | null $attr [ 'count' ] Optional . Maximum number of items . Default 4.
* @ param string | null $attr [ 'author' ] Optional . Limit posts to a specific author .
* @ param string | null $attr [ 'type' ] Optional . Choose between 'default' and 'compact' .
* @ param string | null $attr [ 'order' ] Optional . Order argument . Default 'DESC' .
* @ param string | null $attr [ 'orderby' ] Optional . Orderby argument . Default 'date' .
* @ param string | null $attr [ 'post_ids' ] Optional . Limit posts to specific post IDs .
* @ param string | null $attr [ 'ignore_protected' ] Optional . Whether to ignore protected posts . Default false .
2024-09-20 23:41:37 +02:00
* @ param string | null $attr [ 'only_protected' ] Optional . Whether to query only protected posts . Default false .
2023-09-16 23:41:30 +02:00
* @ param string | null $attr [ 'author_ids' ] Optional . Only include posts by these author IDs .
* @ param string | null $attr [ 'exclude_author_ids' ] Optional . Exclude posts with these author IDs .
* @ param string | null $attr [ 'exclude_tag_ids' ] Optional . Exclude posts with these tags .
* @ param string | null $attr [ 'exclude_cat_ids' ] Optional . Exclude posts with these categories .
* @ param string | null $attr [ 'categories' ] Optional . Limit posts to specific category names .
* @ param string | null $attr [ 'tags' ] Optional . Limit posts to specific tag names .
* @ param string | null $attr [ 'fandoms' ] Optional . Limit posts to specific fandom names .
* @ param string | null $attr [ 'genres' ] Optional . Limit posts to specific genre names .
* @ param string | null $attr [ 'characters' ] Optional . Limit posts to specific character names .
* @ param string | null $attr [ 'rel' ] Optional . Relationship between taxonomies . Default 'AND' .
2024-04-25 14:18:57 +02:00
* @ param string | null $attr [ 'vertical' ] Optional . Whether to show the vertical variant .
2024-05-15 09:49:51 +02:00
* @ param string | null $attr [ 'seamless' ] Optional . Whether to render the image seamless . Default false ( Customizer ) .
2024-04-25 14:18:57 +02:00
* @ param string | null $attr [ 'aspect_ratio' ] Optional . Aspect ratio for the image . Only with vertical .
* @ param string | null $attr [ 'lightbox' ] Optional . Whether the thumbnail is opened in the lightbox . Default true .
2024-05-15 09:49:51 +02:00
* @ param string | null $attr [ 'thumbnail' ] Optional . Whether to show the thumbnail . Default true ( Customizer ) .
2023-09-16 23:41:30 +02:00
* @ param string | null $attr [ 'class' ] Optional . Additional CSS classes , separated by whitespace .
2024-09-06 01:26:42 +02:00
* @ param string | null $args [ 'splide' ] Configuration JSON for the Splide slider . Default empty .
2023-01-21 01:31:34 +01:00
*
2024-01-29 14:52:56 +01:00
* @ return string The captured shortcode HTML .
2023-01-21 01:31:34 +01:00
*/
function fictioneer_shortcode_latest_recommendations ( $attr ) {
2023-09-16 22:59:43 +02:00
// Defaults
$args = fictioneer_get_default_shortcode_args ( $attr , 4 );
2023-09-16 02:20:07 +02:00
2023-09-16 21:44:12 +02:00
// Type
2023-09-16 22:59:43 +02:00
$type = sanitize_text_field ( $attr [ 'type' ] ? ? 'default' );
2023-09-16 21:44:12 +02:00
2024-08-23 23:12:24 +02:00
// Terms
$args [ 'terms' ] = fictioneer_sanitize_query_var ( $attr [ 'terms' ] ? ? 0 , [ 'inline' , 'pills' , 'none' , 'false' ], 'inline' );
$args [ 'max_terms' ] = absint ( ( $attr [ 'max_terms' ] ? ? 10 ) ? : 10 );
2024-09-06 01:26:42 +02:00
// Extra classes
if ( $args [ 'splide' ] ? ? 0 ) {
2024-10-06 23:53:02 +02:00
$args [ 'classes' ] .= ' splide _splide-placeholder' ;
2024-09-06 01:26:42 +02:00
}
2023-08-06 04:57:12 +02:00
// Transient?
2024-10-13 14:15:20 +02:00
$transient_enabled = fictioneer_enable_shortcode_transients ( 'fictioneer_latest_recommendations' );
if ( $transient_enabled && $args [ 'cache' ] ) {
2023-09-16 02:20:07 +02:00
$base = serialize ( $args ) . serialize ( $attr );
2023-08-06 04:57:12 +02:00
$transient_key = " fictioneer_shortcode_latest_recommendations_ { $type } _html_ " . md5 ( $base );
$transient = get_transient ( $transient_key );
if ( ! empty ( $transient ) ) {
return $transient ;
}
}
2023-01-21 01:31:34 +01:00
// Buffer
ob_start ();
switch ( $type ) {
case 'compact' :
2023-03-08 23:02:54 +01:00
get_template_part ( 'partials/_latest-recommendations-compact' , null , $args );
2023-01-21 01:31:34 +01:00
break ;
default :
2023-03-08 23:02:54 +01:00
get_template_part ( 'partials/_latest-recommendations' , null , $args );
2023-01-21 01:31:34 +01:00
}
2023-08-06 04:57:12 +02:00
$html = fictioneer_minify_html ( ob_get_clean () );
2024-09-06 01:26:42 +02:00
if ( ( $args [ 'splide' ] ? ? 0 ) && strpos ( $args [ 'classes' ], 'no-auto-splide' ) === false ) {
2024-10-09 19:30:37 +02:00
$html .= fictioneer_get_splide_inline_init ();
2024-09-06 01:26:42 +02:00
}
2024-10-13 14:15:20 +02:00
if ( $transient_enabled && $args [ 'cache' ] ) {
2023-08-06 04:57:12 +02:00
set_transient ( $transient_key , $html , FICTIONEER_SHORTCODE_TRANSIENT_EXPIRATION );
}
2023-06-10 18:43:58 +02:00
// Return minified buffer
2023-08-06 04:57:12 +02:00
return $html ;
2023-01-21 01:31:34 +01:00
}
add_shortcode ( 'fictioneer_latest_recommendations' , 'fictioneer_shortcode_latest_recommendations' );
// =============================================================================
// LATEST POST SHORTCODE
// =============================================================================
/**
* Shortcode to show the latest post
*
2024-01-26 17:45:59 +01:00
* @ since 4.0 . 0
2023-01-21 01:31:34 +01:00
*
2023-09-16 23:41:30 +02:00
* @ param string | null $attr [ 'count' ] Optional . Maximum number of items . Default 1.
* @ param string | null $attr [ 'author' ] Optional . Limit posts to a specific author .
* @ param string | null $attr [ 'post_ids' ] Optional . Limit posts to specific post IDs .
* @ param string | null $attr [ 'ignore_protected' ] Optional . Whether to ignore protected posts . Default false .
2024-09-20 23:41:37 +02:00
* @ param string | null $attr [ 'only_protected' ] Optional . Whether to query only protected posts . Default false .
2023-09-16 23:41:30 +02:00
* @ param string | null $attr [ 'author_ids' ] Optional . Only include posts by these author IDs .
* @ param string | null $attr [ 'exclude_author_ids' ] Optional . Exclude posts with these author IDs .
* @ param string | null $attr [ 'exclude_tag_ids' ] Optional . Exclude posts with these tags .
* @ param string | null $attr [ 'exclude_cat_ids' ] Optional . Exclude posts with these categories .
* @ param string | null $attr [ 'categories' ] Optional . Limit posts to specific category names .
* @ param string | null $attr [ 'tags' ] Optional . Limit posts to specific tag names .
* @ param string | null $attr [ 'rel' ] Optional . Relationship between taxonomies . Default 'AND' .
* @ param string | null $attr [ 'class' ] Optional . Additional CSS classes , separated by whitespace .
2023-01-21 01:31:34 +01:00
*
2024-01-29 14:52:56 +01:00
* @ return string The captured shortcode HTML .
2023-01-21 01:31:34 +01:00
*/
function fictioneer_shortcode_latest_posts ( $attr ) {
2023-09-16 22:59:43 +02:00
// Defaults
$args = fictioneer_get_default_shortcode_args ( $attr , 1 );
2023-09-16 21:44:12 +02:00
2023-08-06 04:57:12 +02:00
// Transient?
2024-10-13 14:15:20 +02:00
$transient_enabled = fictioneer_enable_shortcode_transients ( 'fictioneer_latest_posts' );
if ( $transient_enabled && $args [ 'cache' ] ) {
2023-09-16 02:20:07 +02:00
$base = serialize ( $args ) . serialize ( $attr );
2023-08-06 04:57:12 +02:00
$transient_key = " fictioneer_shortcode_latest_posts_html_ " . md5 ( $base );
$transient = get_transient ( $transient_key );
if ( ! empty ( $transient ) ) {
return $transient ;
}
}
2023-01-21 01:31:34 +01:00
// Buffer
ob_start ();
2023-08-06 04:57:12 +02:00
get_template_part ( 'partials/_latest-posts' , null , $args );
$html = fictioneer_minify_html ( ob_get_clean () );
2024-10-13 14:15:20 +02:00
if ( $transient_enabled && $args [ 'cache' ] ) {
2023-08-06 04:57:12 +02:00
set_transient ( $transient_key , $html , FICTIONEER_SHORTCODE_TRANSIENT_EXPIRATION );
}
2023-01-21 01:31:34 +01:00
2023-06-10 18:43:58 +02:00
// Return minified buffer
2023-08-06 04:57:12 +02:00
return $html ;
2023-01-21 01:31:34 +01:00
}
add_shortcode ( 'fictioneer_latest_posts' , 'fictioneer_shortcode_latest_posts' );
// =============================================================================
// BOOKMARKS SHORTCODE
// =============================================================================
/**
* Shortcode to show bookmarks
*
2024-01-26 17:45:59 +01:00
* @ since 4.0 . 0
2023-01-21 01:31:34 +01:00
*
2023-08-09 10:19:20 +02:00
* @ param string | null $attr [ 'count' ] Optional . Maximum number of items . Default - 1 ( all ) .
* @ param string | null $attr [ 'show_empty' ] Optional . Whether to show the " no bookmarks " message . Default false .
2024-05-15 11:35:14 +02:00
* @ param string | null $attr [ 'seamless' ] Optional . Whether to render the image seamless . Default false ( Customizer ) .
* @ param string | null $attr [ 'thumbnail' ] Optional . Whether to show the thumbnail . Default true ( Customizer ) .
2023-01-21 01:31:34 +01:00
*
2024-01-29 14:52:56 +01:00
* @ return string The captured shortcode HTML .
2023-01-21 01:31:34 +01:00
*/
function fictioneer_shortcode_bookmarks ( $attr ) {
2023-09-16 02:20:07 +02:00
// Sanitize attributes
$attr = is_array ( $attr ) ? array_map ( 'sanitize_text_field' , $attr ) : sanitize_text_field ( $attr );
2023-01-21 01:31:34 +01:00
// Setup
2024-05-15 11:35:14 +02:00
$seamless_default = get_theme_mod ( 'card_image_style' , 'default' ) === 'seamless' ;
$thumbnail_default = get_theme_mod ( 'card_image_style' , 'default' ) !== 'none' ;
2023-01-21 01:31:34 +01:00
// Buffer
ob_start ();
get_template_part ( 'partials/_bookmarks' , null , array (
2024-05-15 11:35:14 +02:00
'count' => max ( - 1 , intval ( $attr [ 'count' ] ? ? - 1 ) ),
'show_empty' => $attr [ 'show_empty' ] ? ? false ,
'seamless' => filter_var ( $attr [ 'seamless' ] ? ? $seamless_default , FILTER_VALIDATE_BOOLEAN ),
'thumbnail' => filter_var ( $attr [ 'thumbnail' ] ? ? $thumbnail_default , FILTER_VALIDATE_BOOLEAN )
2023-01-21 01:31:34 +01:00
));
2023-06-10 18:43:58 +02:00
// Return minified buffer
return fictioneer_minify_html ( ob_get_clean () );
2023-01-21 01:31:34 +01:00
}
add_shortcode ( 'fictioneer_bookmarks' , 'fictioneer_shortcode_bookmarks' );
// =============================================================================
// COOKIES SHORTCODE
// =============================================================================
/**
* Shortcode to show cookie consent actions
*
* Renders buttons to handle your consent and stored cookies .
*
2024-01-26 17:45:59 +01:00
* @ since 4.7 . 0
2023-01-21 01:31:34 +01:00
*
2024-01-29 14:52:56 +01:00
* @ return string The captured shortcode HTML .
2023-01-21 01:31:34 +01:00
*/
function fictioneer_shortcode_cookie_buttons ( $attr ) {
ob_start ();
2024-08-22 20:26:14 +02:00
// Start HTML ---> ?>
< div class = " cookies spacing-top spacing-bottom " >
2024-12-06 17:38:32 +01:00
< button type = " button " data - action = " click->fictioneer#clearConsent " class = " button " >< ? php _e ( 'Reset Consent' , 'fictioneer' ); ?> </button>
< button type = " button " data - action = " click->fictioneer#clearCookies " data - message = " <?php _e( 'Cookies and local storage have been cleared. To keep it that way, you should leave the site.', 'fictioneer' ); ?> " class = " button " >< ? php _e ( 'Clear Cookies' , 'fictioneer' ); ?> </button>
2024-08-22 20:26:14 +02:00
</ div >
< ? php // <--- End HTML
2023-06-10 18:43:58 +02:00
return fictioneer_minify_html ( ob_get_clean () );
2023-01-21 01:31:34 +01:00
}
add_shortcode ( 'fictioneer_cookie_buttons' , 'fictioneer_shortcode_cookie_buttons' );
// =============================================================================
// CHAPTER LIST SHORTCODE
// =============================================================================
/**
2024-01-29 14:32:25 +01:00
* Returns empty chapter list
2023-01-21 01:31:34 +01:00
*
2024-01-29 14:32:25 +01:00
* @ since 5.9 . 4
2023-01-21 01:31:34 +01:00
*
2024-02-13 14:13:10 +01:00
* @ param string | null $attr [ 'heading' ] Optional . Show < h5 > heading above list .
2023-01-21 01:31:34 +01:00
*
2024-01-29 14:32:25 +01:00
* @ return string The captured HTML .
2023-01-21 01:31:34 +01:00
*/
2024-01-29 14:32:25 +01:00
function fictioneer_shortcode_chapter_list_empty ( $attr ) {
2023-01-21 01:31:34 +01:00
ob_start ();
2024-01-29 14:32:25 +01:00
2023-01-21 01:31:34 +01:00
// Start HTML ---> ?>
2024-03-05 11:38:17 +01:00
< div class = " chapter-group chapter-list _standalone _empty " >
2023-01-21 01:31:34 +01:00
< ? php if ( ! empty ( $attr [ 'heading' ] ) ) : ?>
2024-12-06 17:38:32 +01:00
< button class = " chapter-group__name " data - action = " click->fictioneer#toggleChapterGroup " aria - label = " <?php echo esc_attr( sprintf( __( 'Toggle chapter group: %s', 'fictioneer' ), $attr['heading'] ) ); ?> " tabindex = " 0 " >
2023-02-17 11:55:55 +01:00
< i class = " fa-solid fa-chevron-down chapter-group__heading-icon " ></ i >
< span >< ? php echo $attr [ 'heading' ]; ?> </span>
2023-06-10 18:23:04 +02:00
</ button >
2023-01-21 01:31:34 +01:00
< ? php endif ; ?>
< ol class = " chapter-group__list " >
2023-09-11 12:26:34 +02:00
< li class = " chapter-group__list-item _empty " >< ? php _e ( 'No chapters published yet.' , 'fictioneer' ); ?> </li>
2023-01-21 01:31:34 +01:00
</ ol >
</ div >
< ? php // <--- End HTML
2024-01-29 14:32:25 +01:00
return fictioneer_minify_html ( ob_get_clean () );
}
/**
* Shortcode to show chapter list outside of story pages
*
* @ since 5.0 . 0
*
* @ param string $attr [ 'story_id' ] Either / Or . The ID of the story the chapters belong to .
* @ param string | null $attr [ 'chapter_ids' ] Either / Or . Comma - separated list of chapter IDs .
* @ param string | null $attr [ 'count' ] Optional . Maximum number of items . Default - 1 ( all ) .
* @ param string | null $attr [ 'offset' ] Optional . Skip a number of posts .
* @ param string | null $attr [ 'group' ] Optional . Only show chapters of the group .
* @ param string | null $attr [ 'heading' ] Optional . Show < h5 > heading above list .
* @ param string | null $attr [ 'class' ] Optional . Additional CSS classes , separated by whitespace .
*
* @ return string The captured shortcode HTML .
*/
function fictioneer_shortcode_chapter_list ( $attr ) {
// Sanitize attributes
$attr = is_array ( $attr ) ? array_map ( 'sanitize_text_field' , $attr ) : sanitize_text_field ( $attr );
// Return empty case if...
2023-08-17 01:32:02 +02:00
if ( empty ( $attr [ 'story_id' ] ) && empty ( $attr [ 'chapter_ids' ] ) ) {
2024-01-29 14:32:25 +01:00
return fictioneer_shortcode_chapter_list_empty ( $attr );
2023-08-17 01:32:02 +02:00
}
2023-01-21 01:31:34 +01:00
// Setup
2024-09-07 00:28:36 +02:00
$cache = filter_var ( $attr [ 'cache' ] ? ? 1 , FILTER_VALIDATE_BOOLEAN );
2023-01-21 01:31:34 +01:00
$count = max ( - 1 , intval ( $attr [ 'count' ] ? ? - 1 ) );
$offset = max ( 0 , intval ( $attr [ 'offset' ] ? ? 0 ) );
2023-03-11 12:59:33 +01:00
$group = empty ( $attr [ 'group' ] ) ? false : strtolower ( trim ( $attr [ 'group' ] ) );
2023-01-21 01:31:34 +01:00
$heading = empty ( $attr [ 'heading' ] ) ? false : $attr [ 'heading' ];
2023-03-10 16:39:20 +01:00
$story_id = fictioneer_validate_id ( $attr [ 'story_id' ] ? ? - 1 , 'fcn_story' );
2024-06-29 13:37:55 +02:00
$prefer_chapter_icon = get_option ( 'fictioneer_override_chapter_status_icons' );
2023-01-21 01:31:34 +01:00
$hide_icons = get_option ( 'fictioneer_hide_chapter_icons' );
2023-06-05 11:49:01 +02:00
$can_checkmarks = get_option ( 'fictioneer_enable_checkmarks' ) && ( is_user_logged_in () || get_option ( 'fictioneer_enable_ajax_authentication' ) );
2024-04-18 12:27:14 +02:00
$classes = wp_strip_all_tags ( $attr [ 'class' ] ? ? '' );
2023-01-21 01:31:34 +01:00
$chapter_ids = [];
$chapters = [];
// Extract chapter IDs (if any)
2023-03-10 16:39:20 +01:00
if ( ! empty ( $attr [ 'chapter_ids' ] ) ) {
$chapter_ids = fictioneer_explode_list ( $attr [ 'chapter_ids' ] );
2023-01-21 01:31:34 +01:00
}
// Get chapters...
if ( $story_id && empty ( $chapter_ids ) ) {
// ... via story
2023-11-30 16:03:53 +01:00
$hide_icons = $hide_icons || get_post_meta ( $story_id , 'fictioneer_story_hide_chapter_icons' , true );
2023-08-05 18:31:39 +02:00
$story_data = fictioneer_get_story_data ( $story_id , false ); // Does not refresh comment count!
2023-01-21 01:31:34 +01:00
$chapters = $story_data [ 'chapter_ids' ];
} elseif ( ! empty ( $chapter_ids ) ) {
// ... via chapter IDs
$chapters = $chapter_ids ;
}
2023-01-27 01:23:02 +01:00
// Extra classes
2023-08-17 01:32:02 +02:00
if ( $hide_icons ) {
2023-09-15 22:42:34 +02:00
$classes .= ' _no-icons' ;
2023-08-17 01:32:02 +02:00
}
2023-01-21 01:31:34 +01:00
2024-01-18 12:15:19 +01:00
if ( get_option ( 'fictioneer_collapse_groups_by_default' ) && ! str_contains ( $classes , 'no-auto-collapse' ) ) {
$classes .= ' _closed' ;
}
2023-08-17 01:32:02 +02:00
// Apply offset and count
if ( ! $group ) {
$chapters = array_slice ( $chapters , $offset );
$chapters = $count > 0 ? array_slice ( $chapters , 0 , $count ) : $chapters ;
}
2023-01-21 01:31:34 +01:00
2024-01-29 14:32:25 +01:00
// Return empty case if...
2023-08-17 01:32:02 +02:00
if ( empty ( $chapters ) ) {
2024-01-29 14:32:25 +01:00
return fictioneer_shortcode_chapter_list_empty ( $attr );
2023-08-17 01:32:02 +02:00
}
2023-01-21 01:31:34 +01:00
2023-02-17 11:55:55 +01:00
// Query chapters
2023-08-03 13:17:32 +02:00
$query_args = array (
2024-05-23 17:38:05 +02:00
'fictioneer_query_name' => 'fictioneer_shortcode_chapter_list' ,
2023-08-03 13:17:32 +02:00
'post_type' => 'fcn_chapter' ,
'post_status' => 'publish' ,
2023-08-17 01:32:02 +02:00
'post__in' => $chapters , // Cannot be empty!
2023-08-03 13:17:32 +02:00
'ignore_sticky_posts' => true ,
'orderby' => 'post__in' , // Preserve order from meta box
'posts_per_page' => - 1 , // Get all chapters (this can be hundreds)
'no_found_rows' => true , // Improve performance
'update_post_term_cache' => false // Improve performance
2023-02-17 11:55:55 +01:00
);
2023-08-06 04:57:12 +02:00
// Transient?
2024-10-13 14:15:20 +02:00
$transient_enabled = fictioneer_enable_shortcode_transients ( 'fictioneer_chapter_list' );
if ( $transient_enabled && $cache ) {
2023-09-15 22:42:34 +02:00
$base = serialize ( $query_args ) . serialize ( $attr ) . $classes ;
2023-08-06 04:57:12 +02:00
$base .= ( $hide_icons ? '1' : '0' ) . ( $can_checkmarks ? '1' : '0' );
$transient_key = " fictioneer_shortcode_chapter_list_html_ " . md5 ( $base );
$transient = get_transient ( $transient_key );
if ( ! empty ( $transient ) ) {
return $transient ;
}
}
// Query
2023-08-03 13:17:32 +02:00
$chapter_query = fictioneer_shortcode_query ( $query_args );
2024-01-29 14:32:25 +01:00
// Return empty case if...
2023-08-17 01:32:02 +02:00
if ( ! $chapter_query -> have_posts () ) {
2024-01-29 14:32:25 +01:00
return fictioneer_shortcode_chapter_list_empty ( $attr );
2023-08-17 01:32:02 +02:00
}
2023-02-17 11:55:55 +01:00
2023-01-21 01:31:34 +01:00
// Buffer
ob_start ();
// Start HTML ---> ?>
2024-04-18 12:27:14 +02:00
< div class = " chapter-group chapter-list _standalone <?php echo esc_attr( $classes ); ?> " >
2023-01-21 01:31:34 +01:00
< ? php if ( $heading ) : ?>
2024-12-06 17:38:32 +01:00
< button class = " chapter-group__name " data - action = " click->fictioneer#toggleChapterGroup " aria - label = " <?php echo esc_attr( sprintf( __( 'Toggle chapter group: %s', 'fictioneer' ), $heading ) ); ?> " tabindex = " 0 " >
2023-01-23 21:49:08 +01:00
< i class = " fa-solid fa-chevron-down chapter-group__heading-icon " ></ i >
< span >< ? php echo $heading ; ?> </span>
2023-06-10 18:23:04 +02:00
</ button >
2023-01-21 01:31:34 +01:00
< ? php endif ; ?>
< ol class = " chapter-group__list " >
< ? php
$render_count = 0 ;
2024-01-18 21:26:08 +01:00
global $post ;
2023-02-17 11:55:55 +01:00
while ( $chapter_query -> have_posts () ) {
// Setup
$chapter_query -> the_post ();
$chapter_id = get_the_ID ();
2024-10-26 02:03:23 +02:00
$chapter_story_id = fictioneer_get_chapter_story_id ( $chapter_id );
2023-02-17 11:55:55 +01:00
// Skip not visible chapters
2023-11-30 16:03:53 +01:00
if ( get_post_meta ( $chapter_id , 'fictioneer_chapter_hidden' , true ) ) {
2023-08-22 22:51:47 +02:00
continue ;
}
2023-01-21 01:31:34 +01:00
// Check group (if any)
2023-11-30 16:03:53 +01:00
if ( $group && $group != strtolower ( trim ( get_post_meta ( $chapter_id , 'fictioneer_chapter_group' , true ) ) ) ) {
2023-08-22 22:51:47 +02:00
continue ;
}
2023-01-21 01:31:34 +01:00
// Count renderings
$render_count ++ ;
2023-02-17 11:55:55 +01:00
// Apply offset if limited to group (not working in query for 'posts_per_page' => -1)
2023-08-22 22:51:47 +02:00
if ( $group && $offset > 0 && $render_count <= $offset ) {
continue ;
}
2023-01-21 01:31:34 +01:00
// Apply count if limited to group
2023-08-22 22:51:47 +02:00
if ( $group && $count > 0 && $render_count > $count ) {
break ;
}
2023-01-21 01:31:34 +01:00
// Data
2023-11-30 16:03:53 +01:00
$warning = get_post_meta ( $chapter_id , 'fictioneer_chapter_warning' , true );
$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 );
2024-03-01 12:39:42 +01:00
$title = fictioneer_get_safe_title ( $chapter_id , 'shortcode-chapter-list' );
2024-03-01 11:37:03 +01:00
$has_password = ! empty ( $post -> post_password );
2024-03-05 19:42:08 +01:00
$extra_classes = '_shortcode' ;
if ( $warning ) {
$extra_classes .= ' _warning' ;
}
if ( $has_password ) {
$extra_classes .= ' _password' ;
}
2023-02-17 11:55:55 +01:00
// Start HTML ---> ?>
2024-03-05 19:42:08 +01:00
< li class = " chapter-group__list-item <?php echo $extra_classes ; ?> " data - post - id = " <?php echo $chapter_id ; ?> " >
2024-05-23 20:16:39 +02:00
< ? php
if ( ! $hide_icons ) {
2024-06-20 16:03:27 +02:00
// Icon hierarchy: password > scheduled > text > normal
2024-06-29 13:37:55 +02:00
if ( ! $prefer_chapter_icon && $has_password ) {
2024-06-20 14:59:57 +02:00
$icon = '<i class="fa-solid fa-lock chapter-group__list-item-icon"></i>' ;
2024-06-29 13:37:55 +02:00
} elseif ( ! $prefer_chapter_icon && get_post_status ( $chapter_id ) === 'future' ) {
2024-06-20 16:03:27 +02:00
$icon = '<i class="fa-solid fa-calendar-days chapter-group__list-item-icon"></i>' ;
2024-06-20 14:59:57 +02:00
} elseif ( $text_icon ) {
2024-05-23 20:16:39 +02:00
$icon = " <span class='chapter-group__list-item-icon _text text-icon'> { $text_icon } </span> " ;
} else {
2024-05-23 20:30:08 +02:00
$icon = $icon ? : FICTIONEER_DEFAULT_CHAPTER_ICON ;
2024-05-23 20:16:39 +02:00
$icon = " <i class=' { $icon } chapter-group__list-item-icon'></i> " ;
}
echo apply_filters ( 'fictioneer_filter_chapter_icon' , $icon , $chapter_id , $story_id );
}
?>
2023-01-21 01:31:34 +01:00
2024-03-01 11:37:03 +01:00
< a
href = " <?php the_permalink( $chapter_id ); ?> "
class = " chapter-group__list-item-link truncate _1-1 <?php echo $has_password ? '_password' : ''; ?> "
>< ? php
2025-01-03 18:45:14 +01:00
$title_output = '' ;
$prefix = apply_filters ( 'fictioneer_filter_list_chapter_prefix' , $prefix , $chapter_id , 'shortcode' );
2024-03-01 11:37:03 +01:00
if ( ! empty ( $prefix ) ) {
// Mind space between prefix and title
2025-01-03 18:45:14 +01:00
$title_output .= $prefix . ' ' ;
2024-03-01 11:37:03 +01:00
}
2025-01-03 18:45:14 +01:00
$title_output .= $title ;
echo apply_filters (
'fictioneer_filter_list_chapter_title_row' ,
$title_output , $chapter_id , $prefix , $has_password , 'shortcode'
);
2024-03-01 11:37:03 +01:00
?> </a>
2023-01-21 01:31:34 +01:00
2023-02-26 17:14:56 +01:00
< ? php
// Chapter subrow
2024-06-20 16:02:31 +02:00
echo fictioneer_get_list_chapter_meta_row (
array (
'id' => $chapter_id ,
'warning' => $warning ,
'password' => $has_password ,
'timestamp' => get_the_time ( 'c' ),
'list_date' => get_the_date ( '' ),
'words' => fictioneer_get_word_count ( $chapter_id ),
)
);
2023-02-26 17:14:56 +01:00
?>
2023-01-21 01:31:34 +01:00
< ? php if ( $can_checkmarks && ! empty ( $chapter_story_id ) && get_post_status ( $chapter_story_id ) === 'publish' ) : ?>
2023-06-05 11:49:01 +02:00
< button
2024-12-06 17:38:32 +01:00
class = " checkmark chapter-group__list-item-checkmark only-logged-in "
data - fictioneer - checkmarks - target = " chapterCheck "
data - fictioneer - checkmarks - story - param = " <?php echo $chapter_story_id ; ?> "
data - fictioneer - checkmarks - chapter - param = " <?php echo $chapter_id ; ?> "
data - action = " click->fictioneer-checkmarks#toggleChapter "
2023-06-05 11:49:01 +02:00
role = " checkbox "
aria - checked = " false "
2024-12-02 15:54:59 +01:00
aria - label = " <?php
printf (
esc_attr__ ( 'Chapter checkmark for %s.' , 'fictioneer' ),
esc_attr ( wp_strip_all_tags ( $title ) )
);
?> "
2023-06-05 11:49:01 +02:00
>< i class = " fa-solid fa-check " ></ i ></ button >
2023-01-21 01:31:34 +01:00
< ? php endif ; ?>
</ li >
2023-02-17 11:55:55 +01:00
< ? php // <--- End HTML
2023-01-21 01:31:34 +01:00
}
// Restore postdata
wp_reset_postdata ();
?>
</ ol >
</ div >
< ? php // <--- End HTML
2023-08-06 04:57:12 +02:00
// Store buffer
$html = fictioneer_minify_html ( ob_get_clean () );
2024-10-13 14:15:20 +02:00
if ( $transient_enabled && $cache ) {
2023-08-06 04:57:12 +02:00
set_transient ( $transient_key , $html , FICTIONEER_SHORTCODE_TRANSIENT_EXPIRATION );
}
2023-06-10 18:23:04 +02:00
2023-08-06 04:57:12 +02:00
// Return minified buffer
return $html ;
2023-01-21 01:31:34 +01:00
}
add_shortcode ( 'fictioneer_chapter_list' , 'fictioneer_shortcode_chapter_list' );
// =============================================================================
// CONTACT FORM SHORTCODE
// =============================================================================
/**
* Shortcode to show a contact form
*
2024-01-26 17:45:59 +01:00
* @ since 5.0 . 0
2023-01-21 01:31:34 +01:00
*
2023-08-09 10:19:20 +02:00
* @ param string | null $attr [ 'title' ] Optional . Title of the form .
* @ param string | null $attr [ 'submit' ] Optional . Submit button caption .
* @ param string | null $attr [ 'privacy_policy' ] Optional . Must accept privacy policy .
* @ param string | null $attr [ 'required' ] Optional . Make all fields required
* @ param string | null $attr [ 'email' ] Optional . Email field .
* @ param string | null $attr [ 'name' ] Optional . Name field .
* @ param string | null $attr [ " text_ { $i } " ] Optional . Up to 6 extra text field ( s ) .
* @ param string | null $attr [ " check_ { $i } " ] Optional . Up to 6 extra checkbox field ( s ) .
* @ param string | null $attr [ 'class' ] Optional . Additional CSS classes , separated by whitespace .
2023-01-21 01:31:34 +01:00
*
2024-01-29 14:52:56 +01:00
* @ return string The captured shortcode HTML .
2023-01-21 01:31:34 +01:00
*/
function fictioneer_shortcode_contact_form ( $attr ) {
2023-09-16 02:20:07 +02:00
// Sanitize attributes
$attr = is_array ( $attr ) ? array_map ( 'sanitize_text_field' , $attr ) : sanitize_text_field ( $attr );
2023-01-21 01:31:34 +01:00
// Setup
$title = $attr [ 'title' ] ? ? _x ( 'Nameless Form' , 'Contact form.' , 'fictioneer' );
$submit = $attr [ 'submit' ] ? ? __ ( 'Submit' , 'fictioneer' );
$privacy_policy = filter_var ( $attr [ 'privacy_policy' ] ? ? 0 , FILTER_VALIDATE_BOOLEAN );
$required = isset ( $attr [ 'required' ] ) ? 'required' : '' ;
$email = $attr [ 'email' ] ? ? '' ;
$name = $attr [ 'name' ] ? ? '' ;
2024-04-18 12:27:14 +02:00
$classes = wp_strip_all_tags ( $attr [ 'class' ] ? ? '' );
2023-01-21 01:31:34 +01:00
$fields = [];
// HTML snippets
if ( ! empty ( $email ) ) {
2023-12-01 03:00:41 +01:00
$fields [] = " <input style='opacity: 0;' type='email' name='email' maxlength='100' placeholder=' { $email } ' { $required } > " ;
2023-01-21 01:31:34 +01:00
}
if ( ! empty ( $name ) ) {
2023-12-01 03:00:41 +01:00
$fields [] = " <input style='opacity: 0;' type='text' name='name' maxlength='100' placeholder=' { $name } ' { $required } > " ;
2023-01-21 01:31:34 +01:00
}
// Custom text fields
for ( $i = 1 ; $i <= 6 ; $i ++ ) {
2023-12-01 03:00:41 +01:00
$field = $attr [ " text_ { $i } " ] ? ? '' ;
2023-01-21 01:31:34 +01:00
if ( ! empty ( $field ) ) {
2023-12-01 03:00:41 +01:00
$fields [] = " <input style='opacity: 0;' type='text' name='text_ { $i } ' maxlength='100' placeholder=' { $field } ' { $required } ><input type='hidden' name='text_label_ { $i } ' value=' { $field } '> " ;
2023-01-21 01:31:34 +01:00
}
}
// Custom checkboxes
for ( $i = 1 ; $i <= 6 ; $i ++ ) {
2023-12-01 03:00:41 +01:00
$field = $attr [ " check_ { $i } " ] ? ? '' ;
2023-01-21 01:31:34 +01:00
if ( ! empty ( $field ) ) {
2023-12-01 03:00:41 +01:00
$fields [] = " <label class='checkbox-label'><input class='_no-stretch' style='opacity: 0;' type='checkbox' value='1' name='check_ { $i } ' autocomplete='off' { $required } ><span> { $field } </span></label><input type='hidden' name='check_label_ { $i } ' value=' { $field } '> " ;
2023-01-21 01:31:34 +01:00
}
}
// Privacy policy checkbox
$privacy_policy_link = get_option ( 'wp_page_for_privacy_policy' ) ? esc_url ( get_privacy_policy_url () ) : false ;
if ( $privacy_policy && $privacy_policy_link ) {
$fields [] = " <label class='checkbox-label'><input class='_no-stretch' style='opacity: 0;' type='checkbox' value='1' name='privacy_policy' autocomplete='off' required><span> " . sprintf ( fcntr ( 'accept_privacy_policy' ), $privacy_policy_link ) . " </span></label><input type='hidden' name='require_privacy_policy' value='1'> " ;
}
// Apply filters
$fields = apply_filters ( 'fictioneer_filter_contact_form_fields' , $fields , get_the_ID () );
// Buffer
ob_start ();
/*
* The inline " opacity: 0 " style is a reverse bot trap . They are made visible again with CSS ,
* but dumb bots might think this is a trap for them and ignore the fields . Not a reliable
* spam protection , but this is security in depth .
*
* The " phone " and " terms " inputs are honeypots .
*/
// Start HTML ---> ?>
2024-04-18 12:27:14 +02:00
< form class = " fcn-contact-form <?php echo esc_attr( $classes ); ?> " >
2023-03-07 23:22:38 +01:00
< div class = " fcn-contact-form__message " >
< textarea class = " fcn-contact-form__textarea adaptive-textarea " style = " opacity: 0; " name = " message " maxlength = " 65525 " placeholder = " <?php _e( 'Please enter your message.', 'fictioneer' ); ?> " required ></ textarea >
2023-01-21 01:31:34 +01:00
</ div >
< ? php if ( ! empty ( $fields ) ) : ?>
2023-03-07 23:22:38 +01:00
< div class = " fcn-contact-form__fields " >
2024-06-17 22:12:39 +02:00
< ? php foreach ( $fields as $field ) : ?>
2023-03-07 23:22:38 +01:00
< div class = " fcn-contact-form__field " >< ? php echo $field ; ?> </div>
2023-01-21 01:31:34 +01:00
< ? php endforeach ; ?>
</ div >
< ? php endif ; ?>
< input type = " checkbox " name = " terms " value = " 1 " autocomplete = " off " tabindex = " -1 " >
< input type = " tel " name = " phone " autocomplete = " off " tabindex = " -1 " >
< input type = " hidden " name = " title " value = " <?php echo $title ; ?> " >
2023-03-07 23:22:38 +01:00
< div class = " fcn-contact-form__actions " >
< button class = " fcn-contact-form__submit button " type = " button " data - enabled = " <?php echo esc_attr( $submit ); ?> " data - disabled = " <?php esc_attr_e( 'Sending…', 'fictioneer' ); ?> " data - done = " <?php esc_attr_e( 'Message sent!', 'fictioneer' ); ?> " >< ? php echo $submit ; ?> </button>
2023-01-21 01:31:34 +01:00
</ div >
</ form >
< ? php // <--- End HTML
2023-06-10 18:43:58 +02:00
// Return minified buffer
return fictioneer_minify_html ( ob_get_clean () );
2023-01-21 01:31:34 +01:00
}
add_shortcode ( 'fictioneer_contact_form' , 'fictioneer_shortcode_contact_form' );
// =============================================================================
// SEARCH SHORTCODE
// =============================================================================
/**
* Shortcode to show the latest post
*
2024-01-26 17:45:59 +01:00
* @ since 5.0 . 0
2023-01-21 01:31:34 +01:00
*
2023-08-09 10:19:20 +02:00
* @ param string | null $attr [ 'simple' ] Optional . Hide the advanced options .
* @ param string | null $attr [ 'placeholder' ] Optional . Placeholder text .
* @ param string | null $attr [ 'type' ] Optional . Default post type to query .
2023-01-21 01:31:34 +01:00
*
2024-01-29 14:52:56 +01:00
* @ return string The captured shortcode HTML .
2023-01-21 01:31:34 +01:00
*/
function fictioneer_shortcode_search ( $attr ) {
2023-09-16 02:20:07 +02:00
// Sanitize attributes
$attr = is_array ( $attr ) ? array_map ( 'sanitize_text_field' , $attr ) : sanitize_text_field ( $attr );
2023-01-21 01:31:34 +01:00
// Setup
2023-07-28 11:25:52 +02:00
$args = array ( 'cache' => true );
2023-01-21 01:31:34 +01:00
$simple = isset ( $attr [ 'simple' ] ) ? $attr [ 'simple' ] == 'true' || $attr [ 'simple' ] == '1' : false ;
$placeholder = $attr [ 'placeholder' ] ? ? false ;
2023-07-28 11:25:52 +02:00
$type = $attr [ 'type' ] ? ? false ;
2024-05-24 14:21:50 +02:00
$pre_tags = fictioneer_explode_list ( $attr [ 'tags' ] ? ? '' );
$pre_genres = fictioneer_explode_list ( $attr [ 'genres' ] ? ? '' );
$pre_fandoms = fictioneer_explode_list ( $attr [ 'fandoms' ] ? ? '' );
$pre_characters = fictioneer_explode_list ( $attr [ 'characters' ] ? ? '' );
$pre_warnings = fictioneer_explode_list ( $attr [ 'warnings' ] ? ? '' );
2023-01-21 01:31:34 +01:00
// Prepare arguments
2024-08-28 14:28:56 +02:00
$args [ 'expanded' ] = filter_var ( $attr [ 'expanded' ] ? ? 0 , FILTER_VALIDATE_BOOLEAN );
2023-08-09 10:19:20 +02:00
if ( $simple ) {
$args [ 'simple' ] = $simple ;
}
2023-07-28 11:25:52 +02:00
2023-08-09 10:19:20 +02:00
if ( $placeholder ) {
$args [ 'placeholder' ] = $placeholder ;
}
2023-01-21 01:31:34 +01:00
2023-07-28 11:25:52 +02:00
if ( $type && in_array ( $type , [ 'any' , 'story' , 'chapter' , 'recommendation' , 'collection' , 'post' ] ) ) {
2023-12-01 03:00:41 +01:00
$args [ 'preselect_type' ] = in_array ( $type , [ 'story' , 'chapter' , 'recommendation' , 'collection' ] ) ? " fcn_ { $type } " : $type ;
2023-07-28 11:25:52 +02:00
}
2024-05-24 14:21:50 +02:00
if ( $pre_tags ) {
$args [ 'preselect_tags' ] = array_map ( 'absint' , $pre_tags );
}
if ( $pre_genres ) {
$args [ 'preselect_genres' ] = array_map ( 'absint' , $pre_genres );
}
if ( $pre_fandoms ) {
$args [ 'preselect_fandoms' ] = array_map ( 'absint' , $pre_fandoms );
}
if ( $pre_characters ) {
$args [ 'preselect_characters' ] = array_map ( 'absint' , $pre_characters );
}
if ( $pre_warnings ) {
$args [ 'preselect_warnings' ] = array_map ( 'absint' , $pre_warnings );
}
2023-01-21 01:31:34 +01:00
// Buffer
ob_start ();
get_search_form ( $args );
2023-06-10 18:43:58 +02:00
// Return minified buffer
return fictioneer_minify_html ( ob_get_clean () );
2023-01-21 01:31:34 +01:00
}
add_shortcode ( 'fictioneer_search' , 'fictioneer_shortcode_search' );
2023-03-10 15:35:55 +01:00
// =============================================================================
// BLOG SHORTCODE
// =============================================================================
/**
* Shortcode to show blog with pagination
*
* @ since 5.2 . 0
*
2023-07-29 13:06:37 +02:00
* @ param string | null $attr [ 'per_page' ] Optional . Number of posts per page .
2023-09-13 20:57:37 +02:00
* @ param string | null $attr [ 'ignore_sticky' ] Optional . Whether to ignore sticky posts . Default false .
2023-09-15 14:25:43 +02:00
* @ param string | null $attr [ 'ignore_protected' ] Optional . Whether to ignore protected posts . Default false .
2024-09-20 23:41:37 +02:00
* @ param string | null $attr [ 'only_protected' ] Optional . Whether to query only protected posts . Default false .
2023-09-15 22:42:34 +02:00
* @ param string | null $attr [ 'author' ] Optional . Limit posts to a specific author .
2023-07-29 13:06:37 +02:00
* @ param string | null $attr [ 'author_ids' ] Optional . Only include posts by these author IDs .
* @ param string | null $attr [ 'exclude_author_ids' ] Optional . Exclude posts with these author IDs .
* @ param string | null $attr [ 'exclude_tag_ids' ] Optional . Exclude posts with these tags .
* @ param string | null $attr [ 'exclude_cat_ids' ] Optional . Exclude posts with these categories .
2023-09-15 22:42:34 +02:00
* @ param string | null $attr [ 'categories' ] Optional . Limit posts to specific category names .
* @ param string | null $attr [ 'tags' ] Optional . Limit posts to specific tag names .
2023-07-29 13:06:37 +02:00
* @ param string | null $attr [ 'rel' ] Optional . Relationship between taxonomies . Default 'AND' .
* @ param string | null $attr [ 'class' ] Optional . Additional CSS classes , separated by whitespace .
2023-03-10 15:35:55 +01:00
*
2024-01-29 14:52:56 +01:00
* @ return string The captured shortcode HTML .
2023-03-10 15:35:55 +01:00
*/
function fictioneer_shortcode_blog ( $attr ) {
2023-09-16 22:59:43 +02:00
// Defaults
$args = fictioneer_get_default_shortcode_args ( $attr );
2023-03-10 15:53:34 +01:00
2023-09-16 01:40:06 +02:00
// Query arguments
2023-03-10 15:35:55 +01:00
$query_args = array (
2023-09-16 13:54:50 +02:00
'fictioneer_query_name' => 'blog_shortcode' ,
2023-03-10 15:35:55 +01:00
'post_type' => 'post' ,
'post_status' => 'publish' ,
2023-09-16 01:40:06 +02:00
'paged' => $args [ 'page' ],
'posts_per_page' => $args [ 'posts_per_page' ],
'ignore_sticky_posts' => $args [ 'ignore_sticky' ]
2023-03-10 15:35:55 +01:00
);
// Author?
2023-09-16 01:40:06 +02:00
if ( ! empty ( $args [ 'author' ] ) ) {
$query_args [ 'author_name' ] = $args [ 'author' ];
2023-08-22 22:51:47 +02:00
}
2023-03-10 15:35:55 +01:00
2023-07-29 13:06:37 +02:00
// Author IDs?
2023-09-16 01:40:06 +02:00
if ( ! empty ( $args [ 'author_ids' ] ) ) {
$query_args [ 'author__in' ] = $args [ 'author_ids' ];
2023-08-22 22:51:47 +02:00
}
2023-07-29 13:06:37 +02:00
2023-03-10 15:35:55 +01:00
// Taxonomies?
2023-09-16 01:40:06 +02:00
if ( ! empty ( $args [ 'taxonomies' ] ) ) {
$query_args [ 'tax_query' ] = fictioneer_get_shortcode_tax_query ( $args );
2023-03-10 15:35:55 +01:00
}
// Excluded tags?
2023-09-16 01:40:06 +02:00
if ( ! empty ( $args [ 'excluded_tags' ] ) ) {
$query_args [ 'tag__not_in' ] = $args [ 'excluded_tags' ];
2023-08-22 22:51:47 +02:00
}
2023-03-10 15:35:55 +01:00
// Excluded categories?
2023-09-16 01:40:06 +02:00
if ( ! empty ( $args [ 'excluded_cats' ] ) ) {
$query_args [ 'category__not_in' ] = $args [ 'excluded_cats' ];
2023-08-22 22:51:47 +02:00
}
2023-03-10 15:35:55 +01:00
2023-07-29 13:06:37 +02:00
// Excluded authors?
2023-09-16 01:40:06 +02:00
if ( ! empty ( $args [ 'excluded_authors' ] ) ) {
$query_args [ 'author__not_in' ] = $args [ 'excluded_authors' ];
2023-08-22 22:51:47 +02:00
}
2023-07-29 13:06:37 +02:00
2023-09-13 20:57:37 +02:00
// Exclude protected
2023-09-16 01:40:06 +02:00
if ( $args [ 'ignore_protected' ] ) {
2024-09-20 23:32:29 +02:00
$query_args [ 'has_password' ] = false ;
2023-09-13 20:57:37 +02:00
}
2023-03-10 15:35:55 +01:00
// Apply filters
2023-09-16 01:40:06 +02:00
$query_args = apply_filters ( 'fictioneer_filter_shortcode_blog_query_args' , $query_args , $args );
2023-03-10 15:35:55 +01:00
2023-08-06 04:57:12 +02:00
// Transient?
2024-10-13 14:15:20 +02:00
$transient_enabled = fictioneer_enable_shortcode_transients ( 'fictioneer_blog' );
if ( $transient_enabled && $args [ 'cache' ] ) {
2023-09-16 02:20:07 +02:00
$base = serialize ( $query_args ) . serialize ( $args ) . serialize ( $attr );
2024-08-17 15:38:55 +02:00
$transient_key = 'fictioneer_shortcode_blog_html_' . md5 ( $base );
2023-08-06 04:57:12 +02:00
$transient = get_transient ( $transient_key );
if ( ! empty ( $transient ) ) {
return $transient ;
}
}
2023-03-10 15:35:55 +01:00
// Query
$blog_query = new WP_Query ( $query_args );
2023-08-05 18:46:40 +02:00
// Prime author cache
if ( function_exists ( 'update_post_author_caches' ) ) {
update_post_author_caches ( $blog_query -> posts );
}
2023-09-16 01:40:06 +02:00
// Pagination
$pag_args = array (
'current' => $args [ 'page' ],
'total' => $blog_query -> max_num_pages ,
'prev_text' => fcntr ( 'previous' ),
'next_text' => fcntr ( 'next' ),
'add_fragment' => '#blog'
);
2023-03-10 15:35:55 +01:00
// Buffer
ob_start ();
if ( $blog_query -> have_posts () ) {
// Start HTML ---> ?>
2023-09-16 02:52:18 +02:00
< section id = " blog " class = " scroll-margin-top blog-posts _nested <?php echo $args['classes'] ; ?> " >
2023-03-10 17:47:23 +01:00
< ? php
while ( $blog_query -> have_posts () ) {
$blog_query -> the_post ();
2024-10-14 11:36:10 +02:00
get_template_part ( 'partials/_post' , null , array ( 'nested' => true , 'context' => 'shortcode_fictioneer_blog' ) );
2023-03-10 17:47:23 +01:00
}
2023-09-16 01:40:06 +02:00
2023-03-10 17:47:23 +01:00
wp_reset_postdata ();
2023-09-16 01:40:06 +02:00
if ( $blog_query -> max_num_pages > 1 ) {
echo '<nav class="pagination">' . fictioneer_paginate_links ( $pag_args ) . '</nav>' ;
}
2023-03-10 17:47:23 +01:00
?>
</ section >
2023-03-10 15:35:55 +01:00
< ? php // <--- End HTML
} else {
// Start HTML ---> ?>
< article class = " post _empty " >
2023-09-11 12:26:34 +02:00
< span >< ? php _e ( 'No (more) posts found.' , 'fictioneer' ); ?> </span>
2023-03-10 15:35:55 +01:00
</ article >
< ? php // <--- End HTML
}
2023-08-06 04:57:12 +02:00
// Store buffer
$html = fictioneer_minify_html ( ob_get_clean () );
2024-10-13 14:15:20 +02:00
if ( $transient_enabled && $args [ 'cache' ] ) {
2023-08-06 04:57:12 +02:00
set_transient ( $transient_key , $html , FICTIONEER_SHORTCODE_TRANSIENT_EXPIRATION );
}
2023-06-10 18:43:58 +02:00
// Return minified buffer
2023-08-06 04:57:12 +02:00
return $html ;
2023-03-10 15:35:55 +01:00
}
add_shortcode ( 'fictioneer_blog' , 'fictioneer_shortcode_blog' );
2023-09-15 22:19:25 +02:00
// =============================================================================
// ARTICLE CARDS SHORTCODE
// =============================================================================
/**
* Shortcode to show article cards with pagination
*
* @ since 5.7 . 3
*
* @ param string | null $attr [ 'post_type' ] Optional . The post types to query . Default 'post' .
2023-09-16 17:41:02 +02:00
* @ param string | null $attr [ 'post_ids' ] Optional . Limit posts to specific post IDs .
2023-09-15 22:19:25 +02:00
* @ param string | null $attr [ 'per_page' ] Optional . Number of posts per page .
* @ param string | null $attr [ 'count' ] Optional . Maximum number of posts . Default - 1.
* @ param string | null $attr [ 'order' ] Optional . Order argument . Default 'DESC' .
* @ param string | null $attr [ 'orderby' ] Optional . Orderby argument . Default 'date' .
* @ param string | null $attr [ 'ignore_sticky' ] Optional . Whether to ignore sticky posts . Default false .
* @ param string | null $attr [ 'ignore_protected' ] Optional . Whether to ignore protected posts . Default false .
2024-09-20 23:41:37 +02:00
* @ param string | null $attr [ 'only_protected' ] Optional . Whether to query only protected posts . Default false .
2023-09-15 22:19:25 +02:00
* @ param string | null $attr [ 'author' ] Optional . Limit posts to a specific author .
* @ param string | null $attr [ 'author_ids' ] Optional . Only include posts by these author IDs .
* @ param string | null $attr [ 'exclude_author_ids' ] Optional . Exclude posts with these author IDs .
* @ param string | null $attr [ 'exclude_tag_ids' ] Optional . Exclude posts with these tags .
* @ param string | null $attr [ 'exclude_cat_ids' ] Optional . Exclude posts with these categories .
* @ param string | null $attr [ 'categories' ] Optional . Limit posts to specific category names .
* @ param string | null $attr [ 'tags' ] Optional . Limit posts to specific tag names .
* @ param string | null $attr [ 'fandoms' ] Optional . Limit posts to specific fandom names .
* @ param string | null $attr [ 'genres' ] Optional . Limit posts to specific genre names .
* @ param string | null $attr [ 'characters' ] Optional . Limit posts to specific character names .
* @ param string | null $attr [ 'rel' ] Optional . Relationship between taxonomies . Default 'AND' .
2024-05-15 09:49:51 +02:00
* @ param string | null $attr [ 'seamless' ] Optional . Whether to render the image seamless . Default false ( Customizer ) .
2024-04-25 14:18:57 +02:00
* @ param string | null $attr [ 'aspect_ratio' ] Optional . Aspect ratio for the image .
* @ param string | null $attr [ 'lightbox' ] Optional . Whether the thumbnail is opened in the lightbox . Default true .
2024-05-15 09:49:51 +02:00
* @ param string | null $attr [ 'thumbnail' ] Optional . Whether to show the thumbnail . Default true ( Customizer ) .
2024-08-21 22:53:24 +02:00
* @ param string | null $attr [ 'date_format' ] Optional . String to override the date format . Default empty .
* @ param string | null $attr [ 'footer' ] Optional . Whether to show the footer ( if any ) . Default true .
* @ param string | null $attr [ 'footer_author' ] Optional . Whether to show the post author . Default true .
* @ param string | null $attr [ 'footer_date' ] Optional . Whether to show the post date . Default true .
* @ param string | null $attr [ 'footer_comments' ] Optional . Whether to show the post comment count . Default true .
2023-09-15 22:19:25 +02:00
* @ param string | null $attr [ 'class' ] Optional . Additional CSS classes , separated by whitespace .
2024-09-06 01:26:42 +02:00
* @ param string | null $args [ 'splide' ] Configuration JSON for the Splide slider . Default empty .
2023-09-15 22:19:25 +02:00
*
2024-01-29 14:52:56 +01:00
* @ return string The captured shortcode HTML .
2023-09-15 22:19:25 +02:00
*/
function fictioneer_shortcode_article_cards ( $attr ) {
2023-09-16 22:59:43 +02:00
// Defaults
$args = fictioneer_get_default_shortcode_args ( $attr );
2023-09-16 02:20:07 +02:00
2024-08-23 23:12:24 +02:00
// Terms
$args [ 'terms' ] = fictioneer_sanitize_query_var ( $attr [ 'terms' ] ? ? 0 , [ 'inline' , 'pills' , 'none' , 'false' ], 'inline' );
$args [ 'max_terms' ] = absint ( ( $attr [ 'max_terms' ] ? ? 10 ) ? : 10 );
2023-09-16 22:59:43 +02:00
// Post type(s)...
$post_types = sanitize_text_field ( $attr [ 'post_type' ] ? ? 'post' );
$post_types = fictioneer_explode_list ( $post_types );
2023-09-15 22:19:25 +02:00
$allowed_post_types = array (
'post' => 'post' ,
'posts' => 'post' ,
'page' => 'page' ,
'pages' => 'page' ,
'story' => 'fcn_story' ,
'stories' => 'fcn_story' ,
'chapter' => 'fcn_chapter' ,
'chapters' => 'fcn_chapter' ,
'collection' => 'fcn_collection' ,
'collections' => 'fcn_collection' ,
'recommendation' => 'fcn_recommendation' ,
'recommendations' => 'fcn_recommendation'
);
2023-09-15 23:03:47 +02:00
// ... must be in array
$query_post_types = array_map ( function ( $item ) use ( $allowed_post_types ) {
return $allowed_post_types [ $item ] ? ? null ;
}, $post_types );
// ... remove null values
$query_post_types = array_filter ( $query_post_types , function ( $value ) {
return ! is_null ( $value );
});
// ... fix array
$query_post_types = array_unique ( $query_post_types );
$query_post_types = array_values ( $query_post_types );
$query_post_types = empty ( $query_post_types ) ? [ 'post' ] : $query_post_types ;
2023-09-15 22:19:25 +02:00
2023-09-16 22:59:43 +02:00
// ... add to args
$args [ 'post_type' ] = $query_post_types ;
2023-09-16 21:44:12 +02:00
2024-09-06 01:26:42 +02:00
// Extra classes
if ( $args [ 'splide' ] ? ? 0 ) {
2024-10-06 23:53:02 +02:00
$args [ 'classes' ] .= ' splide _splide-placeholder' ;
2024-09-06 01:26:42 +02:00
}
2023-09-15 22:19:25 +02:00
// Transient?
2024-10-13 14:15:20 +02:00
$transient_enabled = fictioneer_enable_shortcode_transients ( 'fictioneer_article_cards' );
if ( $transient_enabled && $args [ 'cache' ] ) {
2023-09-16 02:20:07 +02:00
$base = serialize ( $args ) . serialize ( $attr );
2023-09-15 22:19:25 +02:00
$transient_key = " fictioneer_shortcode_article_cards_html_ " . md5 ( $base );
$transient = get_transient ( $transient_key );
if ( ! empty ( $transient ) ) {
return $transient ;
}
}
// Buffer
ob_start ();
get_template_part ( 'partials/_article-cards' , null , $args );
$html = fictioneer_minify_html ( ob_get_clean () );
2024-09-06 01:26:42 +02:00
if ( ( $args [ 'splide' ] ? ? 0 ) && strpos ( $args [ 'classes' ], 'no-auto-splide' ) === false ) {
2024-10-09 19:30:37 +02:00
$html .= fictioneer_get_splide_inline_init ();
2024-09-06 01:26:42 +02:00
}
2024-10-13 14:15:20 +02:00
if ( $transient_enabled && $args [ 'cache' ] ) {
2023-09-15 22:19:25 +02:00
set_transient ( $transient_key , $html , FICTIONEER_SHORTCODE_TRANSIENT_EXPIRATION );
}
// Return minified buffer
return $html ;
}
add_shortcode ( 'fictioneer_article_cards' , 'fictioneer_shortcode_article_cards' );
2024-04-14 12:48:06 +02:00
// =============================================================================
// STORY SECTION SHORTCODE
// =============================================================================
/**
* Shortcode to show story section
*
* @ since 5.14 . 0
*
2024-04-15 01:51:41 +02:00
* @ param string $attr [ 'story_id' ] The ID of the story .
2024-04-14 12:48:06 +02:00
* @ param string | null $attr [ 'tabs' ] Optional . Whether to show the tabs above chapters . Default false .
* @ param string | null $attr [ 'blog' ] Optional . Whether to show the blog tab . Default false .
* @ param string | null $attr [ 'pages' ] Optional . Whether to show the custom page tabs . Default false .
* @ param string | null $attr [ 'scheduled' ] Optional . Whether to show the scheduled chapter note . Default false .
* @ param string | null $attr [ 'class' ] Optional . Additional CSS classes , separated by whitespace .
*
* @ return string The captured shortcode HTML .
*/
function fictioneer_shortcode_story_section ( $attr ) {
2024-04-15 01:51:41 +02:00
global $post ;
2024-04-18 21:33:18 +02:00
// Abort if...
if ( ! is_page_template ( 'singular-story.php' ) ) {
return fictioneer_notice (
__ ( 'The [fictioneer_story_section] shortcode requires the "Story Page" template.' ),
'warning' ,
false
);
}
2024-04-14 12:48:06 +02:00
// Setup
2024-09-07 00:28:36 +02:00
$cache = filter_var ( $attr [ 'cache' ] ? ? 1 , FILTER_VALIDATE_BOOLEAN );
2024-04-18 21:33:18 +02:00
$story_id = fictioneer_validate_id ( $attr [ 'story_id' ] ? ? 0 , 'fcn_story' );
2024-04-15 01:51:41 +02:00
$post = get_post ( $story_id );
2024-04-14 12:48:06 +02:00
$story_data = fictioneer_get_story_data ( $story_id );
$classes = wp_strip_all_tags ( $attr [ 'class' ] ? ? '' );
$show_tabs = filter_var ( $attr [ 'tabs' ] ? ? 0 , FILTER_VALIDATE_BOOLEAN );
$show_pages = filter_var ( $attr [ 'pages' ] ? ? 0 , FILTER_VALIDATE_BOOLEAN );
$show_blog = filter_var ( $attr [ 'blog' ] ? ? 0 , FILTER_VALIDATE_BOOLEAN );
$show_scheduled = filter_var ( $attr [ 'scheduled' ] ? ? 0 , FILTER_VALIDATE_BOOLEAN );
2024-05-10 01:26:09 +02:00
$hook_args = array ( 'story_id' => $story_id , 'story_data' => $story_data , 'password_required' => post_password_required () );
2024-04-14 12:48:06 +02:00
// Abort if...
if ( ! $story_data ) {
2024-04-17 17:22:45 +02:00
return '' ;
2024-04-14 12:48:06 +02:00
}
// Prepare classes
if ( ! get_option ( 'fictioneer_enable_checkmarks' ) ) {
$classes .= ' _no-checkmarks' ;
}
if ( ! $show_pages || ! $show_tabs ) {
$classes .= ' _no-pages' ;
}
if ( ! $show_blog || ! $show_tabs ) {
$classes .= ' _no-blog' ;
}
// Transient?
2024-10-13 14:15:20 +02:00
$transient_enabled = fictioneer_enable_shortcode_transients ( 'fictioneer_story_section' );
if ( $transient_enabled && $cache ) {
2024-04-14 13:42:21 +02:00
$base = serialize ( $attr ) . $classes ;
$transient_key = " fictioneer_shortcode_story_section_html_ " . md5 ( $base );
$transient = get_transient ( $transient_key );
2024-04-14 12:48:06 +02:00
2024-04-14 13:42:21 +02:00
if ( ! empty ( $transient ) ) {
return $transient ;
}
}
2024-04-14 12:48:06 +02:00
2024-04-15 01:51:41 +02:00
// Require functions (necessary in post editor for some reason)
require_once __DIR__ . '/hooks/_story_hooks.php' ;
2024-04-14 12:48:06 +02:00
// Setup post data
2024-04-15 01:51:41 +02:00
setup_postdata ( $post );
2024-04-14 12:48:06 +02:00
// Buffer
ob_start ();
2024-04-18 12:27:49 +02:00
echo '<div class="story-section-shortcode story _shortcode ' . esc_attr ( $classes ) . '">' ;
2024-04-14 12:48:06 +02:00
if ( $show_tabs ) {
fictioneer_story_tabs ( $hook_args );
}
if ( $show_scheduled ) {
fictioneer_story_scheduled_chapter ( $hook_args );
}
if ( $show_tabs && $show_pages ) {
fictioneer_story_pages ( $hook_args );
}
fictioneer_story_chapters ( $hook_args );
if ( $show_tabs && $show_blog ) {
fictioneer_story_blog ( $hook_args );
}
echo '</div>' ;
// Store buffer
$html = fictioneer_minify_html ( ob_get_clean () );
// Reset post data
wp_reset_postdata ();
2024-04-14 13:42:21 +02:00
// Cache in Transient
2024-10-13 14:15:20 +02:00
if ( $transient_enabled && $cache ) {
2024-04-14 13:42:21 +02:00
set_transient ( $transient_key , $html , FICTIONEER_SHORTCODE_TRANSIENT_EXPIRATION );
}
2024-04-14 12:48:06 +02:00
// Return minified buffer
return $html ;
}
add_shortcode ( 'fictioneer_story_section' , 'fictioneer_shortcode_story_section' );
2024-04-15 01:52:01 +02:00
// =============================================================================
// STORY ACTIONS SHORTCODE
// =============================================================================
/**
* Shortcode to show story actions
*
* @ since 5.14 . 0
*
* @ param string $attr [ 'story_id' ] The ID of the story .
* @ param string | null $attr [ 'class' ] Optional . Additional CSS classes , separated by whitespace .
* @ param string | null $attr [ 'follow' ] Optional . Whether to show the Follow button if enabled . Default true .
* @ param string | null $attr [ 'reminder' ] Optional . Whether to show the Reminder button if enabled . Default true .
* @ param string | null $attr [ 'subscribe' ] Optional . Whether to show the Subscribe button if enabled . Default true .
* @ param string | null $attr [ 'download' ] Optional . Whether to show the Download button if enabled . Default true .
2024-04-15 02:21:43 +02:00
* @ param string | null $attr [ 'rss' ] Optional . Whether to show the RSS links if enabled . Default true .
* @ param string | null $attr [ 'share' ] Optional . Whether to show the Share buttons if enabled . Default true .
2024-04-15 01:52:01 +02:00
*
* @ return string The captured shortcode HTML .
*/
function fictioneer_shortcode_story_actions ( $attr ) {
2024-04-18 21:33:18 +02:00
// Abort if...
if ( ! is_page_template ( 'singular-story.php' ) ) {
return fictioneer_notice (
__ ( 'The [fictioneer_story_actions] shortcode requires the "Story Page" template.' ),
'warning' ,
false
);
}
2024-04-15 01:52:01 +02:00
// Setup
2024-09-07 00:28:36 +02:00
$cache = filter_var ( $attr [ 'cache' ] ? ? 1 , FILTER_VALIDATE_BOOLEAN );
2024-04-18 21:33:18 +02:00
$story_id = fictioneer_validate_id ( $attr [ 'story_id' ] ? ? 0 , 'fcn_story' );
2024-04-15 01:52:01 +02:00
$story_data = fictioneer_get_story_data ( $story_id );
$classes = wp_strip_all_tags ( $attr [ 'class' ] ? ? '' );
$follow = filter_var ( $attr [ 'follow' ] ? ? 1 , FILTER_VALIDATE_BOOLEAN );
$reminder = filter_var ( $attr [ 'reminder' ] ? ? 1 , FILTER_VALIDATE_BOOLEAN );
$subscribe = filter_var ( $attr [ 'subscribe' ] ? ? 1 , FILTER_VALIDATE_BOOLEAN );
$download = filter_var ( $attr [ 'download' ] ? ? 1 , FILTER_VALIDATE_BOOLEAN );
2024-04-15 02:21:43 +02:00
$rss = filter_var ( $attr [ 'rss' ] ? ? 1 , FILTER_VALIDATE_BOOLEAN );
$share = filter_var ( $attr [ 'share' ] ? ? 1 , FILTER_VALIDATE_BOOLEAN );
2024-04-15 01:52:01 +02:00
2024-04-18 21:33:18 +02:00
// Abort if...
if ( ! $story_data ) {
return '' ;
}
// Prepare hook arguments
2024-04-15 01:52:01 +02:00
$hook_args = array (
2024-04-15 12:02:28 +02:00
'post_id' => $story_id ,
'post_type' => 'fcn_story' ,
2024-04-15 01:52:01 +02:00
'story_id' => $story_id ,
'story_data' => $story_data ,
'follow' => $follow ,
'reminder' => $reminder ,
'subscribe' => $subscribe ,
2024-04-15 02:21:43 +02:00
'download' => $download ,
'rss' => $rss ,
'share' => $share
2024-04-15 01:52:01 +02:00
);
// Transient?
2024-10-13 14:15:20 +02:00
$transient_enabled = fictioneer_enable_shortcode_transients ( 'fictioneer_story_actions' );
if ( $transient_enabled && $cache ) {
2024-04-15 01:52:01 +02:00
$base = serialize ( $attr ) . $classes ;
$transient_key = " fictioneer_shortcode_story_actions_html_ " . md5 ( $base );
$transient = get_transient ( $transient_key );
if ( ! empty ( $transient ) ) {
return $transient ;
}
}
2024-04-15 11:09:17 +02:00
// Add filter for buttons
add_filter ( 'fictioneer_filter_story_buttons' , 'fictioneer_shortcode_remove_story_buttons' , 99 , 2 );
2024-04-15 12:02:28 +02:00
// Build HTML
2024-04-18 12:27:49 +02:00
$html = '<section class="story-actions story__after-summary ' . esc_attr ( $classes ) . '">' ;
2024-04-15 12:02:28 +02:00
$html .= fictioneer_get_media_buttons ( $hook_args );
$html .= '<div class="story__actions">' . fictioneer_get_story_buttons ( $hook_args ) . '</div></section>' ;
2024-04-15 01:52:01 +02:00
2024-04-15 11:09:17 +02:00
// Remove filter for buttons
remove_filter ( 'fictioneer_shortcode_remove_story_buttons' , 99 , 2 );
2024-04-15 12:02:28 +02:00
// Minify HTML
$html = fictioneer_minify_html ( $html );
2024-04-15 01:52:01 +02:00
// Cache in Transient
2024-10-13 14:15:20 +02:00
if ( $transient_enabled && $cache ) {
2024-04-15 01:52:01 +02:00
set_transient ( $transient_key , $html , FICTIONEER_SHORTCODE_TRANSIENT_EXPIRATION );
}
2024-04-15 12:02:28 +02:00
// Return minified HTML
2024-04-15 01:52:01 +02:00
return $html ;
}
add_shortcode ( 'fictioneer_story_actions' , 'fictioneer_shortcode_story_actions' );
2024-04-15 11:09:17 +02:00
/**
* Removes buttons for the [ fictioneer_story_actions ] shortcode
*
* This function only works if boolean arguments are provided for
* 'follow' , 'reminder' , 'subscribe' , and / or 'download' .
*
* @ since 5.14 . 0
*
* @ param array $output Associative array with HTML for buttons to be rendered .
* @ param array $args Arguments passed to filter .
*
* @ return array The filtered output .
*/
function fictioneer_shortcode_remove_story_buttons ( $output , $args ) {
if ( ! ( $args [ 'follow' ] ? ? 1 ) ) {
unset ( $output [ 'follow' ] );
}
if ( ! ( $args [ 'reminder' ] ? ? 1 ) ) {
unset ( $output [ 'reminder' ] );
}
if ( ! ( $args [ 'subscribe' ] ? ? 1 ) ) {
unset ( $output [ 'subscribe' ] );
}
if ( ! ( $args [ 'download' ] ? ? 1 ) ) {
unset ( $output [ 'epub' ] );
unset ( $output [ 'ebook' ] );
}
return $output ;
};
2024-04-15 20:49:43 +02:00
// =============================================================================
2024-04-16 11:29:12 +02:00
// SUBSCRIBE BUTTON SHORTCODE
2024-04-15 20:49:43 +02:00
// =============================================================================
/**
* Shortcode to show subscribe button
*
* @ since 5.14 . 0
*
* @ param string | null $attr [ 'post_id' ] Optional . Post ID to subscribe to ( for plugins ) . Defaults to current ID .
* @ param string | null $attr [ 'story_id' ] Optional . Story ID to subscribe to ( for plugins ) . Defaults to current ID .
* @ param string | null $attr [ 'inline' ] Optional . Whether the button should be wrapped in a block . Default true .
* @ param string | null $attr [ 'class' ] Optional . Additional CSS classes , separated by whitespace .
*
* @ return string The captured shortcode HTML .
*/
function fictioneer_shortcode_subscribe_button ( $attr ) {
// Setup
$post_id = absint ( $attr [ 'post_id' ] ? ? $attr [ 'story_id' ] ? ? get_the_ID () );
$classes = wp_strip_all_tags ( $attr [ 'class' ] ? ? '' );
$subscribe_buttons = fictioneer_get_subscribe_options ( $post_id );
2024-04-16 13:51:11 +02:00
if ( filter_var ( $attr [ 'inline' ] ? ? 0 , FILTER_VALIDATE_BOOLEAN ) ) {
2024-04-15 20:49:43 +02:00
$classes .= ' _inline' ;
}
// Build and return button
if ( ! empty ( $subscribe_buttons ) ) {
return sprintf (
2024-12-06 17:38:32 +01:00
'<div class="subscribe-menu-toggle button _secondary popup-menu-toggle _popup-right-if-last ' . esc_attr ( $classes ) . '" tabindex="0" role="button" aria-label="%s" data-fictioneer-last-click-target="toggle" data-action="click->fictioneer-last-click#toggle"><div><i class="fa-solid fa-bell"></i> %s</div><div class="popup-menu _bottom _center">%s</div></div>' ,
2024-04-15 20:49:43 +02:00
fcntr ( 'subscribe' , true ),
fcntr ( 'subscribe' ),
$subscribe_buttons
);
}
// Return nothing if empty
return '' ;
}
add_shortcode ( 'fictioneer_subscribe_button' , 'fictioneer_shortcode_subscribe_button' );
2024-04-16 11:50:11 +02:00
// =============================================================================
// STORY COMMENTS SHORTCODE
// =============================================================================
/**
* Shortcode to show story comments
*
* @ since 5.14 . 0
*
* @ param string | null $attr [ 'story_id' ] Optional . Story ID to get comments for . Defaults to current ID .
* @ param string | null $attr [ 'header' ] Optional . Whether to show the heading with count . Default true .
* @ param string | null $attr [ 'class' ] Optional . Additional CSS classes , separated by whitespace .
*
* @ return string The captured shortcode HTML .
*/
function fictioneer_shortcode_story_comments ( $attr ) {
// Abort if...
if ( ! is_page_template ( 'singular-story.php' ) ) {
return fictioneer_notice (
2024-04-18 21:33:18 +02:00
__ ( 'The [fictioneer_story_comments] shortcode requires the "Story Page" template.' ),
2024-04-16 11:50:11 +02:00
'warning' ,
false
);
}
// Setup
$story_id = fictioneer_validate_id ( $attr [ 'story_id' ] ? ? get_the_ID (), 'fcn_story' );
$story_data = fictioneer_get_story_data ( $story_id ? : 0 );
$header = filter_var ( $attr [ 'header' ] ? ? 1 , FILTER_VALIDATE_BOOLEAN );
2024-08-18 22:08:43 +02:00
$classes = wp_strip_all_tags ( $attr [ 'classes' ] ? ? $attr [ 'class' ] ? ? '' );
2024-04-16 15:34:35 +02:00
$style = esc_attr ( wp_strip_all_tags ( $attr [ 'style' ] ? ? '' ) );
2024-04-16 11:50:11 +02:00
if ( ! $story_data ) {
return '' ;
}
// Require functions (necessary in post editor for some reason)
require_once __DIR__ . '/hooks/_story_hooks.php' ;
// Buffer
ob_start ();
// Output story comment section
fictioneer_story_comments (
array (
'story_id' => $story_id ,
'story_data' => $story_data ,
'shortcode' => 1 ,
'classes' => $classes ,
2024-04-16 15:34:35 +02:00
'header' => $header ,
'style' => $style
2024-04-16 11:50:11 +02:00
)
);
// Capture and return buffer
return fictioneer_minify_html ( ob_get_clean () );
}
add_shortcode ( 'fictioneer_story_comments' , 'fictioneer_shortcode_story_comments' );
2024-04-16 13:56:14 +02:00
// =============================================================================
// STORY DATA SHORTCODE
// =============================================================================
/**
* Shortcode to show selected story data
*
2024-04-16 14:12:06 +02:00
* Data : id , word_count , chapter_count , icon , age_rating , rating_letter , comment_count ,
* datetime , date , time , categories , tags , genres , fandoms , characters , or warnings .
*
* Format : default , raw , or short . Not all of them apply to all data .
*
2024-04-16 13:56:14 +02:00
* @ since 5.14 . 0
*
* @ param string | null $attr [ 'data' ] The requested data , one at a time . See description .
* @ param string | null $attr [ 'story_id' ] Optional . Story ID to get comments for . Defaults to current ID .
* @ param string | null $attr [ 'format' ] Optional . Special formatting for selected data . See description .
* @ param string | null $attr [ 'date_format' ] Optional . Format for date string . Defaults to WP settings .
* @ param string | null $attr [ 'time_format' ] Optional . Format for time string . Defaults to WP settings .
* @ param string | null $attr [ 'separator' ] Optional . Separator string for tags , genres , fandoms , etc .
* @ param string | null $attr [ 'tag' ] Optional . The wrapper HTML tag . Defaults to 'span' .
* @ param string | null $attr [ 'class' ] Optional . Additional CSS classes , separated by whitespace .
* @ param string | null $attr [ 'inner_class' ] Optional . Additional CSS classes for nested items , separated by whitespace .
* @ param string | null $attr [ 'style' ] Optional . Inline style applied to wrapper element .
* @ param string | null $attr [ 'inner_style' ] Optional . Inline style applied to nested items .
*
2024-04-16 14:43:20 +02:00
* @ return string The shortcode HTML .
2024-04-16 13:56:14 +02:00
*/
function fictioneer_shortcode_story_data ( $attr ) {
// Setup
$story_id = fictioneer_validate_id ( $attr [ 'story_id' ] ? ? get_the_ID (), 'fcn_story' );
$story_data = fictioneer_get_story_data ( $story_id ? : 0 );
$data = $attr [ 'data' ] ? ? '' ;
$format = $attr [ 'format' ] ? ? '' ;
$separator = wp_strip_all_tags ( $attr [ 'separator' ] ? ? '' ) ? : ', ' ;
$classes = esc_attr ( wp_strip_all_tags ( $attr [ 'class' ] ? ? '' ) );
$inner_classes = esc_attr ( wp_strip_all_tags ( $attr [ 'inner_class' ] ? ? '' ) );
$style = esc_attr ( wp_strip_all_tags ( $attr [ 'style' ] ? ? '' ) );
$inner_style = esc_attr ( wp_strip_all_tags ( $attr [ 'inner_style' ] ? ? '' ) );
$tag = wp_strip_all_tags ( $attr [ 'tag' ] ? ? 'span' );
$output = '' ;
if ( ! $story_data ) {
return '' ;
}
// Get requested data
switch ( $data ) {
case 'word_count' :
$output = $story_data [ 'word_count' ] ? ? 0 ;
$output = $format !== 'short' ? $output : fictioneer_shorten_number ( $output );
$output = ( $format === 'raw' || $format === 'short' ) ? $output : number_format_i18n ( $output );
break ;
case 'chapter_count' :
$output = $story_data [ 'chapter_count' ] ? ? 0 ;
$output = $format === 'raw' ? $output : number_format_i18n ( $output );
break ;
case 'status' :
$output = $story_data [ 'status' ] ? ? '' ;
break ;
case 'icon' :
$output = esc_attr ( $story_data [ 'icon' ] ? ? '' );
$output = $output ? " <i class=' { $output } '></i> " : '' ;
break ;
case 'age_rating' :
$output = $story_data [ 'rating' ] ? ? '' ;
break ;
case 'rating_letter' :
$output = $story_data [ 'rating_letter' ] ? ? '' ;
break ;
case 'comment_count' :
$output = $story_data [ 'comment_count' ] ? ? 0 ;
$output = $format === 'raw' ? $output : number_format_i18n ( $output );
break ;
case 'id' :
$output = $story_data [ 'id' ] ? ? '' ;
break ;
case 'datetime' :
$date = get_the_date ( $attr [ 'date_format' ] ? ? '' , $story_id );
$time = get_the_time ( $attr [ 'time_format' ] ? ? '' , $story_id );
$output = sprintf ( $format ? $format : '%s at %s' , $date , $time );
break ;
case 'date' :
$output = get_the_date ( $attr [ 'date_format' ] ? ? '' , $story_id );
break ;
case 'time' :
$output = get_the_time ( $attr [ 'time_format' ] ? ? '' , $story_id );
break ;
}
// Get requested terms
if ( in_array ( $data , [ 'categories' , 'tags' , 'genres' , 'fandoms' , 'characters' , 'warnings' ] ) ) {
$terms = $data === 'categories' ? get_the_category ( $story_id ) : ( $story_data [ $data ] ? ? [] );
$terms = is_array ( $terms ) ? $terms : [];
$output = [];
foreach ( $terms as $term ) {
$link = get_tag_link ( $term );
$output [] = " <a href=' { $link } ' class='story-page-terms _ { $data } { $inner_classes } ' style=' { $inner_style } '> { $term -> name } </a> " ;
}
$output = implode ( $separator , $output );
}
// Build and return output
2024-04-18 12:27:49 +02:00
return $output ? " < { $tag } class='story-data { $classes } ' style=' { $style } '> { $output } </ { $tag } > " : '' ;
2024-04-16 13:56:14 +02:00
}
add_shortcode ( 'fictioneer_story_data' , 'fictioneer_shortcode_story_data' );
2024-04-16 14:43:20 +02:00
// =============================================================================
// FONT AWESOME SHORTCODE
// =============================================================================
/**
* Shortcode to show a Font Awesome icon
*
* @ since 5.14 . 0
*
* @ param string | null $attr [ 'class' ] The icon classes , separated by whitespace .
*
* @ return string The shortcode HTML .
*/
function fictioneer_shortcode_font_awesome ( $attr ) {
// Setup
$classes = esc_attr ( trim ( wp_strip_all_tags ( $attr [ 'class' ] ? ? '' ) ) );
if ( empty ( $classes ) ) {
return '' ;
}
// Build and return output
return " <i class=' { $classes } '></i> " ;
}
add_shortcode ( 'fictioneer_fa' , 'fictioneer_shortcode_font_awesome' );
2024-06-13 14:25:56 +02:00
// =============================================================================
// SIDEBAR SHORTCODE
// =============================================================================
/**
* Shortcode to show sidebar
*
* @ since 5.20 . 0
*
* @ param string | null $attr [ 'name' ] Optional . Name of the sidebar . Default 'fictioneer_sidebar' .
*
* @ return string The captured shortcode HTML .
*/
function fictioneer_shortcode_sidebar ( $attr ) {
// Setup
$name = sanitize_text_field ( $attr [ 'name' ] ? ? '' ) ? : 'fictioneer-sidebar' ;
// Buffer
ob_start ();
2024-08-03 20:40:13 +02:00
// Does sidebar exist?
if ( ! is_active_sidebar ( $name ) ) {
return ;
}
2024-08-09 09:53:21 +02:00
// Remove filters
remove_filter ( 'excerpt_more' , 'fictioneer_excerpt_ellipsis' );
remove_filter ( 'excerpt_length' , 'fictioneer_custom_excerpt_length' );
2024-08-03 20:40:13 +02:00
// Start HTML ---> ?>
< div class = " fictioneer-sidebar _shortcode " >
< div class = " fictioneer-sidebar__wrapper " >
< ? php dynamic_sidebar ( $name ); ?>
</ div >
</ div >
< ? php // <--- End HTML
2024-06-13 14:25:56 +02:00
2024-08-09 09:53:21 +02:00
// Restore filters
add_filter ( 'excerpt_more' , 'fictioneer_excerpt_ellipsis' );
add_filter ( 'excerpt_length' , 'fictioneer_custom_excerpt_length' );
2024-06-13 14:25:56 +02:00
// Capture and return buffer
return ob_get_clean ();
}
2024-06-13 14:51:01 +02:00
if ( ! get_option ( 'fictioneer_disable_all_widgets' ) ) {
add_shortcode ( 'fictioneer_sidebar' , 'fictioneer_shortcode_sidebar' );
}
2024-10-03 12:57:55 +02:00
// =============================================================================
2024-10-14 23:28:46 +07:00
// TOOLTIP AND FOOTNOTE SHORTCODE
2024-10-03 12:57:55 +02:00
// =============================================================================
/**
2024-10-14 23:28:46 +07:00
* Shortcode to add a tooltip with an associated footnote
*
2024-10-13 23:08:49 +07:00
* @ since 5.25 . 0
2024-10-03 12:57:55 +02:00
*
2024-10-14 20:01:25 +02:00
* @ param string $atts [ 'header' ] Optional . Header of the tooltip .
* @ param string $atts [ 'content' ] Content of the tooltip .
* @ param bool $atts [ 'footnote' ] Optional . Whether to show the footnote . Default true .
* @ param string $content Shortcode content .
2024-10-14 23:28:46 +07:00
*
* @ return string HTML for the tooltip and associated footnote link .
2024-10-03 12:57:55 +02:00
*/
2024-10-14 20:01:25 +02:00
function fictioneer_shortcode_tooltip ( $atts , $content = null ) {
2024-10-14 23:28:46 +07:00
// Initialize a static counter for unique tooltip/footnote IDs
static $tooltip_id_counter = 0 ;
2024-10-14 20:01:25 +02:00
// Setup
$default_atts = array (
'header' => '' ,
2024-10-14 23:28:46 +07:00
'content' => '' ,
2024-10-14 23:46:52 +07:00
'footnote' => true ,
2024-10-14 20:01:25 +02:00
);
2024-10-14 23:28:46 +07:00
$atts = shortcode_atts ( $default_atts , $atts , 'fcnt' );
2024-10-14 20:01:25 +02:00
$footnote_allowed = get_option ( 'fictioneer_generate_footnotes_from_tooltips' ) && $atts [ 'footnote' ];
$footnote_link = '' ;
2024-10-14 23:28:46 +07:00
// Sanitize user inputs
2024-10-14 20:01:25 +02:00
$tooltip_header = trim ( wp_kses_post ( $atts [ 'header' ] ) );
2024-10-14 23:28:46 +07:00
$tooltip_content = trim ( wp_kses_post ( $atts [ 'content' ] ) );
2024-10-03 12:57:55 +02:00
2024-10-13 23:04:38 +07:00
// Bail if no content
2024-10-14 23:28:46 +07:00
if ( empty ( $tooltip_content ) ) {
2024-10-13 23:04:38 +07:00
return $content ;
}
2024-10-03 12:57:55 +02:00
2024-10-14 20:01:25 +02:00
// Increment counter
$tooltip_id_counter ++ ;
// Prepare footnote if allowed
if ( $footnote_allowed ) {
// Create a footnote link to be appended to the tooltip content
$footnote_link = sprintf (
'<sup class="tooltip-counter"><a href="#footnote-%1$d" class="footnote-link">%1$d</a></sup>' ,
$tooltip_id_counter
);
}
2024-10-13 22:52:44 +07:00
2024-10-14 23:28:46 +07:00
// Prepare data attributes for the tooltip
2024-10-14 20:01:25 +02:00
$tooltip_data = array (
'dialog-header' => $tooltip_header ,
2024-10-14 23:28:46 +07:00
'dialog-content' => $tooltip_content . $footnote_link ,
2024-10-14 20:01:25 +02:00
);
2024-10-13 22:52:44 +07:00
2024-10-14 23:28:46 +07:00
// Convert data array to HTML attributes
$tooltip_data_attributes = array_map (
function ( $key , $value ) {
return sprintf ( 'data-%s="%s"' , esc_attr ( $key ), esc_attr ( $value ) );
2024-10-13 23:04:38 +07:00
},
2024-10-14 23:28:46 +07:00
array_keys ( $tooltip_data ),
$tooltip_data
2024-10-13 23:04:38 +07:00
);
2024-10-13 22:52:44 +07:00
2024-10-14 23:28:46 +07:00
$tooltip_title = _x ( 'Click to see note' , 'Tooltip shortcode.' , 'fictioneer' );
2024-10-13 23:04:38 +07:00
2024-10-14 23:28:46 +07:00
// Construct the HTML for the tooltip
2024-10-13 23:04:38 +07:00
$html = sprintf (
2024-10-14 23:28:46 +07:00
'<span><a id="tooltip-%1$d" class="modal-tooltip" title="%2$s" %3$s data-click-action="open-tooltip-modal">%4$s</a>%5$s</span>' ,
$tooltip_id_counter ,
esc_attr ( $tooltip_title ),
implode ( ' ' , $tooltip_data_attributes ),
2024-10-13 23:04:38 +07:00
$content ,
$footnote_link
);
2024-10-03 12:57:55 +02:00
2024-10-14 20:01:25 +02:00
// Collect footnote if allowed
if ( $footnote_allowed ) {
2024-10-14 23:46:52 +07:00
do_action ( 'fictioneer_collect_footnote' , $tooltip_id_counter , $tooltip_content );
}
2024-10-03 12:57:55 +02:00
2024-10-13 23:04:38 +07:00
return $html ;
2024-10-03 12:57:55 +02:00
}
2024-10-14 20:01:25 +02:00
add_shortcode ( 'fcnt' , 'fictioneer_shortcode_tooltip' );
2025-01-07 19:45:50 +01:00
// =============================================================================
// TERMS SHORTCODE
// =============================================================================
/**
* Shortcode to show taxonomies .
*
* @ since 5.27 . 2
*
* @ param string | null $attr [ 'term_type' ] Term type . Default 'post_tag' .
* @ param int | null $attr [ 'post_id' ] Post ID . Default 0.
* @ param int | null $attr [ 'count' ] Maximum number of terms . Default - 1 ( all ) .
* @ param string | null $attr [ 'orderby' ] Orderby argument . Default 'count' .
* @ param string | null $attr [ 'order' ] Order argument . Default 'DESC' .
* @ param bool | null $attr [ 'show_empty' ] Whether to show empty terms . Default false .
* @ param bool | null $attr [ 'show_count' ] Whether to show term counts . Default false .
* @ param string | null $attr [ 'classes' ] Additional section CSS classes . Default empty .
* @ param string | null $attr [ 'inner_classes' ] Additional term CSS classes . Default empty .
* @ param string | null $attr [ 'style' ] Inline section CSS style . Default empty .
* @ param string | null $attr [ 'inner_style' ] Inline term CSS style . Default empty .
* @ param string | null $attr [ 'empty' ] Override message for empty query result .
*
* @ return string The shortcode HTML .
*/
function fictioneer_shortcode_terms ( $attr ) {
// Setup
$type = sanitize_key ( $attr [ 'type' ] ? ? 'tag' );
$post_id = absint ( $attr [ 'post_id' ] ? ? 0 );
$count = max ( - 1 , intval ( $attr [ 'count' ] ? ? - 1 ) );
$orderby = sanitize_text_field ( $attr [ 'orderby' ] ? ? 'count' );
$order = sanitize_text_field ( $attr [ 'order' ] ? ? 'DESC' );
$show_empty = filter_var ( $attr [ 'show_empty' ] ? ? 0 , FILTER_VALIDATE_BOOLEAN );
$show_count = filter_var ( $attr [ 'show_count' ] ? ? 0 , FILTER_VALIDATE_BOOLEAN );
$classes = esc_attr ( wp_strip_all_tags ( $attr [ 'classes' ] ? ? $attr [ 'class' ] ? ? '' ) );
$inner_classes = esc_attr ( wp_strip_all_tags ( $attr [ 'inner_classes' ] ? ? $attr [ 'inner_class' ] ? ? '' ) );
$style = esc_attr ( wp_strip_all_tags ( $attr [ 'style' ] ? ? '' ) );
$inner_style = esc_attr ( wp_strip_all_tags ( $attr [ 'inner_style' ] ? ? '' ) );
$empty = sanitize_text_field ( $attr [ 'empty' ] ? ? __ ( 'No taxonomies specified yet.' , 'fictioneer' ) );
$term_map = array (
'tag' => 'post_tag' ,
'genre' => 'fcn_genre' ,
'fandom' => 'fcn_fandom' ,
'character' => 'fcn_character' ,
'warning' => 'fcn_content_warning'
);
$term_type = $term_map [ $type ] ? ? $type ;
// Term exists?
if ( ! taxonomy_exists ( $term_type ) ) {
return 'Error: Taxonomy does not exist.' ;
}
// Post exists?
if ( $post_id && ! get_post ( $post_id ) ) {
return 'Error: Post not found.' ;
}
// Prepare query args
$args = array (
2025-01-08 00:02:01 +01:00
'fictioneer_query_name' => 'terms_shortcode' ,
2025-01-07 19:45:50 +01:00
'taxonomy' => $term_type ,
'orderby' => $orderby ,
'order' => $order ,
'hide_empty' => ! $show_empty
);
if ( $count > 0 ) {
$args [ 'number' ] = $count ;
}
2025-01-08 00:02:01 +01:00
// Apply filters
$args = apply_filters ( 'fictioneer_filter_shortcode_terms_query_args' , $args , $attr );
2025-01-07 19:45:50 +01:00
// Query terms
if ( $post_id ) {
$terms = wp_get_post_terms ( $post_id , $term_type , $args );
} else {
$terms = get_terms ( $args );
}
// All good?
if ( is_wp_error ( $terms ) ) {
return 'Error: ' . $terms -> get_error_message ();
}
// Build and return HTML
$html = '' ;
if ( ! empty ( $terms ) ) {
foreach ( $terms as $term ) {
$html .= sprintf (
'<a href="%s" class="tag-pill _taxonomy-%s _taxonomy-slug-%s %s" style="%s">%s</a>' ,
get_tag_link ( $term ),
str_replace ( 'fcn_' , '' , $term -> taxonomy ),
$term -> slug ,
'tag-pill ' . $inner_classes ,
$inner_style ,
$show_count
? sprintf ( _x ( '%1$s (%2$s)' , 'Terms shortcode with count.' , 'fictioneer' ), $term -> name , $term -> count )
: $term -> name
);
}
} else {
$html = $empty ;
}
return sprintf (
'<section class="terms-shortcode tag-group %s" style="%s">%s</section>' ,
" _ { $term_type } { $classes } " . wp_unique_id ( 'shortcode-id-' ),
$style ,
$html
);
}
add_shortcode ( 'fictioneer_terms' , 'fictioneer_shortcode_terms' );