I will build this as a large, practical inc/helpers/template-functions.php for your RX theme: safe helpers, template tags, breadcrumbs, reading time, post meta, images, pagination, related posts, schema hooks, SEO-friendly utilities, and compatibility functions.
Below is an advanced template-functions.php file for your RX theme.
Place it here:
rx-theme/inc/helpers/template-functions.php
Then load it from functions.php:
require_once get_template_directory() . '/inc/helpers/template-functions.php';
<?php
/**
* RX Theme Template Functions
*
* Advanced helper and template functions for RX Theme.
*
* File path:
* inc/helpers/template-functions.php
*
* @package RX_Theme
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* ------------------------------------------------------------
* 01. BASIC THEME HELPERS
* ------------------------------------------------------------
*/
/**
* Get theme version safely.
*/
if ( ! function_exists( 'rx_theme_version' ) ) {
function rx_theme_version() {
$theme = wp_get_theme();
return $theme ? $theme->get( 'Version' ) : '1.0.0';
}
}
/**
* Get theme name safely.
*/
if ( ! function_exists( 'rx_theme_name' ) ) {
function rx_theme_name() {
$theme = wp_get_theme();
return $theme ? $theme->get( 'Name' ) : 'RX Theme';
}
}
/**
* Get theme URI.
*/
if ( ! function_exists( 'rx_theme_uri' ) ) {
function rx_theme_uri( $path = '' ) {
$uri = get_template_directory_uri();
if ( ! empty( $path ) ) {
$uri .= '/' . ltrim( $path, '/' );
}
return esc_url( $uri );
}
}
/**
* Get theme path.
*/
if ( ! function_exists( 'rx_theme_path' ) ) {
function rx_theme_path( $path = '' ) {
$dir = get_template_directory();
if ( ! empty( $path ) ) {
$dir .= '/' . ltrim( $path, '/' );
}
return $dir;
}
}
/**
* Check if WooCommerce is active.
*/
if ( ! function_exists( 'rx_is_woocommerce_active' ) ) {
function rx_is_woocommerce_active() {
return class_exists( 'WooCommerce' );
}
}
/**
* Check if current page is WooCommerce page.
*/
if ( ! function_exists( 'rx_is_woocommerce_page' ) ) {
function rx_is_woocommerce_page() {
if ( ! rx_is_woocommerce_active() ) {
return false;
}
return is_woocommerce() || is_cart() || is_checkout() || is_account_page();
}
}
/**
* Safe echo SVG icon.
*/
if ( ! function_exists( 'rx_icon' ) ) {
function rx_icon( $name = '', $class = 'rx-icon' ) {
$name = sanitize_key( $name );
$class = esc_attr( $class );
$icons = array(
'search' => '<svg class="' . $class . '" width="20" height="20" viewBox="0 0 24 24" aria-hidden="true"><path d="M21 20l-5.2-5.2a7 7 0 10-1.4 1.4L20 21zM5 10a5 5 0 1110 0A5 5 0 015 10z" fill="currentColor"/></svg>',
'menu' => '<svg class="' . $class . '" width="24" height="24" viewBox="0 0 24 24" aria-hidden="true"><path d="M3 6h18v2H3V6zm0 5h18v2H3v-2zm0 5h18v2H3v-2z" fill="currentColor"/></svg>',
'close' => '<svg class="' . $class . '" width="24" height="24" viewBox="0 0 24 24" aria-hidden="true"><path d="M18.3 5.7L12 12l6.3 6.3-1.4 1.4L10.6 13.4 4.3 19.7 2.9 18.3 9.2 12 2.9 5.7 4.3 4.3l6.3 6.3 6.3-6.3z" fill="currentColor"/></svg>',
'user' => '<svg class="' . $class . '" width="20" height="20" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 12a5 5 0 100-10 5 5 0 000 10zm0 2c-4.4 0-8 2.2-8 5v1h16v-1c0-2.8-3.6-5-8-5z" fill="currentColor"/></svg>',
'date' => '<svg class="' . $class . '" width="20" height="20" viewBox="0 0 24 24" aria-hidden="true"><path d="M7 2h2v2h6V2h2v2h3v18H4V4h3V2zm13 8H6v10h14V10z" fill="currentColor"/></svg>',
);
if ( isset( $icons[ $name ] ) ) {
echo wp_kses(
$icons[ $name ],
array(
'svg' => array(
'class' => true,
'width' => true,
'height' => true,
'viewBox' => true,
'aria-hidden' => true,
),
'path' => array(
'd' => true,
'fill' => true,
),
)
);
}
}
}
/**
* ------------------------------------------------------------
* 02. BODY, POST, AND LAYOUT CLASSES
* ------------------------------------------------------------
*/
/**
* Add advanced body classes.
*/
if ( ! function_exists( 'rx_body_classes' ) ) {
function rx_body_classes( $classes ) {
$classes[] = 'rx-theme';
$classes[] = 'rx-version-' . sanitize_html_class( str_replace( '.', '-', rx_theme_version() ) );
if ( is_front_page() ) {
$classes[] = 'rx-front-page';
}
if ( is_home() ) {
$classes[] = 'rx-blog-page';
}
if ( is_singular() ) {
$classes[] = 'rx-singular';
}
if ( is_single() ) {
$classes[] = 'rx-single-post';
}
if ( is_page() ) {
$classes[] = 'rx-page';
}
if ( is_archive() ) {
$classes[] = 'rx-archive';
}
if ( is_search() ) {
$classes[] = 'rx-search-page';
}
if ( is_404() ) {
$classes[] = 'rx-404-page';
}
if ( is_user_logged_in() ) {
$classes[] = 'rx-user-logged-in';
} else {
$classes[] = 'rx-user-logged-out';
}
if ( has_nav_menu( 'primary' ) ) {
$classes[] = 'rx-has-primary-menu';
}
if ( is_active_sidebar( 'sidebar-1' ) ) {
$classes[] = 'rx-has-sidebar';
} else {
$classes[] = 'rx-no-sidebar';
}
if ( rx_is_woocommerce_page() ) {
$classes[] = 'rx-woocommerce-page';
}
return $classes;
}
}
add_filter( 'body_class', 'rx_body_classes' );
/**
* Add custom post classes.
*/
if ( ! function_exists( 'rx_post_classes' ) ) {
function rx_post_classes( $classes ) {
if ( is_sticky() ) {
$classes[] = 'rx-sticky-post';
}
if ( has_post_thumbnail() ) {
$classes[] = 'rx-has-thumbnail';
} else {
$classes[] = 'rx-no-thumbnail';
}
$post_format = get_post_format();
if ( $post_format ) {
$classes[] = 'rx-format-' . sanitize_html_class( $post_format );
}
return $classes;
}
}
add_filter( 'post_class', 'rx_post_classes' );
/**
* ------------------------------------------------------------
* 03. ACCESSIBILITY HELPERS
* ------------------------------------------------------------
*/
/**
* Skip link for accessibility.
*/
if ( ! function_exists( 'rx_skip_link' ) ) {
function rx_skip_link() {
echo '<a class="skip-link screen-reader-text" href="#primary">' . esc_html__( 'Skip to content', 'rx-theme' ) . '</a>';
}
}
add_action( 'wp_body_open', 'rx_skip_link', 5 );
/**
* Screen reader text.
*/
if ( ! function_exists( 'rx_screen_reader_text' ) ) {
function rx_screen_reader_text( $text = '' ) {
if ( empty( $text ) ) {
return;
}
echo '<span class="screen-reader-text">' . esc_html( $text ) . '</span>';
}
}
/**
* ------------------------------------------------------------
* 04. POST META FUNCTIONS
* ------------------------------------------------------------
*/
/**
* Posted on date.
*/
if ( ! function_exists( 'rx_posted_on' ) ) {
function rx_posted_on() {
$time_string = '<time class="entry-date published updated" datetime="%1$s">%2$s</time>';
if ( get_the_time( 'U' ) !== get_the_modified_time( 'U' ) ) {
$time_string = '<time class="entry-date published" datetime="%1$s">%2$s</time><time class="updated" datetime="%3$s">%4$s</time>';
}
$time_string = sprintf(
$time_string,
esc_attr( get_the_date( DATE_W3C ) ),
esc_html( get_the_date() ),
esc_attr( get_the_modified_date( DATE_W3C ) ),
esc_html( get_the_modified_date() )
);
echo '<span class="posted-on">';
rx_icon( 'date', 'rx-meta-icon' );
echo '<a href="' . esc_url( get_permalink() ) . '" rel="bookmark">' . wp_kses_post( $time_string ) . '</a>';
echo '</span>';
}
}
/**
* Posted by author.
*/
if ( ! function_exists( 'rx_posted_by' ) ) {
function rx_posted_by() {
echo '<span class="byline">';
rx_icon( 'user', 'rx-meta-icon' );
echo '<span class="author vcard">';
echo '<a class="url fn n" href="' . esc_url( get_author_posts_url( get_the_author_meta( 'ID' ) ) ) . '">';
echo esc_html( get_the_author() );
echo '</a>';
echo '</span>';
echo '</span>';
}
}
/**
* Display post categories.
*/
if ( ! function_exists( 'rx_post_categories' ) ) {
function rx_post_categories( $before = '', $after = '' ) {
if ( 'post' !== get_post_type() ) {
return;
}
$categories = get_the_category_list( esc_html__( ', ', 'rx-theme' ) );
if ( $categories ) {
echo wp_kses_post( $before );
echo '<span class="cat-links">';
echo wp_kses_post( $categories );
echo '</span>';
echo wp_kses_post( $after );
}
}
}
/**
* Display post tags.
*/
if ( ! function_exists( 'rx_post_tags' ) ) {
function rx_post_tags( $before = '', $after = '' ) {
if ( 'post' !== get_post_type() ) {
return;
}
$tags = get_the_tag_list( '', esc_html_x( ', ', 'list item separator', 'rx-theme' ) );
if ( $tags ) {
echo wp_kses_post( $before );
echo '<span class="tags-links">';
echo wp_kses_post( $tags );
echo '</span>';
echo wp_kses_post( $after );
}
}
}
/**
* Comments link.
*/
if ( ! function_exists( 'rx_comments_link' ) ) {
function rx_comments_link() {
if ( ! post_password_required() && ( comments_open() || get_comments_number() ) ) {
echo '<span class="comments-link">';
comments_popup_link(
esc_html__( 'Leave a comment', 'rx-theme' ),
esc_html__( '1 Comment', 'rx-theme' ),
esc_html__( '% Comments', 'rx-theme' )
);
echo '</span>';
}
}
}
/**
* Full post meta.
*/
if ( ! function_exists( 'rx_entry_meta' ) ) {
function rx_entry_meta() {
echo '<div class="entry-meta rx-entry-meta">';
rx_posted_on();
rx_posted_by();
rx_comments_link();
echo '</div>';
}
}
/**
* Entry footer.
*/
if ( ! function_exists( 'rx_entry_footer' ) ) {
function rx_entry_footer() {
echo '<footer class="entry-footer rx-entry-footer">';
rx_post_categories(
'<div class="rx-post-categories"><span class="rx-meta-label">' . esc_html__( 'Categories:', 'rx-theme' ) . '</span> ',
'</div>'
);
rx_post_tags(
'<div class="rx-post-tags"><span class="rx-meta-label">' . esc_html__( 'Tags:', 'rx-theme' ) . '</span> ',
'</div>'
);
edit_post_link(
sprintf(
wp_kses(
__( 'Edit <span class="screen-reader-text">%s</span>', 'rx-theme' ),
array(
'span' => array(
'class' => array(),
),
)
),
wp_kses_post( get_the_title() )
),
'<span class="edit-link">',
'</span>'
);
echo '</footer>';
}
}
/**
* ------------------------------------------------------------
* 05. EXCERPT HELPERS
* ------------------------------------------------------------
*/
/**
* Custom excerpt length.
*/
if ( ! function_exists( 'rx_excerpt_length' ) ) {
function rx_excerpt_length( $length ) {
return 28;
}
}
add_filter( 'excerpt_length', 'rx_excerpt_length', 20 );
/**
* Custom excerpt more.
*/
if ( ! function_exists( 'rx_excerpt_more' ) ) {
function rx_excerpt_more( $more ) {
return '…';
}
}
add_filter( 'excerpt_more', 'rx_excerpt_more' );
/**
* Get trimmed excerpt.
*/
if ( ! function_exists( 'rx_get_excerpt' ) ) {
function rx_get_excerpt( $post_id = null, $length = 30 ) {
$post_id = $post_id ? absint( $post_id ) : get_the_ID();
if ( ! $post_id ) {
return '';
}
$post = get_post( $post_id );
if ( ! $post ) {
return '';
}
if ( has_excerpt( $post_id ) ) {
$text = get_the_excerpt( $post_id );
} else {
$text = wp_strip_all_tags( strip_shortcodes( $post->post_content ) );
}
return wp_trim_words( $text, absint( $length ), '…' );
}
}
/**
* Print excerpt.
*/
if ( ! function_exists( 'rx_the_excerpt' ) ) {
function rx_the_excerpt( $length = 30 ) {
echo esc_html( rx_get_excerpt( get_the_ID(), $length ) );
}
}
/**
* Read more button.
*/
if ( ! function_exists( 'rx_read_more_button' ) ) {
function rx_read_more_button( $text = '' ) {
if ( empty( $text ) ) {
$text = esc_html__( 'Read More', 'rx-theme' );
}
echo '<a class="rx-read-more button" href="' . esc_url( get_permalink() ) . '" aria-label="' . esc_attr( sprintf( __( 'Read more about %s', 'rx-theme' ), get_the_title() ) ) . '">';
echo esc_html( $text );
echo '</a>';
}
}
/**
* ------------------------------------------------------------
* 06. READING TIME AND WORD COUNT
* ------------------------------------------------------------
*/
/**
* Get word count.
*/
if ( ! function_exists( 'rx_get_word_count' ) ) {
function rx_get_word_count( $post_id = null ) {
$post_id = $post_id ? absint( $post_id ) : get_the_ID();
if ( ! $post_id ) {
return 0;
}
$content = get_post_field( 'post_content', $post_id );
$content = wp_strip_all_tags( strip_shortcodes( $content ) );
return str_word_count( $content );
}
}
/**
* Get reading time.
*/
if ( ! function_exists( 'rx_get_reading_time' ) ) {
function rx_get_reading_time( $post_id = null, $words_per_minute = 200 ) {
$word_count = rx_get_word_count( $post_id );
$minutes = ceil( $word_count / absint( $words_per_minute ) );
return max( 1, $minutes );
}
}
/**
* Print reading time.
*/
if ( ! function_exists( 'rx_reading_time' ) ) {
function rx_reading_time( $post_id = null ) {
$minutes = rx_get_reading_time( $post_id );
echo '<span class="rx-reading-time">';
echo esc_html(
sprintf(
_n( '%s minute read', '%s minutes read', $minutes, 'rx-theme' ),
number_format_i18n( $minutes )
)
);
echo '</span>';
}
}
/**
* Print word count.
*/
if ( ! function_exists( 'rx_word_count' ) ) {
function rx_word_count( $post_id = null ) {
$count = rx_get_word_count( $post_id );
echo '<span class="rx-word-count">';
echo esc_html(
sprintf(
_n( '%s word', '%s words', $count, 'rx-theme' ),
number_format_i18n( $count )
)
);
echo '</span>';
}
}
/**
* ------------------------------------------------------------
* 07. FEATURED IMAGE HELPERS
* ------------------------------------------------------------
*/
/**
* Get fallback image URL.
*/
if ( ! function_exists( 'rx_get_fallback_image_url' ) ) {
function rx_get_fallback_image_url() {
$fallback = rx_theme_uri( 'assets/images/fallback.jpg' );
return apply_filters( 'rx_fallback_image_url', $fallback );
}
}
/**
* Get post thumbnail URL with fallback.
*/
if ( ! function_exists( 'rx_get_thumbnail_url' ) ) {
function rx_get_thumbnail_url( $post_id = null, $size = 'large' ) {
$post_id = $post_id ? absint( $post_id ) : get_the_ID();
if ( has_post_thumbnail( $post_id ) ) {
return get_the_post_thumbnail_url( $post_id, $size );
}
return rx_get_fallback_image_url();
}
}
/**
* Display post thumbnail with lazy loading.
*/
if ( ! function_exists( 'rx_post_thumbnail' ) ) {
function rx_post_thumbnail( $size = 'large', $class = 'rx-post-thumbnail' ) {
if ( post_password_required() || is_attachment() ) {
return;
}
$class = esc_attr( $class );
echo '<div class="' . $class . '">';
if ( is_singular() ) {
if ( has_post_thumbnail() ) {
the_post_thumbnail(
$size,
array(
'class' => 'rx-featured-image',
'loading' => 'eager',
'decoding' => 'async',
)
);
}
} else {
echo '<a href="' . esc_url( get_permalink() ) . '" aria-hidden="true" tabindex="-1">';
if ( has_post_thumbnail() ) {
the_post_thumbnail(
$size,
array(
'class' => 'rx-featured-image',
'loading' => 'lazy',
'decoding' => 'async',
)
);
} else {
echo '<img class="rx-featured-image rx-fallback-image" src="' . esc_url( rx_get_fallback_image_url() ) . '" alt="' . esc_attr( get_the_title() ) . '" loading="lazy" decoding="async">';
}
echo '</a>';
}
echo '</div>';
}
}
/**
* ------------------------------------------------------------
* 08. TITLE HELPERS
* ------------------------------------------------------------
*/
/**
* Archive title cleanup.
*/
if ( ! function_exists( 'rx_archive_title' ) ) {
function rx_archive_title( $title ) {
if ( is_category() ) {
$title = single_cat_title( '', false );
} elseif ( is_tag() ) {
$title = single_tag_title( '', false );
} elseif ( is_author() ) {
$title = get_the_author();
} elseif ( is_post_type_archive() ) {
$title = post_type_archive_title( '', false );
} elseif ( is_tax() ) {
$title = single_term_title( '', false );
}
return $title;
}
}
add_filter( 'get_the_archive_title', 'rx_archive_title' );
/**
* Page header title.
*/
if ( ! function_exists( 'rx_page_title' ) ) {
function rx_page_title() {
if ( is_home() && ! is_front_page() ) {
echo esc_html( single_post_title( '', false ) );
} elseif ( is_front_page() ) {
echo esc_html( get_bloginfo( 'name' ) );
} elseif ( is_archive() ) {
the_archive_title();
} elseif ( is_search() ) {
printf(
esc_html__( 'Search Results for: %s', 'rx-theme' ),
'<span>' . esc_html( get_search_query() ) . '</span>'
);
} elseif ( is_404() ) {
esc_html_e( 'Page Not Found', 'rx-theme' );
} else {
the_title();
}
}
}
/**
* ------------------------------------------------------------
* 09. BREADCRUMBS
* ------------------------------------------------------------
*/
/**
* Display breadcrumbs.
*/
if ( ! function_exists( 'rx_breadcrumbs' ) ) {
function rx_breadcrumbs() {
if ( is_front_page() ) {
return;
}
echo '<nav class="rx-breadcrumbs" aria-label="' . esc_attr__( 'Breadcrumb', 'rx-theme' ) . '">';
echo '<ol class="rx-breadcrumb-list">';
echo '<li class="rx-breadcrumb-item">';
echo '<a href="' . esc_url( home_url( '/' ) ) . '">' . esc_html__( 'Home', 'rx-theme' ) . '</a>';
echo '</li>';
if ( is_home() ) {
echo '<li class="rx-breadcrumb-item current">' . esc_html__( 'Blog', 'rx-theme' ) . '</li>';
} elseif ( is_category() || is_tag() || is_tax() ) {
$term = get_queried_object();
if ( $term && ! is_wp_error( $term ) ) {
if ( ! empty( $term->parent ) ) {
$parents = get_ancestors( $term->term_id, $term->taxonomy );
if ( ! empty( $parents ) ) {
$parents = array_reverse( $parents );
foreach ( $parents as $parent_id ) {
$parent = get_term( $parent_id, $term->taxonomy );
if ( $parent && ! is_wp_error( $parent ) ) {
echo '<li class="rx-breadcrumb-item">';
echo '<a href="' . esc_url( get_term_link( $parent ) ) . '">' . esc_html( $parent->name ) . '</a>';
echo '</li>';
}
}
}
}
echo '<li class="rx-breadcrumb-item current">' . esc_html( $term->name ) . '</li>';
}
} elseif ( is_single() ) {
$categories = get_the_category();
if ( ! empty( $categories ) ) {
$category = $categories[0];
echo '<li class="rx-breadcrumb-item">';
echo '<a href="' . esc_url( get_category_link( $category->term_id ) ) . '">' . esc_html( $category->name ) . '</a>';
echo '</li>';
}
echo '<li class="rx-breadcrumb-item current">' . esc_html( get_the_title() ) . '</li>';
} elseif ( is_page() ) {
$post = get_post();
if ( $post && $post->post_parent ) {
$parents = array_reverse( get_post_ancestors( $post->ID ) );
foreach ( $parents as $parent_id ) {
echo '<li class="rx-breadcrumb-item">';
echo '<a href="' . esc_url( get_permalink( $parent_id ) ) . '">' . esc_html( get_the_title( $parent_id ) ) . '</a>';
echo '</li>';
}
}
echo '<li class="rx-breadcrumb-item current">' . esc_html( get_the_title() ) . '</li>';
} elseif ( is_search() ) {
echo '<li class="rx-breadcrumb-item current">' . esc_html__( 'Search', 'rx-theme' ) . '</li>';
} elseif ( is_404() ) {
echo '<li class="rx-breadcrumb-item current">' . esc_html__( '404', 'rx-theme' ) . '</li>';
} elseif ( is_author() ) {
echo '<li class="rx-breadcrumb-item current">' . esc_html( get_the_author() ) . '</li>';
} elseif ( is_date() ) {
echo '<li class="rx-breadcrumb-item current">' . esc_html( get_the_date() ) . '</li>';
}
echo '</ol>';
echo '</nav>';
}
}
/**
* ------------------------------------------------------------
* 10. PAGINATION
* ------------------------------------------------------------
*/
/**
* Numeric pagination.
*/
if ( ! function_exists( 'rx_pagination' ) ) {
function rx_pagination( $query = null ) {
global $wp_query;
$query = $query ? $query : $wp_query;
if ( ! $query || $query->max_num_pages <= 1 ) {
return;
}
$big = 999999999;
$links = paginate_links(
array(
'base' => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ),
'format' => '?paged=%#%',
'current' => max( 1, get_query_var( 'paged' ) ),
'total' => $query->max_num_pages,
'type' => 'list',
'prev_text' => esc_html__( 'Previous', 'rx-theme' ),
'next_text' => esc_html__( 'Next', 'rx-theme' ),
)
);
if ( $links ) {
echo '<nav class="rx-pagination" aria-label="' . esc_attr__( 'Posts pagination', 'rx-theme' ) . '">';
echo wp_kses_post( $links );
echo '</nav>';
}
}
}
/**
* Previous and next post navigation.
*/
if ( ! function_exists( 'rx_post_navigation' ) ) {
function rx_post_navigation() {
if ( ! is_single() ) {
return;
}
the_post_navigation(
array(
'prev_text' => '<span class="nav-subtitle">' . esc_html__( 'Previous:', 'rx-theme' ) . '</span> <span class="nav-title">%title</span>',
'next_text' => '<span class="nav-subtitle">' . esc_html__( 'Next:', 'rx-theme' ) . '</span> <span class="nav-title">%title</span>',
)
);
}
}
/**
* ------------------------------------------------------------
* 11. RELATED POSTS
* ------------------------------------------------------------
*/
/**
* Get related posts.
*/
if ( ! function_exists( 'rx_get_related_posts' ) ) {
function rx_get_related_posts( $post_id = null, $limit = 3 ) {
$post_id = $post_id ? absint( $post_id ) : get_the_ID();
if ( ! $post_id ) {
return false;
}
$categories = wp_get_post_categories( $post_id );
if ( empty( $categories ) ) {
return false;
}
$args = array(
'post_type' => 'post',
'post_status' => 'publish',
'posts_per_page' => absint( $limit ),
'post__not_in' => array( $post_id ),
'ignore_sticky_posts' => true,
'category__in' => $categories,
'no_found_rows' => true,
);
return new WP_Query( $args );
}
}
/**
* Display related posts.
*/
if ( ! function_exists( 'rx_related_posts' ) ) {
function rx_related_posts( $post_id = null, $limit = 3 ) {
$related = rx_get_related_posts( $post_id, $limit );
if ( ! $related || ! $related->have_posts() ) {
return;
}
echo '<section class="rx-related-posts">';
echo '<h2 class="rx-related-title">' . esc_html__( 'Related Posts', 'rx-theme' ) . '</h2>';
echo '<div class="rx-related-grid">';
while ( $related->have_posts() ) {
$related->the_post();
echo '<article class="rx-related-card">';
echo '<a href="' . esc_url( get_permalink() ) . '" class="rx-related-link">';
if ( has_post_thumbnail() ) {
the_post_thumbnail(
'medium',
array(
'class' => 'rx-related-image',
'loading' => 'lazy',
'decoding' => 'async',
)
);
}
echo '<h3 class="rx-related-post-title">' . esc_html( get_the_title() ) . '</h3>';
echo '</a>';
echo '</article>';
}
echo '</div>';
echo '</section>';
wp_reset_postdata();
}
}
/**
* ------------------------------------------------------------
* 12. AUTHOR BOX
* ------------------------------------------------------------
*/
/**
* Display author box.
*/
if ( ! function_exists( 'rx_author_box' ) ) {
function rx_author_box() {
if ( ! is_single() ) {
return;
}
$author_id = get_the_author_meta( 'ID' );
$description = get_the_author_meta( 'description', $author_id );
echo '<section class="rx-author-box">';
echo '<div class="rx-author-avatar">';
echo get_avatar( $author_id, 96 );
echo '</div>';
echo '<div class="rx-author-content">';
echo '<h2 class="rx-author-title">';
echo esc_html__( 'About ', 'rx-theme' ) . esc_html( get_the_author_meta( 'display_name', $author_id ) );
echo '</h2>';
if ( $description ) {
echo '<p class="rx-author-description">' . esc_html( $description ) . '</p>';
}
echo '<a class="rx-author-posts-link" href="' . esc_url( get_author_posts_url( $author_id ) ) . '">';
echo esc_html__( 'View all posts', 'rx-theme' );
echo '</a>';
echo '</div>';
echo '</section>';
}
}
/**
* ------------------------------------------------------------
* 13. SEARCH FORM
* ------------------------------------------------------------
*/
/**
* Custom search form.
*/
if ( ! function_exists( 'rx_search_form' ) ) {
function rx_search_form( $form ) {
$form = '
<form role="search" method="get" class="rx-search-form search-form" action="' . esc_url( home_url( '/' ) ) . '">
<label class="screen-reader-text" for="rx-search-field">' . esc_html__( 'Search for:', 'rx-theme' ) . '</label>
<input type="search" id="rx-search-field" class="rx-search-field search-field" placeholder="' . esc_attr__( 'Search...', 'rx-theme' ) . '" value="' . esc_attr( get_search_query() ) . '" name="s">
<button type="submit" class="rx-search-submit search-submit">
<span class="screen-reader-text">' . esc_html__( 'Search', 'rx-theme' ) . '</span>
<svg width="20" height="20" viewBox="0 0 24 24" aria-hidden="true"><path d="M21 20l-5.2-5.2a7 7 0 10-1.4 1.4L20 21zM5 10a5 5 0 1110 0A5 5 0 015 10z" fill="currentColor"/></svg>
</button>
</form>';
return $form;
}
}
add_filter( 'get_search_form', 'rx_search_form' );
/**
* ------------------------------------------------------------
* 14. COMMENT HELPERS
* ------------------------------------------------------------
*/
/**
* Custom comment callback.
*/
if ( ! function_exists( 'rx_comment_callback' ) ) {
function rx_comment_callback( $comment, $args, $depth ) {
$GLOBALS['comment'] = $comment;
?>
<li <?php comment_class( 'rx-comment' ); ?> id="comment-<?php comment_ID(); ?>">
<article id="div-comment-<?php comment_ID(); ?>" class="comment-body rx-comment-body">
<footer class="comment-meta rx-comment-meta">
<div class="comment-author vcard rx-comment-author">
<?php echo get_avatar( $comment, 60 ); ?>
<?php
printf(
'<b class="fn">%s</b>',
get_comment_author_link()
);
?>
</div>
<div class="comment-metadata rx-comment-date">
<a href="<?php echo esc_url( get_comment_link( $comment->comment_ID ) ); ?>">
<time datetime="<?php comment_time( 'c' ); ?>">
<?php
printf(
esc_html__( '%1$s at %2$s', 'rx-theme' ),
esc_html( get_comment_date() ),
esc_html( get_comment_time() )
);
?>
</time>
</a>
</div>
</footer>
<div class="comment-content rx-comment-content">
<?php comment_text(); ?>
</div>
<div class="reply rx-comment-reply">
<?php
comment_reply_link(
array_merge(
$args,
array(
'add_below' => 'div-comment',
'depth' => $depth,
'max_depth' => $args['max_depth'],
)
)
);
?>
</div>
</article>
</li>
<?php
}
}
/**
* ------------------------------------------------------------
* 15. SCHEMA HELPERS
* ------------------------------------------------------------
*/
/**
* Get basic organization schema.
*/
if ( ! function_exists( 'rx_get_organization_schema' ) ) {
function rx_get_organization_schema() {
$schema = array(
'@context' => 'https://schema.org',
'@type' => 'Organization',
'name' => get_bloginfo( 'name' ),
'url' => home_url( '/' ),
);
$custom_logo_id = get_theme_mod( 'custom_logo' );
if ( $custom_logo_id ) {
$logo = wp_get_attachment_image_url( $custom_logo_id, 'full' );
if ( $logo ) {
$schema['logo'] = esc_url_raw( $logo );
}
}
return apply_filters( 'rx_organization_schema', $schema );
}
}
/**
* Get article schema.
*/
if ( ! function_exists( 'rx_get_article_schema' ) ) {
function rx_get_article_schema( $post_id = null ) {
$post_id = $post_id ? absint( $post_id ) : get_the_ID();
if ( ! $post_id ) {
return array();
}
$schema = array(
'@context' => 'https://schema.org',
'@type' => 'Article',
'headline' => get_the_title( $post_id ),
'description' => rx_get_excerpt( $post_id, 30 ),
'datePublished' => get_the_date( DATE_W3C, $post_id ),
'dateModified' => get_the_modified_date( DATE_W3C, $post_id ),
'mainEntityOfPage' => get_permalink( $post_id ),
'author' => array(
'@type' => 'Person',
'name' => get_the_author_meta( 'display_name', get_post_field( 'post_author', $post_id ) ),
),
'publisher' => rx_get_organization_schema(),
);
if ( has_post_thumbnail( $post_id ) ) {
$image = get_the_post_thumbnail_url( $post_id, 'full' );
if ( $image ) {
$schema['image'] = array( esc_url_raw( $image ) );
}
}
return apply_filters( 'rx_article_schema', $schema, $post_id );
}
}
/**
* Print JSON-LD schema.
*/
if ( ! function_exists( 'rx_print_schema' ) ) {
function rx_print_schema() {
if ( is_single() ) {
$schema = rx_get_article_schema();
} else {
$schema = rx_get_organization_schema();
}
if ( empty( $schema ) ) {
return;
}
echo '<script type="application/ld+json">' . wp_json_encode( $schema, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE ) . '</script>' . "\n";
}
}
add_action( 'wp_head', 'rx_print_schema', 30 );
/**
* ------------------------------------------------------------
* 16. SEO META FALLBACK HELPERS
* ------------------------------------------------------------
*/
/**
* Meta description fallback.
*/
if ( ! function_exists( 'rx_meta_description' ) ) {
function rx_meta_description() {
if ( is_singular() ) {
$description = rx_get_excerpt( get_the_ID(), 30 );
} elseif ( is_category() || is_tag() || is_tax() ) {
$description = term_description();
$description = wp_strip_all_tags( $description );
} elseif ( is_search() ) {
$description = sprintf(
esc_html__( 'Search results for %s', 'rx-theme' ),
get_search_query()
);
} else {
$description = get_bloginfo( 'description' );
}
$description = wp_strip_all_tags( $description );
$description = trim( $description );
if ( empty( $description ) ) {
return;
}
echo '<meta name="description" content="' . esc_attr( wp_trim_words( $description, 30, '' ) ) . '">' . "\n";
}
}
/**
* Only add fallback meta description when common SEO plugins are not active.
*/
if ( ! function_exists( 'rx_maybe_add_meta_description' ) ) {
function rx_maybe_add_meta_description() {
if (
defined( 'WPSEO_VERSION' ) ||
defined( 'RANK_MATH_VERSION' ) ||
defined( 'AIOSEO_VERSION' )
) {
return;
}
rx_meta_description();
}
}
add_action( 'wp_head', 'rx_maybe_add_meta_description', 5 );
/**
* Canonical URL fallback.
*/
if ( ! function_exists( 'rx_canonical_url' ) ) {
function rx_canonical_url() {
if (
defined( 'WPSEO_VERSION' ) ||
defined( 'RANK_MATH_VERSION' ) ||
defined( 'AIOSEO_VERSION' )
) {
return;
}
if ( is_singular() ) {
$url = get_permalink();
} elseif ( is_home() || is_front_page() ) {
$url = home_url( '/' );
} elseif ( is_archive() || is_search() ) {
$url = get_pagenum_link();
} else {
return;
}
echo '<link rel="canonical" href="' . esc_url( $url ) . '">' . "\n";
}
}
add_action( 'wp_head', 'rx_canonical_url', 6 );
/**
* ------------------------------------------------------------
* 17. OPEN GRAPH FALLBACK
* ------------------------------------------------------------
*/
/**
* Basic Open Graph tags.
*/
if ( ! function_exists( 'rx_open_graph_tags' ) ) {
function rx_open_graph_tags() {
if (
defined( 'WPSEO_VERSION' ) ||
defined( 'RANK_MATH_VERSION' ) ||
defined( 'AIOSEO_VERSION' )
) {
return;
}
$title = wp_get_document_title();
$url = is_singular() ? get_permalink() : home_url( add_query_arg( null, null ) );
$description = is_singular() ? rx_get_excerpt( get_the_ID(), 30 ) : get_bloginfo( 'description' );
$image = is_singular() ? rx_get_thumbnail_url( get_the_ID(), 'large' ) : rx_get_fallback_image_url();
$type = is_singular() ? 'article' : 'website';
echo '<meta property="og:title" content="' . esc_attr( $title ) . '">' . "\n";
echo '<meta property="og:description" content="' . esc_attr( $description ) . '">' . "\n";
echo '<meta property="og:url" content="' . esc_url( $url ) . '">' . "\n";
echo '<meta property="og:image" content="' . esc_url( $image ) . '">' . "\n";
echo '<meta property="og:type" content="' . esc_attr( $type ) . '">' . "\n";
echo '<meta property="og:site_name" content="' . esc_attr( get_bloginfo( 'name' ) ) . '">' . "\n";
echo '<meta name="twitter:card" content="summary_large_image">' . "\n";
}
}
add_action( 'wp_head', 'rx_open_graph_tags', 7 );
/**
* ------------------------------------------------------------
* 18. PERFORMANCE HELPERS
* ------------------------------------------------------------
*/
/**
* Add decoding async to post thumbnails.
*/
if ( ! function_exists( 'rx_image_attributes' ) ) {
function rx_image_attributes( $attr ) {
if ( empty( $attr['loading'] ) ) {
$attr['loading'] = 'lazy';
}
if ( empty( $attr['decoding'] ) ) {
$attr['decoding'] = 'async';
}
return $attr;
}
}
add_filter( 'wp_get_attachment_image_attributes', 'rx_image_attributes' );
/**
* Preload featured image on single post/page.
*/
if ( ! function_exists( 'rx_preload_featured_image' ) ) {
function rx_preload_featured_image() {
if ( ! is_singular() || ! has_post_thumbnail() ) {
return;
}
$image = get_the_post_thumbnail_url( get_the_ID(), 'large' );
if ( ! $image ) {
return;
}
echo '<link rel="preload" as="image" href="' . esc_url( $image ) . '">' . "\n";
}
}
add_action( 'wp_head', 'rx_preload_featured_image', 1 );
/**
* Add resource hints.
*/
if ( ! function_exists( 'rx_resource_hints' ) ) {
function rx_resource_hints( $urls, $relation_type ) {
if ( 'preconnect' === $relation_type ) {
$urls[] = array(
'href' => 'https://fonts.gstatic.com',
'crossorigin' => 'anonymous',
);
}
if ( 'dns-prefetch' === $relation_type ) {
$urls[] = '//fonts.googleapis.com';
$urls[] = '//fonts.gstatic.com';
$urls[] = '//www.google-analytics.com';
$urls[] = '//www.googletagmanager.com';
}
return $urls;
}
}
add_filter( 'wp_resource_hints', 'rx_resource_hints', 10, 2 );
/**
* ------------------------------------------------------------
* 19. SOCIAL SHARE
* ------------------------------------------------------------
*/
/**
* Social share links.
*/
if ( ! function_exists( 'rx_social_share' ) ) {
function rx_social_share( $post_id = null ) {
$post_id = $post_id ? absint( $post_id ) : get_the_ID();
if ( ! $post_id ) {
return;
}
$url = rawurlencode( get_permalink( $post_id ) );
$title = rawurlencode( get_the_title( $post_id ) );
$links = array(
'facebook' => 'https://www.facebook.com/sharer/sharer.php?u=' . $url,
'twitter' => 'https://twitter.com/intent/tweet?url=' . $url . '&text=' . $title,
'linkedin' => 'https://www.linkedin.com/shareArticle?mini=true&url=' . $url . '&title=' . $title,
'whatsapp' => 'https://api.whatsapp.com/send?text=' . $title . '%20' . $url,
'telegram' => 'https://t.me/share/url?url=' . $url . '&text=' . $title,
);
echo '<div class="rx-social-share">';
echo '<span class="rx-social-share-title">' . esc_html__( 'Share:', 'rx-theme' ) . '</span>';
foreach ( $links as $network => $link ) {
echo '<a class="rx-share-link rx-share-' . esc_attr( $network ) . '" href="' . esc_url( $link ) . '" target="_blank" rel="noopener noreferrer">';
echo esc_html( ucfirst( $network ) );
echo '</a>';
}
echo '</div>';
}
}
/**
* ------------------------------------------------------------
* 20. TABLE OF CONTENTS
* ------------------------------------------------------------
*/
/**
* Generate simple table of contents from H2/H3 headings.
*/
if ( ! function_exists( 'rx_generate_toc' ) ) {
function rx_generate_toc( $content ) {
if ( ! is_singular() || empty( $content ) ) {
return $content;
}
if ( false === strpos( $content, '<h2' ) && false === strpos( $content, '<h3' ) ) {
return $content;
}
preg_match_all( '/<h([2-3])([^>]*)>(.*?)<\/h[2-3]>/i', $content, $matches, PREG_SET_ORDER );
if ( empty( $matches ) || count( $matches ) < 2 ) {
return $content;
}
$toc = '<nav class="rx-table-of-contents" aria-label="' . esc_attr__( 'Table of contents', 'rx-theme' ) . '">';
$toc .= '<h2 class="rx-toc-title">' . esc_html__( 'Table of Contents', 'rx-theme' ) . '</h2>';
$toc .= '<ol class="rx-toc-list">';
foreach ( $matches as $match ) {
$level = absint( $match[1] );
$text = wp_strip_all_tags( $match[3] );
$id = sanitize_title( $text );
if ( empty( $id ) ) {
continue;
}
$heading_old = $match[0];
if ( false === strpos( $heading_old, 'id=' ) ) {
$heading_new = '<h' . $level . $match[2] . ' id="' . esc_attr( $id ) . '">' . $match[3] . '</h' . $level . '>';
$content = str_replace( $heading_old, $heading_new, $content );
}
$toc .= '<li class="rx-toc-item rx-toc-level-' . esc_attr( $level ) . '">';
$toc .= '<a href="#' . esc_attr( $id ) . '">' . esc_html( $text ) . '</a>';
$toc .= '</li>';
}
$toc .= '</ol>';
$toc .= '</nav>';
$first_paragraph = strpos( $content, '</p>' );
if ( false !== $first_paragraph ) {
$content = substr_replace( $content, '</p>' . $toc, $first_paragraph, 4 );
} else {
$content = $toc . $content;
}
return $content;
}
}
/**
* Enable TOC only when post meta is not disabled.
*/
if ( ! function_exists( 'rx_maybe_add_toc' ) ) {
function rx_maybe_add_toc( $content ) {
if ( is_admin() || ! is_main_query() || ! in_the_loop() ) {
return $content;
}
$disable = get_post_meta( get_the_ID(), '_rx_disable_toc', true );
if ( 'yes' === $disable ) {
return $content;
}
return rx_generate_toc( $content );
}
}
add_filter( 'the_content', 'rx_maybe_add_toc', 20 );
/**
* ------------------------------------------------------------
* 21. CONTENT HELPERS
* ------------------------------------------------------------
*/
/**
* Add responsive wrapper around embeds.
*/
if ( ! function_exists( 'rx_responsive_embeds' ) ) {
function rx_responsive_embeds( $html ) {
if ( false !== strpos( $html, '<iframe' ) ) {
$html = '<div class="rx-responsive-embed">' . $html . '</div>';
}
return $html;
}
}
add_filter( 'embed_oembed_html', 'rx_responsive_embeds' );
add_filter( 'video_embed_html', 'rx_responsive_embeds' );
/**
* Add nofollow to external links in content.
*/
if ( ! function_exists( 'rx_external_links_attributes' ) ) {
function rx_external_links_attributes( $content ) {
if ( is_admin() || empty( $content ) ) {
return $content;
}
$home_host = wp_parse_url( home_url(), PHP_URL_HOST );
return preg_replace_callback(
'/<a\s+[^>]*href=["\']([^"\']+)["\'][^>]*>/i',
function ( $matches ) use ( $home_host ) {
$link = $matches[0];
$url = $matches[1];
$host = wp_parse_url( $url, PHP_URL_HOST );
if ( empty( $host ) || $host === $home_host ) {
return $link;
}
if ( false === strpos( $link, 'rel=' ) ) {
$link = str_replace( '<a ', '<a rel="nofollow noopener noreferrer" ', $link );
}
if ( false === strpos( $link, 'target=' ) ) {
$link = str_replace( '<a ', '<a target="_blank" ', $link );
}
return $link;
},
$content
);
}
}
add_filter( 'the_content', 'rx_external_links_attributes', 25 );
/**
* ------------------------------------------------------------
* 22. MENU HELPERS
* ------------------------------------------------------------
*/
/**
* Fallback menu.
*/
if ( ! function_exists( 'rx_fallback_menu' ) ) {
function rx_fallback_menu() {
echo '<ul class="rx-fallback-menu">';
echo '<li><a href="' . esc_url( home_url( '/' ) ) . '">' . esc_html__( 'Home', 'rx-theme' ) . '</a></li>';
wp_list_pages(
array(
'title_li' => '',
'depth' => 1,
)
);
echo '</ul>';
}
}
/**
* Primary menu.
*/
if ( ! function_exists( 'rx_primary_menu' ) ) {
function rx_primary_menu() {
wp_nav_menu(
array(
'theme_location' => 'primary',
'menu_id' => 'primary-menu',
'menu_class' => 'rx-primary-menu',
'container' => 'nav',
'container_id' => 'site-navigation',
'container_class'=> 'main-navigation rx-main-navigation',
'fallback_cb' => 'rx_fallback_menu',
)
);
}
}
/**
* Footer menu.
*/
if ( ! function_exists( 'rx_footer_menu' ) ) {
function rx_footer_menu() {
if ( ! has_nav_menu( 'footer' ) ) {
return;
}
wp_nav_menu(
array(
'theme_location' => 'footer',
'menu_id' => 'footer-menu',
'menu_class' => 'rx-footer-menu',
'container' => 'nav',
'container_class'=> 'rx-footer-navigation',
'depth' => 1,
)
);
}
}
/**
* ------------------------------------------------------------
* 23. HEADER AND FOOTER HELPERS
* ------------------------------------------------------------
*/
/**
* Site branding.
*/
if ( ! function_exists( 'rx_site_branding' ) ) {
function rx_site_branding() {
echo '<div class="site-branding rx-site-branding">';
if ( has_custom_logo() ) {
the_custom_logo();
}
if ( is_front_page() && is_home() ) {
echo '<h1 class="site-title rx-site-title">';
echo '<a href="' . esc_url( home_url( '/' ) ) . '" rel="home">' . esc_html( get_bloginfo( 'name' ) ) . '</a>';
echo '</h1>';
} else {
echo '<p class="site-title rx-site-title">';
echo '<a href="' . esc_url( home_url( '/' ) ) . '" rel="home">' . esc_html( get_bloginfo( 'name' ) ) . '</a>';
echo '</p>';
}
$description = get_bloginfo( 'description', 'display' );
if ( $description || is_customize_preview() ) {
echo '<p class="site-description rx-site-description">' . esc_html( $description ) . '</p>';
}
echo '</div>';
}
}
/**
* Copyright text.
*/
if ( ! function_exists( 'rx_copyright' ) ) {
function rx_copyright() {
echo '<div class="rx-copyright">';
echo esc_html( sprintf( __( '© %1$s %2$s. All rights reserved.', 'rx-theme' ), date_i18n( 'Y' ), get_bloginfo( 'name' ) ) );
echo '</div>';
}
}
/**
* Back to top button.
*/
if ( ! function_exists( 'rx_back_to_top' ) ) {
function rx_back_to_top() {
echo '<button class="rx-back-to-top" type="button" aria-label="' . esc_attr__( 'Back to top', 'rx-theme' ) . '">';
echo '↑';
echo '</button>';
}
}
add_action( 'wp_footer', 'rx_back_to_top', 20 );
/**
* ------------------------------------------------------------
* 24. ARCHIVE HELPERS
* ------------------------------------------------------------
*/
/**
* Archive description.
*/
if ( ! function_exists( 'rx_archive_description' ) ) {
function rx_archive_description() {
if ( is_archive() ) {
$description = get_the_archive_description();
if ( $description ) {
echo '<div class="archive-description rx-archive-description">';
echo wp_kses_post( wpautop( $description ) );
echo '</div>';
}
}
}
}
/**
* No results template helper.
*/
if ( ! function_exists( 'rx_no_results' ) ) {
function rx_no_results() {
echo '<section class="no-results not-found rx-no-results">';
echo '<header class="page-header">';
echo '<h1 class="page-title">' . esc_html__( 'Nothing Found', 'rx-theme' ) . '</h1>';
echo '</header>';
echo '<div class="page-content">';
if ( is_home() && current_user_can( 'publish_posts' ) ) {
printf(
wp_kses(
__( '<p>Ready to publish your first post? <a href="%1$s">Get started here</a>.</p>', 'rx-theme' ),
array(
'p' => array(),
'a' => array(
'href' => array(),
),
)
),
esc_url( admin_url( 'post-new.php' ) )
);
} elseif ( is_search() ) {
echo '<p>' . esc_html__( 'Sorry, nothing matched your search. Please try again with different keywords.', 'rx-theme' ) . '</p>';
get_search_form();
} else {
echo '<p>' . esc_html__( 'It seems we cannot find what you are looking for. Maybe search can help.', 'rx-theme' ) . '</p>';
get_search_form();
}
echo '</div>';
echo '</section>';
}
}
/**
* ------------------------------------------------------------
* 25. POST VIEWS
* ------------------------------------------------------------
*/
/**
* Count post views.
*/
if ( ! function_exists( 'rx_track_post_views' ) ) {
function rx_track_post_views() {
if ( ! is_single() ) {
return;
}
global $post;
if ( empty( $post->ID ) ) {
return;
}
$key = '_rx_post_views';
$count = get_post_meta( $post->ID, $key, true );
$count = $count ? absint( $count ) : 0;
update_post_meta( $post->ID, $key, $count + 1 );
}
}
add_action( 'wp_head', 'rx_track_post_views' );
/**
* Get post views.
*/
if ( ! function_exists( 'rx_get_post_views' ) ) {
function rx_get_post_views( $post_id = null ) {
$post_id = $post_id ? absint( $post_id ) : get_the_ID();
$count = get_post_meta( $post_id, '_rx_post_views', true );
return $count ? absint( $count ) : 0;
}
}
/**
* Print post views.
*/
if ( ! function_exists( 'rx_post_views' ) ) {
function rx_post_views( $post_id = null ) {
$count = rx_get_post_views( $post_id );
echo '<span class="rx-post-views">';
echo esc_html(
sprintf(
_n( '%s view', '%s views', $count, 'rx-theme' ),
number_format_i18n( $count )
)
);
echo '</span>';
}
}
/**
* ------------------------------------------------------------
* 26. CUSTOMIZER HELPER VALUES
* ------------------------------------------------------------
*/
/**
* Get theme option from customizer.
*/
if ( ! function_exists( 'rx_get_option' ) ) {
function rx_get_option( $key, $default = '' ) {
$value = get_theme_mod( $key, $default );
return apply_filters( 'rx_get_option', $value, $key, $default );
}
}
/**
* Print inline CSS variable from customizer.
*/
if ( ! function_exists( 'rx_css_variable' ) ) {
function rx_css_variable( $name, $value ) {
if ( empty( $name ) || empty( $value ) ) {
return;
}
echo esc_html( '--' . sanitize_key( $name ) . ':' . sanitize_text_field( $value ) . ';' );
}
}
/**
* Output dynamic CSS variables.
*/
if ( ! function_exists( 'rx_dynamic_css_variables' ) ) {
function rx_dynamic_css_variables() {
$primary_color = rx_get_option( 'rx_primary_color', '#0d6efd' );
$body_bg = rx_get_option( 'rx_body_background', '#ffffff' );
$text_color = rx_get_option( 'rx_text_color', '#222222' );
echo '<style id="rx-dynamic-css">';
echo ':root{';
rx_css_variable( 'rx-primary-color', $primary_color );
rx_css_variable( 'rx-body-bg', $body_bg );
rx_css_variable( 'rx-text-color', $text_color );
echo '}';
echo '</style>';
}
}
add_action( 'wp_head', 'rx_dynamic_css_variables', 20 );
/**
* ------------------------------------------------------------
* 27. SECURITY AND CLEAN OUTPUT HELPERS
* ------------------------------------------------------------
*/
/**
* Remove WordPress version from head.
*/
remove_action( 'wp_head', 'wp_generator' );
/**
* Remove version query from static files.
*/
if ( ! function_exists( 'rx_remove_asset_version_query' ) ) {
function rx_remove_asset_version_query( $src ) {
if ( is_admin() ) {
return $src;
}
if ( strpos( $src, 'ver=' ) ) {
$src = remove_query_arg( 'ver', $src );
}
return $src;
}
}
/**
* Optional: enable this only if you really want no ?ver on CSS/JS.
*/
// add_filter( 'style_loader_src', 'rx_remove_asset_version_query', 15 );
// add_filter( 'script_loader_src', 'rx_remove_asset_version_query', 15 );
/**
* Sanitize HTML class.
*/
if ( ! function_exists( 'rx_sanitize_html_classes' ) ) {
function rx_sanitize_html_classes( $classes ) {
if ( is_array( $classes ) ) {
$classes = array_map( 'sanitize_html_class', $classes );
return implode( ' ', $classes );
}
return sanitize_html_class( $classes );
}
}
/**
* ------------------------------------------------------------
* 28. WOOCOMMERCE HELPERS
* ------------------------------------------------------------
*/
if ( rx_is_woocommerce_active() ) {
/**
* WooCommerce wrapper start.
*/
if ( ! function_exists( 'rx_woocommerce_wrapper_start' ) ) {
function rx_woocommerce_wrapper_start() {
echo '<main id="primary" class="site-main rx-woocommerce-main">';
}
}
/**
* WooCommerce wrapper end.
*/
if ( ! function_exists( 'rx_woocommerce_wrapper_end' ) ) {
function rx_woocommerce_wrapper_end() {
echo '</main>';
}
}
remove_action( 'woocommerce_before_main_content', 'woocommerce_output_content_wrapper', 10 );
remove_action( 'woocommerce_after_main_content', 'woocommerce_output_content_wrapper_end', 10 );
add_action( 'woocommerce_before_main_content', 'rx_woocommerce_wrapper_start', 10 );
add_action( 'woocommerce_after_main_content', 'rx_woocommerce_wrapper_end', 10 );
}
/**
* ------------------------------------------------------------
* 29. ADMIN BAR HELPER
* ------------------------------------------------------------
*/
/**
* Add RX quick link in admin bar.
*/
if ( ! function_exists( 'rx_admin_bar_links' ) ) {
function rx_admin_bar_links( $wp_admin_bar ) {
if ( ! current_user_can( 'edit_theme_options' ) ) {
return;
}
$wp_admin_bar->add_node(
array(
'id' => 'rx-theme-options',
'title' => esc_html__( 'RX Theme', 'rx-theme' ),
'href' => esc_url( admin_url( 'customize.php' ) ),
'meta' => array(
'title' => esc_html__( 'Customize RX Theme', 'rx-theme' ),
),
)
);
}
}
add_action( 'admin_bar_menu', 'rx_admin_bar_links', 100 );
/**
* ------------------------------------------------------------
* 30. TEMPLATE PART LOADER
* ------------------------------------------------------------
*/
/**
* Safe template part loader with arguments.
*/
if ( ! function_exists( 'rx_get_template_part' ) ) {
function rx_get_template_part( $slug, $name = null, $args = array() ) {
if ( ! empty( $args ) && is_array( $args ) ) {
set_query_var( 'rx_template_args', $args );
}
get_template_part( $slug, $name );
}
}
/**
* Get argument inside template part.
*/
if ( ! function_exists( 'rx_template_arg' ) ) {
function rx_template_arg( $key, $default = null ) {
$args = get_query_var( 'rx_template_args', array() );
if ( isset( $args[ $key ] ) ) {
return $args[ $key ];
}
return $default;
}
}
/**
* ------------------------------------------------------------
* 31. DEBUG HELPER
* ------------------------------------------------------------
*/
/**
* Safe debug print for development only.
*/
if ( ! function_exists( 'rx_debug' ) ) {
function rx_debug( $data ) {
if ( ! defined( 'WP_DEBUG' ) || ! WP_DEBUG || ! current_user_can( 'manage_options' ) ) {
return;
}
echo '<pre class="rx-debug">';
print_r( $data ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
echo '</pre>';
}
}
You can now use these functions in your theme files like:
<?php rx_site_branding(); ?>
<?php rx_primary_menu(); ?>
<?php rx_breadcrumbs(); ?>
<?php rx_entry_meta(); ?>
<?php rx_post_thumbnail(); ?>
<?php rx_the_excerpt(35); ?>
<?php rx_read_more_button(); ?>
<?php rx_entry_footer(); ?>
<?php rx_author_box(); ?>
<?php rx_related_posts(); ?>
<?php rx_post_navigation(); ?>
<?php rx_pagination(); ?>
<?php rx_copyright(); ?>
Best structure:
rx-theme/
├── functions.php
├── inc/
│ ├── helpers/
│ │ ├── template-functions.php
│ │ ├── breadcrumbs.php
│ │ ├── reading-time.php
│ │ ├── related-posts.php
│ │ ├── pagination.php
│ │ └── schema.php
Since this template-functions.php already includes breadcrumbs, reading time, related posts, pagination, and schema helpers, do not duplicate the same function names in separate helper files unless you split the file later.