Tetrakern 373baa55c9 Make actions/filter no longer pluggable
You can remove them anyway, no need to sacrifice CPU cycles for this.
2023-08-08 22:45:55 +02:00

735 lines
25 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
// =============================================================================
// ADD SEO METABOX
// =============================================================================
/**
* Adds a SEO metabox to selected post types
*
* @since Fictioneer 4.0
*
* @param string $post_type Post type.
* @param string $post Post object.
*/
function fictioneer_add_seo_metabox( $post_type, $post ) {
// Setup
$for_these_types = ['post', 'page', 'fcn_story', 'fcn_chapter', 'fcn_collection', 'fcn_recommendation'];
$not_these_slugs = ['singular-bookshelf.php', 'singular-bookmarks.php', 'user-profile.php'];
// Add meta box
if ( in_array( $post_type, $for_these_types ) && ! in_array( get_page_template_slug( $post ), $not_these_slugs ) ) {
add_meta_box(
'fictioneer-search-engine-appearance',
__( 'SEO & Meta Tags', 'fictioneer' ),
'fictioneer_seo_fields',
null,
'normal',
'high'
);
}
}
if ( get_option( 'fictioneer_enable_seo' ) && ! fictioneer_seo_plugin_active() ) {
add_action( 'add_meta_boxes', 'fictioneer_add_seo_metabox', 10, 2 );
}
// =============================================================================
// SEO METABOX HTML
// =============================================================================
if ( ! function_exists( 'fictioneer_seo_fields' ) ) {
/**
* Output HTML for SEO metabox
*
* @since Fictioneer 4.0
*
* @param object $post The post object.
*/
function fictioneer_seo_fields( $post ) {
// Title
$seo_title = get_post_meta( $post->ID, 'fictioneer_seo_title', true ) ?? '{{title}} {{site}}';
$seo_title_placeholder = fictioneer_get_safe_title( $post->ID ) . ' ' . FICTIONEER_SITE_NAME;
// Description (truncated if necessary)
$seo_description = get_post_meta( $post->ID, 'fictioneer_seo_description', true ) ?? '{{excerpt}}';
$seo_description_placeholder = wp_strip_all_tags( get_the_excerpt( $post ), true );
$seo_description_placeholder = mb_strimwidth( $seo_description_placeholder, 0, 155, '…' );
// Open Graph image...
$seo_og_image = get_post_meta( $post->ID, 'fictioneer_seo_og_image', true );
$seo_og_image_display = wp_get_attachment_url( $seo_og_image );
$image_source = '';
// ... if not set, look for thumbnail...
if ( ! $seo_og_image_display && has_post_thumbnail( $post->ID ) ) {
$seo_og_image_display = get_the_post_thumbnail_url( $post->ID );
$image_source = 'thumbnail';
}
// ... if not found, look for parent thumbnail...
if ( ! $seo_og_image_display && $post->post_type == 'fcn_chapter' ) {
$story_id = fictioneer_get_field( 'fictioneer_chapter_story', $post->ID );
if ( $story_id && has_post_thumbnail( $story_id ) ) {
$seo_og_image_display = get_the_post_thumbnail_url( $story_id );
$image_source = 'parent-thumbnail';
}
}
// ... if not found either, try the default OG image...
if ( ! $seo_og_image_display && get_theme_mod( 'og_image' ) ) {
$seo_og_image_display = wp_get_attachment_url( get_theme_mod( 'og_image' ) );
$image_source = 'default';
}
// ... okay, use a placeholder
if ( ! $seo_og_image_display ) {
$seo_og_image_display = get_template_directory_uri() . '/img/no_image_placeholder.svg';
$image_source = 'placeholder';
}
// Start HTML ---> ?>
<div class="fictioneer-metabox">
<input type="hidden" name="fictioneer_metabox_seo_nonce" value="<?php echo wp_create_nonce( 'fictioneer-metabox-seo-save' ); ?>">
<p class="description"><?php _ex( 'Metadata for search engine results, schema graphs, and social media embeds. If left blank, defaults will be derived from the content. You can use <code>{{title}}</code>, <code>{{site}}</code>, and <code>{{excerpt}}</code> as placeholders. Whether these services actually display the offered data is entirely up to them.', 'Do not translate {{title}}, {{site}}, and {{excerpt}}.', 'fictioneer' ); ?></p>
<div class="fictioneer-metabox__left">
<div class="fictioneer-metabox__row">
<label for="fictioneer-seo-title">
<span><?php _e( 'Title', 'fictioneer' ); ?></span>
<span id="fictioneer-seo-title-chars" class="counter"></span>
</label>
<input id="fictioneer-seo-title" type="text" data-lpignore="true" name="fictioneer_seo_title" value="<?php echo esc_attr( $seo_title ); ?>" placeholder="<?php echo esc_attr( $seo_title_placeholder ); ?>">
</div>
<div class="fictioneer-metabox__row">
<label for="fictioneer-seo-description">
<span><?php _e( 'Description', 'fictioneer' ); ?></span>
</label>
<textarea id="fictioneer-seo-description" name="fictioneer_seo_description" rows="3" placeholder="<?php echo esc_attr( $seo_description_placeholder ); ?>"><?php echo $seo_description; ?></textarea>
</div>
</div>
<div class="fictioneer-metabox__right">
<input type="hidden" id="fictioneer-seo-og-image" name="fictioneer_seo_og_image" value="<?php echo $seo_og_image; ?>">
<a href="#" id="fictioneer-button-seo-og-image-remove" class="og-remove <?php echo $seo_og_image ? '' : 'hidden'; ?>"><?php _e( 'Remove', 'fictioneer' ) ?></a>
<div class="og-source <?php echo $image_source; ?>">
<div class="thumbnail"><?php _e( 'Source: Thumbnail', 'fictioneer' ) ?></div>
<div class="parent-thumbnail"><?php _e( 'Source: Parent', 'fictioneer' ) ?></div>
<div class="default"><?php _e( 'Source: Site Default', 'fictioneer' ) ?></div>
</div>
<a href="#" id="fictioneer-button-og-upload">
<img id="fictioneer-seo-og-display" src="<?php echo esc_url( $seo_og_image_display ); ?>" data-placeholder="<?php echo esc_url( get_template_directory_uri() . '/img/no_image_placeholder.svg' ); ?>">
<div class="og-upload-label"><?php _e( 'Open Graph Image', 'fictioneer' ) ?></div>
</a>
</div>
</div>
<?php // <--- End HTML
}
}
// =============================================================================
// SAVE SEO METABOX
// =============================================================================
/**
* Save SEO metabox data
*
* @since Fictioneer 4.0
*
* @param int $post_id The post ID.
*/
function fictioneer_save_seo_metabox( $post_id ) {
// Validations
if (
! isset( $_POST['fictioneer_metabox_seo_nonce'] ) ||
! wp_verify_nonce( $_POST['fictioneer_metabox_seo_nonce'], 'fictioneer-metabox-seo-save' ) ||
! current_user_can( 'edit_post', $post_id ) ||
wp_is_post_autosave( $post_id ) ||
wp_is_post_revision( $post_id ) ||
in_array( get_post_status( $post_id ), ['auto-draft'] )
) {
return;
}
// Save image
if ( isset( $_POST['fictioneer_seo_og_image'] ) ) {
update_post_meta( $post_id, 'fictioneer_seo_og_image', $_POST['fictioneer_seo_og_image'] );
}
// Save title
if ( isset( $_POST['fictioneer_seo_title'] ) ) {
update_post_meta( $post_id, 'fictioneer_seo_title', $_POST['fictioneer_seo_title'] );
}
// Save description
if ( isset( $_POST['fictioneer_seo_description'] ) ) {
update_post_meta( $post_id, 'fictioneer_seo_description', $_POST['fictioneer_seo_description'] );
}
// Clear caches
delete_post_meta( $post_id, 'fictioneer_seo_title_cache' );
delete_post_meta( $post_id, 'fictioneer_seo_description_cache' );
delete_post_meta( $post_id, 'fictioneer_seo_og_image_cache' );
}
if ( get_option( 'fictioneer_enable_seo' ) && ! fictioneer_seo_plugin_active() ) {
add_action( 'save_post', 'fictioneer_save_seo_metabox', 10 );
}
// =============================================================================
// GET SEO TITLE
// =============================================================================
if ( ! function_exists( 'fictioneer_get_seo_title' ) ) {
/**
* Get SEO title
*
* @since Fictioneer 4.0
*
* @param int $post_id Optional. The post ID.
* @param array $args Optional. Array of arguments.
*
* @return string The SEO title.
*/
function fictioneer_get_seo_title( $post_id = null, $args = [] ) {
// Setup
$post_id = $post_id ? $post_id : get_queried_object_id();
$page = get_query_var( 'paged', 0 ); // Only default pagination is considered
$page_note = $page > 1 ? sprintf( __( ' Page %s', 'fictioneer' ), $page ) : '';
$site_name = FICTIONEER_SITE_NAME;
$skip_cache = isset( $args['skip_cache'] ) && $args['skip_cache'];
$default = isset( $args['default'] ) && ! empty( $args['default'] ) ? $args['default'] : false;
// Search?
if ( is_search() ) {
return esc_html(
sprintf(
_x( 'Search %s', 'Search Site Name.', 'fictioneer' ),
$site_name
)
);
}
// Author?
if ( is_author() ) {
$author_id = get_queried_object_id();
$author = get_userdata( $author_id );
if ( $author ) {
return $author->display_name;
} else {
return _x( 'Author', 'Fallback SEO title for author pages.', 'fictioneer' );
}
}
// Archive?
if ( is_archive() ) {
// Category?
if ( is_category() ) {
return esc_html(
sprintf(
_x( 'Category: %1$s%2$s %3$s', 'Category: Category[ Page n] Site Name. The page is optional.', 'fictioneer' ),
single_cat_title( '', false ),
$page_note,
$site_name
)
);
}
// Tag?
if ( is_tag() ) {
return esc_html(
sprintf(
_x( 'Tag: %1$s%2$s %3$s', 'Tag: Tag[ Page n] Site Name. The page is optional.', 'fictioneer' ),
single_tag_title( '', false ),
$page_note,
$site_name
)
);
}
// Character?
if ( is_tax( 'fcn_character' ) ) {
return esc_html(
sprintf(
_x( 'Character: %1$s%2$s %3$s', 'Character: Character[ Page n] Site Name. The page is optional.', 'fictioneer' ),
single_tag_title( '', false ),
$page_note,
$site_name
)
);
}
// Fandom?
if ( is_tax( 'fcn_fandom' ) ) {
return esc_html(
sprintf(
_x( 'Fandom: %1$s%2$s %3$s', 'Fandom: Fandom[ Page n] Site Name. The page is optional.', 'fictioneer' ),
single_tag_title( '', false ),
$page_note,
$site_name
)
);
}
// Genre?
if ( is_tax( 'fcn_genre' ) ) {
return esc_html(
sprintf(
_x( 'Genre: %1$s%2$s %3$s', 'Genre: Genre[ Page n] Site Name. The page is optional.', 'fictioneer' ),
single_tag_title( '', false ),
$page_note,
$site_name
)
);
}
// Generic archive?
return esc_html( sprintf( __( 'Archive %1$s', 'fictioneer' ), $site_name ) );
}
// Cached title?
$cache = get_post_meta( $post_id, 'fictioneer_seo_title_cache', true );
if ( ! empty( $cache ) && ! $skip_cache ) return $cache;
// Start building...
$seo_title = get_post_meta( $post_id, 'fictioneer_seo_title', true );
$seo_title = empty( $seo_title ) ? false : $seo_title;
// Frontpage case...
if ( is_front_page() && $seo_title == '{{title}} {{site}}' ) {
$seo_title = $site_name;
}
// Defaults...
if ( $default && ( ! $seo_title || $seo_title == '{{title}} {{site}}' ) ) {
$seo_title = $default;
}
// Replace {{title}} placeholder...
if ( str_contains( $seo_title, '{{title}}' ) ) {
$seo_title = str_replace( '{{title}}', fictioneer_get_safe_title( $post_id ), $seo_title );
}
// Replace {{site}} placeholder...
if ( str_contains( $seo_title, '{{site}}' ) ) {
$seo_title = str_replace( '{{site}}', $site_name, $seo_title );
}
// Catch empty
if ( empty( $seo_title ) ) {
$seo_title = sprintf(
_x( '%1$s%2$s %3$s', 'Post Title[ Page n] Site Name. The page is optional.', 'fictioneer' ),
get_the_title( $post_id ),
$page_note,
$site_name
);
}
// Finalize
$seo_title = esc_html( trim( wp_strip_all_tags( $seo_title ) ) );
// Cache for next time
if ( ! $skip_cache ) {
update_post_meta( $post_id, 'fictioneer_seo_title_cache', $seo_title );
}
return $seo_title;
}
}
// =============================================================================
// GET SEO DESCRIPTION
// =============================================================================
if ( ! function_exists( 'fictioneer_get_seo_description' ) ) {
/**
* Get SEO description
*
* @since Fictioneer 4.0
*
* @param int $post_id Optional. The post ID.
* @param array $args Optional. Array of arguments.
*
* @return string The SEO description.
*/
function fictioneer_get_seo_description( $post_id = null, $args = [] ) {
// Setup
$post_id = $post_id ? $post_id : get_queried_object_id();
$site_name = FICTIONEER_SITE_NAME;
$skip_cache = isset( $args['skip_cache'] ) && $args['skip_cache'];
$default = isset( $args['default'] ) && ! empty( $args['default'] ) ? $args['default'] : false;
// Search?
if ( is_search() ) {
return esc_html(
sprintf(
_x( 'Search results on %s.', 'Search page SEO description.', 'fictioneer' ),
$site_name
)
);
}
// Author?
if ( is_author() ) {
$author_id = get_queried_object_id();
$author = get_userdata( $author_id );
if ( $author && ! empty( $author->user_description ) ) {
return $author->user_description;
} else {
return esc_html(
sprintf(
_x( 'Author on %s.', 'Fallback SEO description for author pages.', 'fictioneer' ),
$site_name
)
);
}
}
// Archive?
if ( is_archive() ) {
// Category?
if ( is_category() ) {
return esc_html(
sprintf(
__( 'Archive of all posts in the %s category.', 'fictioneer' ),
single_cat_title( '', false )
)
);
}
// Tag?
if ( is_tag() ) {
return esc_html(
sprintf(
__( 'Archive of all posts with the %s tag.', 'fictioneer' ),
single_tag_title( '', false )
)
);
}
// Character?
if ( is_tax( 'fcn_character' ) ) {
return esc_html(
sprintf(
__( 'Archive of all posts with the character %s.', 'fictioneer' ),
single_tag_title( '', false )
)
);
}
// Fandom?
if ( is_tax( 'fcn_fandom' ) ) {
return esc_html(
sprintf(
__( 'Archive of all posts in the %s fandom.', 'fictioneer' ),
single_tag_title( '', false )
)
);
}
// Genre?
if ( is_tax( 'fcn_genre' ) ) {
return esc_html(
sprintf(
__( 'Archive of all posts with the %s genre.', 'fictioneer' ),
single_tag_title( '', false )
)
);
}
// Generic archive?
return esc_html( sprintf( __( 'Archived posts on %s.', 'fictioneer' ), $site_name ) );
}
// Cached description?
$cache = get_post_meta( $post_id, 'fictioneer_seo_description_cache', true );
if ( ! empty( $cache ) && ! $skip_cache ) return $cache;
// Start building...
$seo_description = get_post_meta( $post_id, 'fictioneer_seo_description', true );
$seo_description = empty( $seo_description ) ? false : $seo_description;
$excerpt = '';
// Special Case: Recommendations
if ( get_post_type( $post_id ) == 'fcn_recommendation' ) {
$default = fictioneer_get_field( 'fictioneer_recommendation_one_sentence', $post_id );
}
// Defaults...
if ( $default && ( ! $seo_description || $seo_description == '{{excerpt}}' ) ) {
$seo_description = $default;
}
// Get description from excerpt if necessary...
if ( ! $seo_description || str_contains( $seo_description, '{{excerpt}}' ) ) {
$excerpt = wp_strip_all_tags( get_the_excerpt( $post_id ), true );
$excerpt = mb_strimwidth( $excerpt, 0, 155, '…' );
if ( ! $seo_description ) $seo_description = $excerpt;
}
// Replace {{excerpt}} placeholder...
if ( str_contains( $seo_description, '{{excerpt}}' ) ) {
$seo_description = str_replace( '{{excerpt}}', $excerpt, $seo_description );
}
// Catch empty
if ( empty( $seo_description ) ) {
$seo_description = $default ? $default : FICTIONEER_SITE_DESCRIPTION;
}
// Finalize
$seo_description = esc_html( trim( wp_strip_all_tags( $seo_description ) ) );
// Cache for next time
if ( ! $skip_cache ) {
update_post_meta( $post_id, 'fictioneer_seo_description_cache', $seo_description );
}
return $seo_description;
}
}
// =============================================================================
// GET SEO IMAGE
// =============================================================================
if ( ! function_exists( 'fictioneer_get_seo_image' ) ) {
/**
* Get SEO image data array
*
* @since Fictioneer 4.0
*
* @param int $post_id Optional. The post ID.
*
* @return array|boolean Data of the image or false if none has been found.
*/
function fictioneer_get_seo_image( $post_id = null ) {
// Setup
$post_id = $post_id ? $post_id : get_queried_object_id();
$use_default = is_archive() || is_search() || is_author();
$transient = get_transient( 'fictioneer_default_global_og_image' );
$default_id = get_theme_mod( 'og_image' );
$image_id = false;
$image = false;
// Page with site default OG image?
if ( $use_default ) {
// Try default OG image Transient
if ( ! empty( $transient ) && $default_id == ( $transient['id'] ?? -1 ) ) {
return $transient;
}
// Get default ID from settings
$image_id = $default_id;
}
// Cached image? Except for site default, which can globally change!
if ( ! $use_default ) {
$cache = get_post_meta( $post_id, 'fictioneer_seo_og_image_cache', true );
if ( $cache ) return $cache;
}
// Get image ID if not yet set
if ( ! $image_id ) {
$image_id = get_post_meta( $post_id, 'fictioneer_seo_og_image', true );
$image_id = wp_attachment_is_image( $image_id ) ? $image_id : false;
}
// No image found...
if ( ! $image_id ) {
// Try thumbnail...
if ( has_post_thumbnail( $post_id ) ) {
$image_id = get_post_thumbnail_id( $post_id );
}
// Try story thumbnail if chapter...
if ( ! $image_id && get_post_type( $post_id ) == 'fcn_chapter' ) {
$story_id = fictioneer_get_field( 'fictioneer_chapter_story', $post_id );
$image_id = has_post_thumbnail( $story_id ) ? get_post_thumbnail_id( $story_id ) : $image_id;
}
// Try default if still nothing...
if ( ! $image_id && get_theme_mod( 'og_image') ) {
// Try default OG image Transient
if ( ! empty( $transient ) && $default_id == ( $transient['id'] ?? -1 ) ) {
return $transient;
}
// Get default ID from settings
$image_id = $default_id;
}
}
// If an image has been found...
if ( $image_id ) {
$meta = wp_get_attachment_metadata( $image_id );
if ( $meta ) {
$image = array(
'url' => wp_get_attachment_url( $image_id ),
'height' => $meta['height'],
'width' => $meta['width'],
'type' => get_post_mime_type( $image_id ),
'id' => $image_id
);
if ( $use_default ) {
set_transient( 'fictioneer_default_global_og_image', $image );
}
}
}
// Cache for next time
if ( ! $use_default ) {
update_post_meta( $post_id, 'fictioneer_seo_og_image_cache', $image );
}
return $image;
}
}
// =============================================================================
// OUTPUT HEAD SEO
// =============================================================================
/**
* Output HTML <head> SEO meta
*
* @since Fictioneer 5.0
*/
function fictioneer_output_head_seo() {
global $wp;
global $post;
// Setup
$post_id = get_queried_object_id(); // In archives and search, this is the first post
$post_type = get_post_type(); // In archives and search, this is the first post
$post_author = $post->post_author ?? 0;
$chapter_story_id = fictioneer_get_field( 'fictioneer_chapter_story' ) ?? 0;
$canonical_url = wp_get_canonical_url(); // Unreliable on aggregated pages
// Flags
$is_page = is_page() || is_front_page() || is_home();
$is_aggregated = is_archive() || is_search();
$is_article = ! $is_page && in_array( $post_type, ['fcn_story', 'fcn_chapter', 'fcn_recommendation', 'post'] );
$show_author = $is_article && is_single() && ! is_front_page() && ! is_home() && ! $is_aggregated;
// Derived
$og_type = $is_article ? 'article' : 'website';
$og_image = fictioneer_get_seo_image( $post_id );
$og_title = fictioneer_get_seo_title( $post_id );
$og_description = fictioneer_get_seo_description( $post_id );
$article_author = $post_author && $show_author ? get_the_author_meta( 'display_name', $post_author ) : false;
$article_twitter = $post_author && $show_author ? get_the_author_meta( 'twitter', $post_author ) : false;
// Special Case: Recommendation author
if ( $post_author && $show_author && $post_type == 'fcn_recommendation' ) {
$article_author = fictioneer_get_field( 'fictioneer_recommendation_author', $post_id ) ?? $article_author;
}
// Special Case: Archives
if ( is_archive() ) $canonical_url = home_url( $wp->request );
// Special Case: Search
if ( is_search() ) $canonical_url = add_query_arg( 's', '', home_url( $wp->request ) );
// Start HTML ---> ?>
<link rel="canonical" href="<?php echo $canonical_url; ?>">
<meta name="description" content="<?php echo $og_description; ?>">
<meta property="og:locale" content="<?php echo get_locale(); ?>">
<meta property="og:type" content="<?php echo $og_type; ?>">
<meta property="og:title" content="<?php echo $og_title; ?>">
<meta property="og:description" content="<?php echo $og_description; ?>">
<meta property="og:url" content="<?php echo $canonical_url; ?>">
<meta property="og:site_name" content="<?php echo FICTIONEER_SITE_NAME; ?>">
<?php if ( ! $is_aggregated && $is_article ) : ?>
<meta property="article:published_time" content="<?php echo get_the_date( 'c' ); ?>">
<meta property="article:modified_time" content="<?php echo get_the_modified_date( 'c' ); ?>">
<?php if ( $show_author && $article_author ) : ?>
<?php
// Get URL for primary author (if any)
$article_author_url = get_the_author_meta( 'url', $post_author );
$article_author_url = empty( $article_author_url ) ? get_author_posts_url( $post_author ) : $article_author_url;
// Prepare author array with either URL (required) or name (better than nothing)
$all_authors = empty( $article_author_url ) ? [$article_author] : [$article_author_url];
// Get co-authors (if any)
$co_authors = $post_type == 'fcn_story' ?
fictioneer_get_field( 'fictioneer_story_co_authors', $post_id ) ?? [] :
fictioneer_get_field( 'fictioneer_chapter_co_authors', $post_id ) ?? [];
// Add co-authors URL or name
if ( ! empty( $co_authors ) ) {
foreach ( $co_authors as $co_author_id ) {
$co_author_name = get_the_author_meta( 'display_name', intval( $co_author_id ) );
$co_author_url = get_the_author_meta( 'url', intval( $co_author_id ) );
$co_author_url = empty( $co_author_url ) ? get_author_posts_url( $co_author_id ) : $co_author_url;
$author_item = empty( $co_author_url ) ? $co_author_name : $co_author_url;
if ( ! empty( $author_item ) && ! in_array( $author_item, $all_authors ) ) $all_authors[] = $author_item;
}
}
// Output og array
foreach ( $all_authors as $author_name ) {
echo "<meta property='article:author' content='$author_name'>";
}
?>
<?php endif; ?>
<?php if ( $post_type == 'fcn_chapter' && ! empty( $chapter_story_id ) ) : ?>
<meta property="article:section" content="<?php echo get_the_title( $chapter_story_id ); ?>">
<?php endif; ?>
<?php endif; ?>
<?php if ( is_array( $og_image ) && count( $og_image ) >= 4 ) : ?>
<meta property="og:image" content="<?php echo $og_image['url']; ?>">
<meta property="og:image:width" content="<?php echo $og_image['width']; ?>">
<meta property="og:image:height" content="<?php echo $og_image['height']; ?>">
<meta property="og:image:type" content="<?php echo $og_image['type']; ?>">
<meta name="twitter:image" content="<?php echo $og_image['url']; ?>">
<?php endif; ?>
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="<?php echo $og_title; ?>">
<meta name="twitter:description" content="<?php echo $og_description; ?>">
<?php if ( $show_author && $article_twitter ) : ?>
<meta name="twitter:creator" content="<?php echo '@' . $article_twitter; ?>">
<meta name="twitter:site" content="<?php echo '@' . $article_twitter; ?>">
<?php endif; ?>
<?php // <--- End HTML
}
if ( get_option( 'fictioneer_enable_seo' ) && ! fictioneer_seo_plugin_active() ) {
add_action( 'wp_head', 'fictioneer_output_head_seo', 5 );
}
?>