theme-setup.php file for your RX theme, focused on theme supports, menus, image sizes, editor setup, performance-safe defaults, accessibility, WooCommerce support, and admin/editor enhancements without duplicating enqueue/SEO files.
Yes friend — in your RX theme, theme-setup.php can include core theme initialization: theme supports, menus, image sizes, editor setup, accessibility, WooCommerce compatibility, content width, starter content, body classes, excerpt defaults, upload MIME support, admin/editor polish, and safe performance defaults.
Create this file:
rx-theme/inc/core/theme-setup.php
<?php
/**
* RX Theme Setup
*
* Path: /inc/core/theme-setup.php
*
* This file contains the core setup for RX Theme:
* - Theme supports
* - Menus
* - Image sizes
* - Editor support
* - Accessibility
* - WooCommerce support
* - Performance-safe WordPress defaults
* - Body/post classes
* - Excerpt defaults
* - Upload MIME support
*
* @package RX_Theme
*/
defined( 'ABSPATH' ) || exit;
if ( ! defined( 'RX_THEME_VERSION' ) ) {
define( 'RX_THEME_VERSION', wp_get_theme()->get( 'Version' ) ?: '1.0.0' );
}
if ( ! defined( 'RX_THEME_TEXTDOMAIN' ) ) {
define( 'RX_THEME_TEXTDOMAIN', 'rx-theme' );
}
if ( ! defined( 'RX_THEME_DIR' ) ) {
define( 'RX_THEME_DIR', trailingslashit( get_template_directory() ) );
}
if ( ! defined( 'RX_THEME_URI' ) ) {
define( 'RX_THEME_URI', trailingslashit( get_template_directory_uri() ) );
}
/**
* Main theme setup.
*/
if ( ! function_exists( 'rx_theme_setup' ) ) {
function rx_theme_setup(): void {
/**
* Translation support.
*/
load_theme_textdomain(
RX_THEME_TEXTDOMAIN,
get_template_directory() . '/languages'
);
/**
* Let WordPress manage the document title.
*/
add_theme_support( 'title-tag' );
/**
* Enable featured images.
*/
add_theme_support( 'post-thumbnails' );
/**
* HTML5 markup support.
*/
add_theme_support(
'html5',
array(
'search-form',
'comment-form',
'comment-list',
'gallery',
'caption',
'style',
'script',
'navigation-widgets',
)
);
/**
* RSS feed links.
*/
add_theme_support( 'automatic-feed-links' );
/**
* Responsive embeds.
*/
add_theme_support( 'responsive-embeds' );
/**
* Wide and full alignment support.
*/
add_theme_support( 'align-wide' );
/**
* Block editor styles.
*/
add_theme_support( 'editor-styles' );
/**
* Load editor stylesheet.
* Create this file later:
* /assets/css/editor-style.css
*/
add_editor_style( 'assets/css/editor-style.css' );
/**
* Block editor custom line height.
*/
add_theme_support( 'custom-line-height' );
/**
* Block editor custom spacing.
*/
add_theme_support( 'custom-spacing' );
/**
* Block editor custom units.
*/
add_theme_support(
'custom-units',
array(
'px',
'em',
'rem',
'vh',
'vw',
'%',
)
);
/**
* Appearance tools for block editor.
*/
add_theme_support( 'appearance-tools' );
/**
* Link color support.
*/
add_theme_support( 'link-color' );
/**
* Border support.
*/
add_theme_support( 'border' );
/**
* Custom logo.
*/
add_theme_support(
'custom-logo',
array(
'height' => 120,
'width' => 360,
'flex-height' => true,
'flex-width' => true,
'unlink-homepage-logo' => true,
)
);
/**
* Custom header support.
*/
add_theme_support(
'custom-header',
array(
'default-image' => '',
'default-text-color' => '111827',
'width' => 1920,
'height' => 560,
'flex-width' => true,
'flex-height' => true,
'uploads' => true,
)
);
/**
* Custom background support.
*/
add_theme_support(
'custom-background',
array(
'default-color' => 'ffffff',
'default-image' => '',
'default-repeat' => 'no-repeat',
'default-position-x' => 'center',
'default-position-y' => 'top',
'default-size' => 'cover',
'default-attachment' => 'scroll',
)
);
/**
* Selective refresh for widgets in customizer.
*/
add_theme_support( 'customize-selective-refresh-widgets' );
/**
* Post formats.
*/
add_theme_support(
'post-formats',
array(
'aside',
'image',
'video',
'audio',
'quote',
'link',
'gallery',
'status',
'chat',
)
);
/**
* Core block patterns.
*/
add_theme_support( 'core-block-patterns' );
/**
* Navigation menus.
*/
register_nav_menus(
array(
'primary' => esc_html__( 'Primary Menu', RX_THEME_TEXTDOMAIN ),
'secondary' => esc_html__( 'Secondary Menu', RX_THEME_TEXTDOMAIN ),
'mobile' => esc_html__( 'Mobile Menu', RX_THEME_TEXTDOMAIN ),
'footer' => esc_html__( 'Footer Menu', RX_THEME_TEXTDOMAIN ),
'footer-legal' => esc_html__( 'Footer Legal Menu', RX_THEME_TEXTDOMAIN ),
'topbar' => esc_html__( 'Top Bar Menu', RX_THEME_TEXTDOMAIN ),
'social' => esc_html__( 'Social Links Menu', RX_THEME_TEXTDOMAIN ),
'category-menu' => esc_html__( 'Category Menu', RX_THEME_TEXTDOMAIN ),
'doctor-menu' => esc_html__( 'Doctor / Medical Menu', RX_THEME_TEXTDOMAIN ),
'utility-menu' => esc_html__( 'Utility Menu', RX_THEME_TEXTDOMAIN ),
'offcanvas-menu' => esc_html__( 'Off Canvas Menu', RX_THEME_TEXTDOMAIN ),
)
);
/**
* Image sizes.
*/
add_image_size( 'rx-thumb-small', 150, 150, true );
add_image_size( 'rx-thumb-medium', 300, 200, true );
add_image_size( 'rx-card', 420, 280, true );
add_image_size( 'rx-card-large', 640, 420, true );
add_image_size( 'rx-featured', 900, 520, true );
add_image_size( 'rx-featured-large', 1200, 675, true );
add_image_size( 'rx-hero', 1600, 720, true );
add_image_size( 'rx-hero-large', 1920, 900, true );
add_image_size( 'rx-square', 600, 600, true );
add_image_size( 'rx-portrait', 480, 720, true );
add_image_size( 'rx-og-image', 1200, 630, true );
/**
* WooCommerce support.
*/
add_theme_support( 'woocommerce' );
add_theme_support(
'wc-product-gallery-zoom'
);
add_theme_support(
'wc-product-gallery-lightbox'
);
add_theme_support(
'wc-product-gallery-slider'
);
/**
* WooCommerce product grid.
*/
add_theme_support(
'woocommerce',
array(
'thumbnail_image_width' => 420,
'single_image_width' => 700,
'product_grid' => array(
'default_rows' => 4,
'min_rows' => 2,
'max_rows' => 8,
'default_columns' => 3,
'min_columns' => 2,
'max_columns' => 5,
),
)
);
/**
* Block editor color palette.
*/
add_theme_support(
'editor-color-palette',
array(
array(
'name' => esc_html__( 'RX Primary', RX_THEME_TEXTDOMAIN ),
'slug' => 'rx-primary',
'color' => '#2563eb',
),
array(
'name' => esc_html__( 'RX Secondary', RX_THEME_TEXTDOMAIN ),
'slug' => 'rx-secondary',
'color' => '#0f172a',
),
array(
'name' => esc_html__( 'RX Accent', RX_THEME_TEXTDOMAIN ),
'slug' => 'rx-accent',
'color' => '#16a34a',
),
array(
'name' => esc_html__( 'RX Danger', RX_THEME_TEXTDOMAIN ),
'slug' => 'rx-danger',
'color' => '#dc2626',
),
array(
'name' => esc_html__( 'RX Warning', RX_THEME_TEXTDOMAIN ),
'slug' => 'rx-warning',
'color' => '#f59e0b',
),
array(
'name' => esc_html__( 'RX Light', RX_THEME_TEXTDOMAIN ),
'slug' => 'rx-light',
'color' => '#f8fafc',
),
array(
'name' => esc_html__( 'RX Dark', RX_THEME_TEXTDOMAIN ),
'slug' => 'rx-dark',
'color' => '#111827',
),
array(
'name' => esc_html__( 'RX Muted', RX_THEME_TEXTDOMAIN ),
'slug' => 'rx-muted',
'color' => '#64748b',
),
)
);
/**
* Block editor gradients.
*/
add_theme_support(
'editor-gradient-presets',
array(
array(
'name' => esc_html__( 'RX Blue Gradient', RX_THEME_TEXTDOMAIN ),
'gradient' => 'linear-gradient(135deg, #2563eb 0%, #1e40af 100%)',
'slug' => 'rx-blue-gradient',
),
array(
'name' => esc_html__( 'RX Green Gradient', RX_THEME_TEXTDOMAIN ),
'gradient' => 'linear-gradient(135deg, #16a34a 0%, #065f46 100%)',
'slug' => 'rx-green-gradient',
),
array(
'name' => esc_html__( 'RX Dark Gradient', RX_THEME_TEXTDOMAIN ),
'gradient' => 'linear-gradient(135deg, #111827 0%, #334155 100%)',
'slug' => 'rx-dark-gradient',
),
)
);
/**
* Editor font sizes.
*/
add_theme_support(
'editor-font-sizes',
array(
array(
'name' => esc_html__( 'Small', RX_THEME_TEXTDOMAIN ),
'size' => 14,
'slug' => 'small',
),
array(
'name' => esc_html__( 'Normal', RX_THEME_TEXTDOMAIN ),
'size' => 16,
'slug' => 'normal',
),
array(
'name' => esc_html__( 'Medium', RX_THEME_TEXTDOMAIN ),
'size' => 20,
'slug' => 'medium',
),
array(
'name' => esc_html__( 'Large', RX_THEME_TEXTDOMAIN ),
'size' => 28,
'slug' => 'large',
),
array(
'name' => esc_html__( 'Extra Large', RX_THEME_TEXTDOMAIN ),
'size' => 40,
'slug' => 'extra-large',
),
array(
'name' => esc_html__( 'Hero', RX_THEME_TEXTDOMAIN ),
'size' => 56,
'slug' => 'hero',
),
)
);
/**
* Starter content for new installs.
*/
add_theme_support(
'starter-content',
array(
'widgets' => array(
'sidebar-1' => array(
'search',
'recent-posts',
'categories',
),
),
'posts' => array(
'home',
'about',
'contact',
'blog',
),
'nav_menus' => array(
'primary' => array(
'name' => esc_html__( 'Primary Menu', RX_THEME_TEXTDOMAIN ),
'items' => array(
'link_home',
'page_about',
'page_blog',
'page_contact',
),
),
),
'options' => array(
'show_on_front' => 'page',
'page_on_front' => '{{home}}',
'page_for_posts' => '{{blog}}',
),
)
);
}
}
add_action( 'after_setup_theme', 'rx_theme_setup' );
/**
* Set content width.
*/
if ( ! function_exists( 'rx_theme_content_width' ) ) {
function rx_theme_content_width(): void {
$GLOBALS['content_width'] = apply_filters( 'rx_theme_content_width', 1200 );
}
}
add_action( 'after_setup_theme', 'rx_theme_content_width', 0 );
/**
* Add custom image sizes to Media Library dropdown.
*/
if ( ! function_exists( 'rx_theme_custom_image_size_names' ) ) {
function rx_theme_custom_image_size_names( array $sizes ): array {
return array_merge(
$sizes,
array(
'rx-thumb-small' => esc_html__( 'RX Small Thumbnail', RX_THEME_TEXTDOMAIN ),
'rx-thumb-medium' => esc_html__( 'RX Medium Thumbnail', RX_THEME_TEXTDOMAIN ),
'rx-card' => esc_html__( 'RX Card', RX_THEME_TEXTDOMAIN ),
'rx-card-large' => esc_html__( 'RX Large Card', RX_THEME_TEXTDOMAIN ),
'rx-featured' => esc_html__( 'RX Featured', RX_THEME_TEXTDOMAIN ),
'rx-featured-large' => esc_html__( 'RX Large Featured', RX_THEME_TEXTDOMAIN ),
'rx-hero' => esc_html__( 'RX Hero', RX_THEME_TEXTDOMAIN ),
'rx-hero-large' => esc_html__( 'RX Large Hero', RX_THEME_TEXTDOMAIN ),
'rx-square' => esc_html__( 'RX Square', RX_THEME_TEXTDOMAIN ),
'rx-portrait' => esc_html__( 'RX Portrait', RX_THEME_TEXTDOMAIN ),
'rx-og-image' => esc_html__( 'RX Open Graph Image', RX_THEME_TEXTDOMAIN ),
)
);
}
}
add_filter( 'image_size_names_choose', 'rx_theme_custom_image_size_names' );
/**
* Improve image output attributes.
*/
if ( ! function_exists( 'rx_theme_image_attributes' ) ) {
function rx_theme_image_attributes( array $attr, $attachment, $size ): array {
if ( empty( $attr['loading'] ) ) {
$attr['loading'] = 'lazy';
}
if ( empty( $attr['decoding'] ) ) {
$attr['decoding'] = 'async';
}
return $attr;
}
}
add_filter( 'wp_get_attachment_image_attributes', 'rx_theme_image_attributes', 10, 3 );
/**
* Do not lazy-load first important featured image on singular posts/pages.
*/
if ( ! function_exists( 'rx_theme_featured_image_loading_attr' ) ) {
function rx_theme_featured_image_loading_attr( $value, $image, $context ) {
if ( is_singular() && 'the_post_thumbnail' === $context ) {
return false;
}
return $value;
}
}
add_filter( 'wp_img_tag_add_loading_attr', 'rx_theme_featured_image_loading_attr', 10, 3 );
/**
* Add useful body classes.
*/
if ( ! function_exists( 'rx_theme_body_classes' ) ) {
function rx_theme_body_classes( array $classes ): array {
$classes[] = 'rx-theme';
$classes[] = 'rx-theme-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_archive() ) {
$classes[] = 'rx-archive';
}
if ( is_search() ) {
$classes[] = 'rx-search-page';
}
if ( is_404() ) {
$classes[] = 'rx-error-404';
}
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';
}
return array_unique( $classes );
}
}
add_filter( 'body_class', 'rx_theme_body_classes' );
/**
* Add useful post classes.
*/
if ( ! function_exists( 'rx_theme_post_classes' ) ) {
function rx_theme_post_classes( array $classes, array $class, int $post_id ): array {
if ( has_post_thumbnail( $post_id ) ) {
$classes[] = 'rx-has-post-thumbnail';
} else {
$classes[] = 'rx-no-post-thumbnail';
}
if ( is_sticky( $post_id ) ) {
$classes[] = 'rx-sticky-post';
}
$post_type = get_post_type( $post_id );
if ( $post_type ) {
$classes[] = 'rx-post-type-' . sanitize_html_class( $post_type );
}
return array_unique( $classes );
}
}
add_filter( 'post_class', 'rx_theme_post_classes', 10, 3 );
/**
* Excerpt length.
*/
if ( ! function_exists( 'rx_theme_excerpt_length' ) ) {
function rx_theme_excerpt_length( int $length ): int {
return (int) apply_filters( 'rx_theme_excerpt_length_value', 28 );
}
}
add_filter( 'excerpt_length', 'rx_theme_excerpt_length' );
/**
* Excerpt more text.
*/
if ( ! function_exists( 'rx_theme_excerpt_more' ) ) {
function rx_theme_excerpt_more( string $more ): string {
return '...';
}
}
add_filter( 'excerpt_more', 'rx_theme_excerpt_more' );
/**
* Add "Read More" link to manual and automatic excerpts.
*/
if ( ! function_exists( 'rx_theme_read_more_link' ) ) {
function rx_theme_read_more_link( string $excerpt ): string {
if ( is_admin() || ! is_main_query() ) {
return $excerpt;
}
if ( is_singular() ) {
return $excerpt;
}
$link = sprintf(
' <a class="rx-read-more" href="%1$s" aria-label="%2$s">%3$s</a>',
esc_url( get_permalink() ),
esc_attr(
sprintf(
/* translators: %s: post title */
__( 'Read more about %s', RX_THEME_TEXTDOMAIN ),
get_the_title()
)
),
esc_html__( 'Read More', RX_THEME_TEXTDOMAIN )
);
return $excerpt . $link;
}
}
add_filter( 'get_the_excerpt', 'rx_theme_read_more_link' );
/**
* Improve archive titles.
*/
if ( ! function_exists( 'rx_theme_archive_title' ) ) {
function rx_theme_archive_title( string $title ): string {
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_theme_archive_title' );
/**
* Add SVG and WebP upload support.
* SVG is allowed only for users with manage_options capability.
*/
if ( ! function_exists( 'rx_theme_upload_mimes' ) ) {
function rx_theme_upload_mimes( array $mimes ): array {
$mimes['webp'] = 'image/webp';
$mimes['avif'] = 'image/avif';
if ( current_user_can( 'manage_options' ) ) {
$mimes['svg'] = 'image/svg+xml';
}
return $mimes;
}
}
add_filter( 'upload_mimes', 'rx_theme_upload_mimes' );
/**
* Fix SVG preview in admin.
*/
if ( ! function_exists( 'rx_theme_fix_svg_admin_preview' ) ) {
function rx_theme_fix_svg_admin_preview(): void {
echo '<style>
.attachment-266x266, .thumbnail img {
width: 100%;
height: auto;
}
td.media-icon img[src$=".svg"],
img[src$=".svg"].attachment-post-thumbnail {
width: 100%;
height: auto;
}
</style>';
}
}
add_action( 'admin_head', 'rx_theme_fix_svg_admin_preview' );
/**
* Add async decoding to content images when possible.
*/
if ( ! function_exists( 'rx_theme_content_image_decoding' ) ) {
function rx_theme_content_image_decoding( string $content ): string {
if ( is_admin() || empty( $content ) ) {
return $content;
}
if ( false === strpos( $content, '<img' ) ) {
return $content;
}
$content = preg_replace(
'/<img(?![^>]*\bdecoding=)([^>]*)>/i',
'<img decoding="async"$1>',
$content
);
return $content ?: '';
}
}
add_filter( 'the_content', 'rx_theme_content_image_decoding', 15 );
/**
* Add loading lazy to content if missing.
*/
if ( ! function_exists( 'rx_theme_content_image_lazy_loading' ) ) {
function rx_theme_content_image_lazy_loading( string $content ): string {
if ( is_admin() || empty( $content ) ) {
return $content;
}
if ( false === strpos( $content, '<img' ) ) {
return $content;
}
$content = preg_replace(
'/<img(?![^>]*\bloading=)([^>]*)>/i',
'<img loading="lazy"$1>',
$content
);
return $content ?: '';
}
}
add_filter( 'the_content', 'rx_theme_content_image_lazy_loading', 16 );
/**
* Enable shortcodes in text widgets.
*/
add_filter( 'widget_text', 'do_shortcode' );
/**
* Enable shortcodes in excerpts.
*/
add_filter( 'the_excerpt', 'do_shortcode' );
/**
* Remove WordPress generator meta.
*/
remove_action( 'wp_head', 'wp_generator' );
/**
* Remove shortlink from head.
*/
remove_action( 'wp_head', 'wp_shortlink_wp_head' );
/**
* Remove Really Simple Discovery link.
*/
remove_action( 'wp_head', 'rsd_link' );
/**
* Remove Windows Live Writer manifest link.
*/
remove_action( 'wp_head', 'wlwmanifest_link' );
/**
* Remove adjacent post links from head.
*/
remove_action( 'wp_head', 'adjacent_posts_rel_link_wp_head', 10 );
/**
* Disable XML-RPC pingback header.
*/
if ( ! function_exists( 'rx_theme_remove_x_pingback' ) ) {
function rx_theme_remove_x_pingback( array $headers ): array {
if ( isset( $headers['X-Pingback'] ) ) {
unset( $headers['X-Pingback'] );
}
return $headers;
}
}
add_filter( 'wp_headers', 'rx_theme_remove_x_pingback' );
/**
* Disable self pingbacks.
*/
if ( ! function_exists( 'rx_theme_disable_self_pingbacks' ) ) {
function rx_theme_disable_self_pingbacks( array &$links ): void {
$home = home_url();
foreach ( $links as $key => $link ) {
if ( 0 === strpos( $link, $home ) ) {
unset( $links[ $key ] );
}
}
}
}
add_action( 'pre_ping', 'rx_theme_disable_self_pingbacks' );
/**
* Improve search query by trimming whitespace.
*/
if ( ! function_exists( 'rx_theme_clean_search_query' ) ) {
function rx_theme_clean_search_query( $query ) {
if ( is_admin() || ! $query->is_main_query() ) {
return;
}
if ( $query->is_search() ) {
$s = $query->get( 's' );
if ( is_string( $s ) ) {
$query->set( 's', trim( sanitize_text_field( $s ) ) );
}
}
}
}
add_action( 'pre_get_posts', 'rx_theme_clean_search_query' );
/**
* Redirect empty search to homepage.
*/
if ( ! function_exists( 'rx_theme_redirect_empty_search' ) ) {
function rx_theme_redirect_empty_search(): void {
if ( is_search() && ! is_admin() ) {
$search_query = get_search_query();
if ( '' === trim( $search_query ) ) {
wp_safe_redirect( home_url( '/' ) );
exit;
}
}
}
}
add_action( 'template_redirect', 'rx_theme_redirect_empty_search' );
/**
* Add accessibility skip link.
*/
if ( ! function_exists( 'rx_theme_skip_link' ) ) {
function rx_theme_skip_link(): void {
echo '<a class="rx-skip-link screen-reader-text" href="#main-content">';
esc_html_e( 'Skip to content', RX_THEME_TEXTDOMAIN );
echo '</a>';
}
}
add_action( 'wp_body_open', 'rx_theme_skip_link', 5 );
/**
* Add default main wrapper ID helper.
*
* Use in template:
* <main id="<?php echo esc_attr( rx_theme_main_id() ); ?>">
*/
if ( ! function_exists( 'rx_theme_main_id' ) ) {
function rx_theme_main_id(): string {
return apply_filters( 'rx_theme_main_id', 'main-content' );
}
}
/**
* Add viewport meta safely.
*/
if ( ! function_exists( 'rx_theme_viewport_meta' ) ) {
function rx_theme_viewport_meta(): void {
echo '<meta name="viewport" content="width=device-width, initial-scale=1">' . "\n";
}
}
add_action( 'wp_head', 'rx_theme_viewport_meta', 1 );
/**
* Add theme color meta.
*/
if ( ! function_exists( 'rx_theme_color_meta' ) ) {
function rx_theme_color_meta(): void {
echo '<meta name="theme-color" content="#2563eb">' . "\n";
}
}
add_action( 'wp_head', 'rx_theme_color_meta', 2 );
/**
* Improve login logo URL.
*/
if ( ! function_exists( 'rx_theme_login_logo_url' ) ) {
function rx_theme_login_logo_url(): string {
return home_url( '/' );
}
}
add_filter( 'login_headerurl', 'rx_theme_login_logo_url' );
/**
* Improve login logo title.
*/
if ( ! function_exists( 'rx_theme_login_logo_title' ) ) {
function rx_theme_login_logo_title(): string {
return get_bloginfo( 'name' );
}
}
add_filter( 'login_headertext', 'rx_theme_login_logo_title' );
/**
* Add custom login page CSS.
*/
if ( ! function_exists( 'rx_theme_login_styles' ) ) {
function rx_theme_login_styles(): void {
$custom_logo_id = get_theme_mod( 'custom_logo' );
$logo_url = '';
if ( $custom_logo_id ) {
$logo_url = wp_get_attachment_image_url( $custom_logo_id, 'full' );
}
if ( ! $logo_url ) {
$logo_url = RX_THEME_URI . 'assets/images/logo.png';
}
?>
<style>
body.login {
background: #f8fafc;
}
body.login #login h1 a {
background-image: url('<?php echo esc_url( $logo_url ); ?>');
background-size: contain;
background-position: center;
width: 240px;
height: 90px;
}
body.login form {
border-radius: 16px;
border: 1px solid #e5e7eb;
box-shadow: 0 20px 40px rgba(15, 23, 42, 0.08);
}
body.login .button-primary {
background: #2563eb;
border-color: #2563eb;
}
</style>
<?php
}
}
add_action( 'login_enqueue_scripts', 'rx_theme_login_styles' );
/**
* Add admin footer text.
*/
if ( ! function_exists( 'rx_theme_admin_footer_text' ) ) {
function rx_theme_admin_footer_text(): string {
return sprintf(
esc_html__( 'Powered by %s Theme.', RX_THEME_TEXTDOMAIN ),
'<strong>RX</strong>'
);
}
}
add_filter( 'admin_footer_text', 'rx_theme_admin_footer_text' );
/**
* Add dashboard body class.
*/
if ( ! function_exists( 'rx_theme_admin_body_class' ) ) {
function rx_theme_admin_body_class( string $classes ): string {
$classes .= ' rx-admin-theme ';
return $classes;
}
}
add_filter( 'admin_body_class', 'rx_theme_admin_body_class' );
/**
* Add category support to pages.
*/
if ( ! function_exists( 'rx_theme_add_categories_to_pages' ) ) {
function rx_theme_add_categories_to_pages(): void {
register_taxonomy_for_object_type( 'category', 'page' );
register_taxonomy_for_object_type( 'post_tag', 'page' );
}
}
add_action( 'init', 'rx_theme_add_categories_to_pages' );
/**
* Enable excerpts for pages.
*/
if ( ! function_exists( 'rx_theme_add_excerpts_to_pages' ) ) {
function rx_theme_add_excerpts_to_pages(): void {
add_post_type_support( 'page', 'excerpt' );
}
}
add_action( 'init', 'rx_theme_add_excerpts_to_pages' );
/**
* Add custom post type support enhancements.
*/
if ( ! function_exists( 'rx_theme_post_type_supports' ) ) {
function rx_theme_post_type_supports(): void {
add_post_type_support( 'post', 'excerpt' );
add_post_type_support( 'post', 'thumbnail' );
add_post_type_support( 'post', 'custom-fields' );
add_post_type_support( 'page', 'thumbnail' );
add_post_type_support( 'page', 'custom-fields' );
if ( post_type_exists( 'product' ) ) {
add_post_type_support( 'product', 'excerpt' );
}
}
}
add_action( 'init', 'rx_theme_post_type_supports' );
/**
* Add custom user contact fields.
*/
if ( ! function_exists( 'rx_theme_user_contact_methods' ) ) {
function rx_theme_user_contact_methods( array $methods ): array {
$methods['facebook'] = esc_html__( 'Facebook URL', RX_THEME_TEXTDOMAIN );
$methods['twitter'] = esc_html__( 'Twitter / X URL', RX_THEME_TEXTDOMAIN );
$methods['linkedin'] = esc_html__( 'LinkedIn URL', RX_THEME_TEXTDOMAIN );
$methods['youtube'] = esc_html__( 'YouTube URL', RX_THEME_TEXTDOMAIN );
$methods['instagram'] = esc_html__( 'Instagram URL', RX_THEME_TEXTDOMAIN );
$methods['website'] = esc_html__( 'Website URL', RX_THEME_TEXTDOMAIN );
return $methods;
}
}
add_filter( 'user_contactmethods', 'rx_theme_user_contact_methods' );
/**
* Add custom avatar fallback.
*/
if ( ! function_exists( 'rx_theme_avatar_defaults' ) ) {
function rx_theme_avatar_defaults( array $avatar_defaults ): array {
$custom_avatar = RX_THEME_URI . 'assets/images/avatar-default.png';
$avatar_defaults[ $custom_avatar ] = esc_html__( 'RX Default Avatar', RX_THEME_TEXTDOMAIN );
return $avatar_defaults;
}
}
add_filter( 'avatar_defaults', 'rx_theme_avatar_defaults' );
/**
* Sanitize pagination number.
*/
if ( ! function_exists( 'rx_theme_get_paged' ) ) {
function rx_theme_get_paged(): int {
$paged = get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1;
if ( is_front_page() ) {
$paged = get_query_var( 'page' ) ? get_query_var( 'page' ) : $paged;
}
return max( 1, absint( $paged ) );
}
}
/**
* Safe fallback menu.
*/
if ( ! function_exists( 'rx_theme_fallback_menu' ) ) {
function rx_theme_fallback_menu(): void {
echo '<ul class="rx-menu rx-fallback-menu">';
echo '<li class="menu-item"><a href="' . esc_url( home_url( '/' ) ) . '">' . esc_html__( 'Home', RX_THEME_TEXTDOMAIN ) . '</a></li>';
wp_list_pages(
array(
'title_li' => '',
'depth' => 1,
)
);
echo '</ul>';
}
}
/**
* Safe primary menu helper.
*/
if ( ! function_exists( 'rx_theme_primary_menu' ) ) {
function rx_theme_primary_menu(): void {
wp_nav_menu(
array(
'theme_location' => 'primary',
'menu_class' => 'rx-menu rx-primary-menu',
'container' => 'nav',
'container_class' => 'rx-primary-navigation',
'container_id' => 'rx-primary-navigation',
'fallback_cb' => 'rx_theme_fallback_menu',
'depth' => 3,
)
);
}
}
/**
* Add active class to menu items.
*/
if ( ! function_exists( 'rx_theme_active_menu_class' ) ) {
function rx_theme_active_menu_class( array $classes, $item ): array {
if (
in_array( 'current-menu-item', $classes, true ) ||
in_array( 'current-menu-parent', $classes, true ) ||
in_array( 'current-menu-ancestor', $classes, true )
) {
$classes[] = 'rx-menu-item-active';
}
return array_unique( $classes );
}
}
add_filter( 'nav_menu_css_class', 'rx_theme_active_menu_class', 10, 2 );
/**
* Add aria-current to active menu links.
*/
if ( ! function_exists( 'rx_theme_menu_link_attributes' ) ) {
function rx_theme_menu_link_attributes( array $atts, $item, $args, int $depth ): array {
if (
isset( $item->classes ) &&
is_array( $item->classes ) &&
in_array( 'current-menu-item', $item->classes, true )
) {
$atts['aria-current'] = 'page';
}
return $atts;
}
}
add_filter( 'nav_menu_link_attributes', 'rx_theme_menu_link_attributes', 10, 4 );
/**
* Limit search to posts by default.
*/
if ( ! function_exists( 'rx_theme_search_only_posts' ) ) {
function rx_theme_search_only_posts( $query ): void {
if ( is_admin() || ! $query->is_main_query() || ! $query->is_search() ) {
return;
}
$post_types = apply_filters(
'rx_theme_search_post_types',
array( 'post', 'page' )
);
$query->set( 'post_type', $post_types );
}
}
add_action( 'pre_get_posts', 'rx_theme_search_only_posts' );
/**
* Improve password protected form.
*/
if ( ! function_exists( 'rx_theme_password_form' ) ) {
function rx_theme_password_form(): string {
global $post;
$post_id = isset( $post->ID ) ? absint( $post->ID ) : 0;
$label = 'pwbox-' . $post_id;
$output = '<form class="rx-password-form post-password-form" action="' . esc_url( site_url( 'wp-login.php?action=postpass', 'login_post' ) ) . '" method="post">';
$output .= '<p>' . esc_html__( 'This content is password protected. Please enter the password to view it.', RX_THEME_TEXTDOMAIN ) . '</p>';
$output .= '<p><label for="' . esc_attr( $label ) . '">' . esc_html__( 'Password:', RX_THEME_TEXTDOMAIN ) . '</label></p>';
$output .= '<p><input name="post_password" id="' . esc_attr( $label ) . '" type="password" size="20" required></p>';
$output .= '<p><button type="submit" class="rx-button">' . esc_html__( 'Submit', RX_THEME_TEXTDOMAIN ) . '</button></p>';
$output .= '</form>';
return $output;
}
}
add_filter( 'the_password_form', 'rx_theme_password_form' );
/**
* Add oEmbed wrapper.
*/
if ( ! function_exists( 'rx_theme_oembed_wrapper' ) ) {
function rx_theme_oembed_wrapper( string $html, string $url, array $attr, int $post_id ): string {
if ( empty( $html ) ) {
return $html;
}
return '<div class="rx-embed-wrapper">' . $html . '</div>';
}
}
add_filter( 'embed_oembed_html', 'rx_theme_oembed_wrapper', 10, 4 );
/**
* Allow iframe responsive CSS class for embeds.
*/
if ( ! function_exists( 'rx_theme_embed_defaults' ) ) {
function rx_theme_embed_defaults( array $size ): array {
$size['width'] = 900;
$size['height'] = 506;
return $size;
}
}
add_filter( 'embed_defaults', 'rx_theme_embed_defaults' );
/**
* Add classes to previous/next post links.
*/
if ( ! function_exists( 'rx_theme_posts_link_attributes' ) ) {
function rx_theme_posts_link_attributes(): string {
return 'class="rx-posts-navigation-link"';
}
}
add_filter( 'next_posts_link_attributes', 'rx_theme_posts_link_attributes' );
add_filter( 'previous_posts_link_attributes', 'rx_theme_posts_link_attributes' );
/**
* Add class to next/previous single post links.
*/
if ( ! function_exists( 'rx_theme_post_link_attributes' ) ) {
function rx_theme_post_link_attributes( string $output ): string {
return str_replace( '<a href=', '<a class="rx-single-post-navigation-link" href=', $output );
}
}
add_filter( 'next_post_link', 'rx_theme_post_link_attributes' );
add_filter( 'previous_post_link', 'rx_theme_post_link_attributes' );
/**
* Disable attachment pages by redirecting to parent or home.
*/
if ( ! function_exists( 'rx_theme_disable_attachment_pages' ) ) {
function rx_theme_disable_attachment_pages(): void {
if ( ! is_attachment() ) {
return;
}
global $post;
if ( $post && $post->post_parent ) {
wp_safe_redirect( get_permalink( $post->post_parent ), 301 );
exit;
}
wp_safe_redirect( home_url( '/' ), 301 );
exit;
}
}
add_action( 'template_redirect', 'rx_theme_disable_attachment_pages' );
/**
* Add security headers safely.
*/
if ( ! function_exists( 'rx_theme_security_headers' ) ) {
function rx_theme_security_headers(): void {
if ( headers_sent() ) {
return;
}
header( 'X-Content-Type-Options: nosniff' );
header( 'X-Frame-Options: SAMEORIGIN' );
header( 'Referrer-Policy: strict-origin-when-cross-origin' );
header( 'Permissions-Policy: camera=(), microphone=(), geolocation=()' );
}
}
add_action( 'send_headers', 'rx_theme_security_headers' );
/**
* Add DNS prefetch hints.
* You may move this later to performance.php.
*/
if ( ! function_exists( 'rx_theme_resource_hints' ) ) {
function rx_theme_resource_hints( array $urls, string $relation_type ): array {
if ( 'dns-prefetch' === $relation_type ) {
$urls[] = '//fonts.googleapis.com';
$urls[] = '//fonts.gstatic.com';
$urls[] = '//www.googletagmanager.com';
$urls[] = '//www.google-analytics.com';
}
if ( 'preconnect' === $relation_type ) {
$urls[] = array(
'href' => 'https://fonts.gstatic.com',
'crossorigin' => 'anonymous',
);
}
return array_unique( $urls, SORT_REGULAR );
}
}
add_filter( 'wp_resource_hints', 'rx_theme_resource_hints', 10, 2 );
/**
* Add preload for custom logo.
*/
if ( ! function_exists( 'rx_theme_preload_logo' ) ) {
function rx_theme_preload_logo(): void {
$custom_logo_id = get_theme_mod( 'custom_logo' );
if ( ! $custom_logo_id ) {
return;
}
$logo_url = wp_get_attachment_image_url( $custom_logo_id, 'full' );
if ( ! $logo_url ) {
return;
}
printf(
'<link rel="preload" as="image" href="%s">' . "\n",
esc_url( $logo_url )
);
}
}
add_action( 'wp_head', 'rx_theme_preload_logo', 3 );
/**
* Add preload for featured image on singular posts.
*/
if ( ! function_exists( 'rx_theme_preload_featured_image' ) ) {
function rx_theme_preload_featured_image(): void {
if ( ! is_singular() || ! has_post_thumbnail() ) {
return;
}
$image = wp_get_attachment_image_src( get_post_thumbnail_id(), 'rx-featured-large' );
if ( empty( $image[0] ) ) {
return;
}
printf(
'<link rel="preload" as="image" href="%s">' . "\n",
esc_url( $image[0] )
);
}
}
add_action( 'wp_head', 'rx_theme_preload_featured_image', 4 );
/**
* Add simple schema site data.
* Advanced schema should stay in /inc/helpers/schema.php later.
*/
if ( ! function_exists( 'rx_theme_basic_website_schema' ) ) {
function rx_theme_basic_website_schema(): void {
if ( ! is_front_page() ) {
return;
}
$schema = array(
'@context' => 'https://schema.org',
'@type' => 'WebSite',
'name' => get_bloginfo( 'name' ),
'url' => home_url( '/' ),
'description' => get_bloginfo( 'description' ),
'potentialAction' => array(
'@type' => 'SearchAction',
'target' => home_url( '/?s={search_term_string}' ),
'query-input' => 'required name=search_term_string',
),
);
echo '<script type="application/ld+json">' . wp_json_encode( $schema, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE ) . '</script>' . "\n";
}
}
add_action( 'wp_head', 'rx_theme_basic_website_schema', 20 );
/**
* Add post schema for singular posts.
*/
if ( ! function_exists( 'rx_theme_basic_article_schema' ) ) {
function rx_theme_basic_article_schema(): void {
if ( ! is_singular( 'post' ) ) {
return;
}
global $post;
if ( ! $post instanceof WP_Post ) {
return;
}
$image = '';
if ( has_post_thumbnail( $post ) ) {
$image_data = wp_get_attachment_image_src( get_post_thumbnail_id( $post ), 'rx-og-image' );
$image = $image_data[0] ?? '';
}
$schema = array(
'@context' => 'https://schema.org',
'@type' => 'Article',
'headline' => get_the_title( $post ),
'description' => wp_strip_all_tags( get_the_excerpt( $post ) ),
'url' => get_permalink( $post ),
'datePublished' => get_the_date( DATE_W3C, $post ),
'dateModified' => get_the_modified_date( DATE_W3C, $post ),
'author' => array(
'@type' => 'Person',
'name' => get_the_author_meta( 'display_name', $post->post_author ),
),
'publisher' => array(
'@type' => 'Organization',
'name' => get_bloginfo( 'name' ),
),
'mainEntityOfPage' => array(
'@type' => 'WebPage',
'@id' => get_permalink( $post ),
),
);
if ( $image ) {
$schema['image'] = $image;
}
echo '<script type="application/ld+json">' . wp_json_encode( $schema, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE ) . '</script>' . "\n";
}
}
add_action( 'wp_head', 'rx_theme_basic_article_schema', 21 );
/**
* Add Open Graph fallback meta.
* Full SEO can be moved later to /inc/seo/meta-tags.php.
*/
if ( ! function_exists( 'rx_theme_basic_og_meta' ) ) {
function rx_theme_basic_og_meta(): void {
$title = wp_get_document_title();
$description = get_bloginfo( 'description' );
$url = home_url( '/' );
$type = 'website';
$image = '';
if ( is_singular() ) {
$post_id = get_the_ID();
$url = get_permalink( $post_id );
$type = 'article';
$description = has_excerpt( $post_id ) ? get_the_excerpt( $post_id ) : wp_trim_words( wp_strip_all_tags( get_post_field( 'post_content', $post_id ) ), 28 );
if ( has_post_thumbnail( $post_id ) ) {
$image_data = wp_get_attachment_image_src( get_post_thumbnail_id( $post_id ), 'rx-og-image' );
$image = $image_data[0] ?? '';
}
}
echo '<meta property="og:site_name" content="' . esc_attr( get_bloginfo( 'name' ) ) . '">' . "\n";
echo '<meta property="og:title" content="' . esc_attr( $title ) . '">' . "\n";
echo '<meta property="og:description" content="' . esc_attr( wp_strip_all_tags( $description ) ) . '">' . "\n";
echo '<meta property="og:url" content="' . esc_url( $url ) . '">' . "\n";
echo '<meta property="og:type" content="' . esc_attr( $type ) . '">' . "\n";
if ( $image ) {
echo '<meta property="og:image" content="' . esc_url( $image ) . '">' . "\n";
}
echo '<meta name="twitter:card" content="summary_large_image">' . "\n";
}
}
add_action( 'wp_head', 'rx_theme_basic_og_meta', 30 );
/**
* Add pingback URL only when needed.
*/
if ( ! function_exists( 'rx_theme_pingback_header' ) ) {
function rx_theme_pingback_header(): void {
if ( is_singular() && pings_open() ) {
printf(
'<link rel="pingback" href="%s">' . "\n",
esc_url( get_bloginfo( 'pingback_url' ) )
);
}
}
}
add_action( 'wp_head', 'rx_theme_pingback_header' );
/**
* Add custom classes to comment form button.
*/
if ( ! function_exists( 'rx_theme_comment_form_defaults' ) ) {
function rx_theme_comment_form_defaults( array $defaults ): array {
$defaults['class_submit'] = 'rx-button rx-comment-submit';
$defaults['label_submit'] = esc_html__( 'Post Comment', RX_THEME_TEXTDOMAIN );
return $defaults;
}
}
add_filter( 'comment_form_defaults', 'rx_theme_comment_form_defaults' );
/**
* Improve comment form fields.
*/
if ( ! function_exists( 'rx_theme_comment_form_fields' ) ) {
function rx_theme_comment_form_fields( array $fields ): array {
if ( isset( $fields['author'] ) ) {
$fields['author'] = str_replace( '<input', '<input class="rx-input"', $fields['author'] );
}
if ( isset( $fields['email'] ) ) {
$fields['email'] = str_replace( '<input', '<input class="rx-input"', $fields['email'] );
}
if ( isset( $fields['url'] ) ) {
$fields['url'] = str_replace( '<input', '<input class="rx-input"', $fields['url'] );
}
return $fields;
}
}
add_filter( 'comment_form_default_fields', 'rx_theme_comment_form_fields' );
/**
* Improve comment textarea.
*/
if ( ! function_exists( 'rx_theme_comment_textarea' ) ) {
function rx_theme_comment_textarea( array $args ): array {
if ( isset( $args['comment_field'] ) ) {
$args['comment_field'] = str_replace( '<textarea', '<textarea class="rx-textarea"', $args['comment_field'] );
}
return $args;
}
}
add_filter( 'comment_form_defaults', 'rx_theme_comment_textarea' );
/**
* Add theme support for infinite scroll if Jetpack exists.
*/
if ( ! function_exists( 'rx_theme_jetpack_setup' ) ) {
function rx_theme_jetpack_setup(): void {
add_theme_support(
'infinite-scroll',
array(
'container' => 'main-content',
'render' => 'rx_theme_infinite_scroll_render',
'footer' => 'page',
)
);
}
}
add_action( 'after_setup_theme', 'rx_theme_jetpack_setup' );
/**
* Jetpack infinite scroll render callback.
*/
if ( ! function_exists( 'rx_theme_infinite_scroll_render' ) ) {
function rx_theme_infinite_scroll_render(): void {
while ( have_posts() ) {
the_post();
if ( locate_template( 'template-parts/content.php' ) ) {
get_template_part( 'template-parts/content', get_post_type() );
} else {
echo '<article id="post-' . esc_attr( get_the_ID() ) . '" ';
post_class();
echo '>';
echo '<h2><a href="' . esc_url( get_permalink() ) . '">' . esc_html( get_the_title() ) . '</a></h2>';
echo '<div class="entry-summary">' . wp_kses_post( get_the_excerpt() ) . '</div>';
echo '</article>';
}
}
}
}
/**
* Add theme debug helper.
*/
if ( ! function_exists( 'rx_theme_is_debug' ) ) {
function rx_theme_is_debug(): bool {
return defined( 'WP_DEBUG' ) && WP_DEBUG;
}
}
/**
* Safe array getter helper.
*/
if ( ! function_exists( 'rx_theme_array_get' ) ) {
function rx_theme_array_get( array $array, string $key, $default = null ) {
return array_key_exists( $key, $array ) ? $array[ $key ] : $default;
}
}
/**
* Safe echo helper.
*/
if ( ! function_exists( 'rx_theme_esc_echo' ) ) {
function rx_theme_esc_echo( string $text ): void {
echo esc_html( $text );
}
}
/**
* Safe SVG icon helper.
*
* Usage:
* echo rx_theme_get_icon( 'search' );
*/
if ( ! function_exists( 'rx_theme_get_icon' ) ) {
function rx_theme_get_icon( string $name ): string {
$icons = array(
'search' => '<svg aria-hidden="true" focusable="false" width="20" height="20" viewBox="0 0 24 24" fill="none"><path d="M21 21l-4.35-4.35m1.35-5.65a7 7 0 11-14 0 7 7 0 0114 0z" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>',
'menu' => '<svg aria-hidden="true" focusable="false" width="24" height="24" viewBox="0 0 24 24" fill="none"><path d="M4 7h16M4 12h16M4 17h16" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>',
'close' => '<svg aria-hidden="true" focusable="false" width="24" height="24" viewBox="0 0 24 24" fill="none"><path d="M6 6l12 12M18 6L6 18" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>',
'arrow' => '<svg aria-hidden="true" focusable="false" width="20" height="20" viewBox="0 0 24 24" fill="none"><path d="M5 12h14M13 5l7 7-7 7" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>',
);
$icon = $icons[ $name ] ?? '';
return apply_filters( 'rx_theme_get_icon', $icon, $name );
}
}
/**
* Safe SVG output.
*/
if ( ! function_exists( 'rx_theme_icon' ) ) {
function rx_theme_icon( string $name ): void {
$allowed = array(
'svg' => array(
'aria-hidden' => true,
'focusable' => true,
'width' => true,
'height' => true,
'viewBox' => true,
'fill' => true,
'xmlns' => true,
),
'path' => array(
'd' => true,
'fill' => true,
'stroke' => true,
'stroke-width' => true,
'stroke-linecap' => true,
'stroke-linejoin' => true,
),
);
echo wp_kses( rx_theme_get_icon( $name ), $allowed );
}
}
/**
* Add custom block category.
*/
if ( ! function_exists( 'rx_theme_block_categories' ) ) {
function rx_theme_block_categories( array $categories, $post ): array {
return array_merge(
array(
array(
'slug' => 'rx-blocks',
'title' => esc_html__( 'RX Blocks', RX_THEME_TEXTDOMAIN ),
'icon' => 'heart',
),
),
$categories
);
}
}
add_filter( 'block_categories_all', 'rx_theme_block_categories', 10, 2 );
/**
* Disable admin bar for non-admin users.
*/
if ( ! function_exists( 'rx_theme_maybe_disable_admin_bar' ) ) {
function rx_theme_maybe_disable_admin_bar(): void {
if ( ! current_user_can( 'edit_posts' ) ) {
show_admin_bar( false );
}
}
}
add_action( 'after_setup_theme', 'rx_theme_maybe_disable_admin_bar' );
/**
* Add custom dashboard widget.
*/
if ( ! function_exists( 'rx_theme_dashboard_widget' ) ) {
function rx_theme_dashboard_widget(): void {
if ( ! current_user_can( 'edit_posts' ) ) {
return;
}
wp_add_dashboard_widget(
'rx_theme_dashboard_widget',
esc_html__( 'RX Theme Information', RX_THEME_TEXTDOMAIN ),
'rx_theme_dashboard_widget_content'
);
}
}
add_action( 'wp_dashboard_setup', 'rx_theme_dashboard_widget' );
/**
* Dashboard widget content.
*/
if ( ! function_exists( 'rx_theme_dashboard_widget_content' ) ) {
function rx_theme_dashboard_widget_content(): void {
echo '<p><strong>' . esc_html__( 'RX Theme is active.', RX_THEME_TEXTDOMAIN ) . '</strong></p>';
echo '<p>' . esc_html__( 'Use this theme for fast, SEO-friendly, medical-style, content-rich WordPress websites.', RX_THEME_TEXTDOMAIN ) . '</p>';
echo '<p>' . esc_html__( 'Theme Version:', RX_THEME_TEXTDOMAIN ) . ' ' . esc_html( RX_THEME_VERSION ) . '</p>';
}
}
/**
* Add editor body class.
*/
if ( ! function_exists( 'rx_theme_editor_body_class' ) ) {
function rx_theme_editor_body_class( string $classes ): string {
return $classes . ' rx-block-editor ';
}
}
add_filter( 'admin_body_class', 'rx_theme_editor_body_class' );
/**
* Add classic editor stylesheet if classic editor is used.
*/
if ( ! function_exists( 'rx_theme_classic_editor_styles' ) ) {
function rx_theme_classic_editor_styles(): void {
add_editor_style( 'assets/css/classic-editor.css' );
}
}
add_action( 'admin_init', 'rx_theme_classic_editor_styles' );
/**
* Add admin notice if important files are missing.
*/
if ( ! function_exists( 'rx_theme_missing_files_notice' ) ) {
function rx_theme_missing_files_notice(): void {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
$recommended_files = array(
'assets/css/editor-style.css',
'assets/css/classic-editor.css',
'assets/images/logo.png',
'assets/images/avatar-default.png',
);
$missing = array();
foreach ( $recommended_files as $file ) {
if ( ! file_exists( RX_THEME_DIR . $file ) ) {
$missing[] = $file;
}
}
if ( empty( $missing ) ) {
return;
}
echo '<div class="notice notice-info is-dismissible">';
echo '<p><strong>' . esc_html__( 'RX Theme notice:', RX_THEME_TEXTDOMAIN ) . '</strong> ';
echo esc_html__( 'Some optional recommended files are missing:', RX_THEME_TEXTDOMAIN );
echo '</p><ul>';
foreach ( $missing as $file ) {
echo '<li><code>' . esc_html( $file ) . '</code></li>';
}
echo '</ul></div>';
}
}
add_action( 'admin_notices', 'rx_theme_missing_files_notice' );
/**
* Add "last updated" helper.
*/
if ( ! function_exists( 'rx_theme_last_updated' ) ) {
function rx_theme_last_updated( int $post_id = 0 ): string {
$post_id = $post_id ?: get_the_ID();
if ( ! $post_id ) {
return '';
}
$published = get_the_time( 'U', $post_id );
$modified = get_the_modified_time( 'U', $post_id );
if ( $modified <= $published ) {
return '';
}
return sprintf(
esc_html__( 'Last updated on %s', RX_THEME_TEXTDOMAIN ),
esc_html( get_the_modified_date( get_option( 'date_format' ), $post_id ) )
);
}
}
/**
* Add estimated reading time helper.
*/
if ( ! function_exists( 'rx_theme_reading_time' ) ) {
function rx_theme_reading_time( int $post_id = 0 ): string {
$post_id = $post_id ?: get_the_ID();
if ( ! $post_id ) {
return '';
}
$content = get_post_field( 'post_content', $post_id );
$words = str_word_count( wp_strip_all_tags( $content ) );
$minutes = max( 1, ceil( $words / 200 ) );
return sprintf(
/* translators: %d: minutes */
_n( '%d minute read', '%d minutes read', $minutes, RX_THEME_TEXTDOMAIN ),
$minutes
);
}
}
/**
* Add estimated reading time shortcode.
*
* Usage:
* [rx_reading_time]
*/
if ( ! function_exists( 'rx_theme_reading_time_shortcode' ) ) {
function rx_theme_reading_time_shortcode(): string {
return esc_html( rx_theme_reading_time() );
}
}
add_shortcode( 'rx_reading_time', 'rx_theme_reading_time_shortcode' );
/**
* Add current year shortcode.
*
* Usage:
* [rx_year]
*/
if ( ! function_exists( 'rx_theme_year_shortcode' ) ) {
function rx_theme_year_shortcode(): string {
return esc_html( gmdate( 'Y' ) );
}
}
add_shortcode( 'rx_year', 'rx_theme_year_shortcode' );
/**
* Add site name shortcode.
*
* Usage:
* [rx_site_name]
*/
if ( ! function_exists( 'rx_theme_site_name_shortcode' ) ) {
function rx_theme_site_name_shortcode(): string {
return esc_html( get_bloginfo( 'name' ) );
}
}
add_shortcode( 'rx_site_name', 'rx_theme_site_name_shortcode' );
/**
* Add home URL shortcode.
*
* Usage:
* [rx_home_url]
*/
if ( ! function_exists( 'rx_theme_home_url_shortcode' ) ) {
function rx_theme_home_url_shortcode(): string {
return esc_url( home_url( '/' ) );
}
}
add_shortcode( 'rx_home_url', 'rx_theme_home_url_shortcode' );
/**
* Add safe copyright shortcode.
*
* Usage:
* [rx_copyright]
*/
if ( ! function_exists( 'rx_theme_copyright_shortcode' ) ) {
function rx_theme_copyright_shortcode(): string {
return sprintf(
'© %s %s. %s',
esc_html( gmdate( 'Y' ) ),
esc_html( get_bloginfo( 'name' ) ),
esc_html__( 'All rights reserved.', RX_THEME_TEXTDOMAIN )
);
}
}
add_shortcode( 'rx_copyright', 'rx_theme_copyright_shortcode' );
/**
* Add template helper for copyright.
*/
if ( ! function_exists( 'rx_theme_copyright' ) ) {
function rx_theme_copyright(): void {
echo wp_kses_post( rx_theme_copyright_shortcode() );
}
}
Now load it from your main functions.php:
<?php
/**
* RX Theme Functions
*/
defined( 'ABSPATH' ) || exit;
require_once get_template_directory() . '/inc/core/theme-setup.php';
Important: this file is very powerful, but later you should move some parts into separate files for a cleaner advanced structure:
inc/core/theme-setup.php
inc/core/menus.php
inc/core/image-sizes.php
inc/core/cleanup.php
inc/helpers/reading-time.php
inc/helpers/schema.php
inc/seo/meta-tags.php
inc/performance/resource-hints.php
But yes, the full code above will work as a strong advanced theme-setup.php for your RX theme.