I’ll build this as a strong WordPress theme options file for your RX theme: admin menu, settings sections, sanitization, defaults, Customizer support, frontend helpers, and output hooks.
Below is an advanced inc/options/theme-options.php file for your RX Theme. It adds many possible theme settings: logo, colors, typography, header, footer, SEO, performance, scripts, breadcrumbs, posts, archive, social links, contact info, ad slots, custom CSS/JS, security, and helper functions.
Create this file:
rx-theme/inc/options/theme-options.php
Then include it from your functions.php:
require_once get_template_directory() . '/inc/options/theme-options.php';
inc/options/theme-options.php
<?php
/**
* RX Theme Options
*
* Path: inc/options/theme-options.php
*
* Advanced theme options panel for RX Theme.
*
* @package RX_Theme
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Define RX option key.
*/
if ( ! defined( 'RX_THEME_OPTION_KEY' ) ) {
define( 'RX_THEME_OPTION_KEY', 'rx_theme_options' );
}
/**
* Get all default theme options.
*
* @return array
*/
function rx_theme_default_options() {
return array(
/* General */
'site_layout' => 'right-sidebar',
'container_width' => 1200,
'enable_dark_mode' => 0,
'enable_sticky_sidebar' => 1,
'enable_back_to_top' => 1,
'enable_preloader' => 0,
'enable_smooth_scroll' => 1,
/* Branding */
'custom_logo_url' => '',
'retina_logo_url' => '',
'favicon_url' => '',
'footer_logo_url' => '',
'show_site_title' => 1,
'show_site_tagline' => 1,
/* Header */
'header_layout' => 'default',
'enable_sticky_header' => 1,
'enable_top_bar' => 1,
'top_bar_text' => 'Welcome to RX Theme',
'top_bar_phone' => '',
'top_bar_email' => '',
'enable_header_search' => 1,
'enable_header_social' => 1,
'enable_mobile_menu' => 1,
/* Footer */
'footer_layout' => 'four-columns',
'footer_copyright' => 'Copyright © {year} {site_name}. All rights reserved.',
'enable_footer_widgets' => 1,
'enable_footer_menu' => 1,
'enable_footer_social' => 1,
'enable_footer_back_top' => 1,
/* Colors */
'primary_color' => '#0d6efd',
'secondary_color' => '#6610f2',
'accent_color' => '#198754',
'body_bg_color' => '#ffffff',
'body_text_color' => '#212529',
'heading_color' => '#111111',
'link_color' => '#0d6efd',
'link_hover_color' => '#084298',
'header_bg_color' => '#ffffff',
'footer_bg_color' => '#111111',
'footer_text_color' => '#ffffff',
/* Typography */
'body_font_family' => 'system',
'heading_font_family' => 'system',
'body_font_size' => 16,
'body_line_height' => 1.7,
'heading_line_height' => 1.3,
'enable_google_fonts' => 0,
'google_fonts_url' => '',
/* Blog */
'blog_layout' => 'grid',
'archive_columns' => 3,
'show_post_thumbnail' => 1,
'show_post_author' => 1,
'show_post_date' => 1,
'show_post_category' => 1,
'show_post_tags' => 1,
'show_post_excerpt' => 1,
'excerpt_length' => 30,
'read_more_text' => 'Read More',
'enable_related_posts' => 1,
'related_posts_count' => 3,
'enable_author_box' => 1,
'enable_post_navigation' => 1,
'enable_comments' => 1,
/* SEO */
'enable_basic_seo' => 1,
'enable_meta_description' => 1,
'default_meta_description' => '',
'enable_og_tags' => 1,
'og_default_image' => '',
'enable_schema' => 1,
'enable_breadcrumbs' => 1,
'enable_noindex_search' => 0,
'enable_noindex_404' => 1,
/* Performance */
'enable_dns_prefetch' => 1,
'dns_prefetch_urls' => "https://fonts.googleapis.com\nhttps://fonts.gstatic.com",
'enable_preconnect' => 1,
'preconnect_urls' => "https://fonts.googleapis.com\nhttps://fonts.gstatic.com",
'enable_preload_fonts' => 0,
'preload_font_urls' => '',
'enable_lazy_loading' => 1,
'disable_emoji_scripts' => 1,
'disable_wp_embed' => 0,
'remove_wp_version' => 1,
'enable_defer_js' => 0,
'enable_async_js' => 0,
'defer_exclude_handles' => 'jquery',
'async_exclude_handles' => 'jquery',
/* Scripts */
'header_scripts' => '',
'footer_scripts' => '',
'custom_css' => '',
'custom_js' => '',
/* Analytics */
'google_analytics_id' => '',
'google_tag_manager_id' => '',
'facebook_pixel_id' => '',
'bing_webmaster_code' => '',
'google_site_verification' => '',
/* Social */
'facebook_url' => '',
'twitter_url' => '',
'linkedin_url' => '',
'instagram_url' => '',
'youtube_url' => '',
'pinterest_url' => '',
'tiktok_url' => '',
'github_url' => '',
'telegram_url' => '',
'whatsapp_url' => '',
/* Contact */
'contact_phone' => '',
'contact_email' => '',
'contact_address' => '',
'contact_map_embed' => '',
/* Ads */
'enable_ads' => 0,
'ad_header' => '',
'ad_before_content' => '',
'ad_after_content' => '',
'ad_sidebar' => '',
'ad_footer' => '',
/* WooCommerce */
'enable_woocommerce_style' => 1,
'woo_shop_layout' => 'grid',
'woo_products_per_page' => 12,
'woo_columns' => 4,
'woo_show_cart_header' => 1,
/* Security */
'disable_xmlrpc' => 0,
'disable_rest_user_links' => 1,
'remove_shortlink' => 1,
);
}
/**
* Get theme options merged with defaults.
*
* @param string|null $key Option key.
* @param mixed $default Default value.
* @return mixed
*/
function rx_theme_get_option( $key = null, $default = null ) {
$defaults = rx_theme_default_options();
$options = get_option( RX_THEME_OPTION_KEY, array() );
if ( ! is_array( $options ) ) {
$options = array();
}
$options = wp_parse_args( $options, $defaults );
if ( null === $key ) {
return $options;
}
if ( isset( $options[ $key ] ) ) {
return $options[ $key ];
}
return $default;
}
/**
* Update single theme option.
*
* @param string $key Option key.
* @param mixed $value Option value.
* @return bool
*/
function rx_theme_update_option( $key, $value ) {
$options = rx_theme_get_option();
$options[ $key ] = $value;
return update_option( RX_THEME_OPTION_KEY, $options );
}
/**
* Sanitize checkbox.
*
* @param mixed $value Value.
* @return int
*/
function rx_theme_sanitize_checkbox( $value ) {
return ! empty( $value ) ? 1 : 0;
}
/**
* Sanitize select field.
*
* @param string $value Value.
* @param array $allowed Allowed values.
* @param string $fallback Fallback value.
* @return string
*/
function rx_theme_sanitize_select( $value, $allowed, $fallback ) {
$value = sanitize_key( $value );
return in_array( $value, $allowed, true ) ? $value : $fallback;
}
/**
* Sanitize textarea allowing safe HTML.
*
* @param string $value Value.
* @return string
*/
function rx_theme_sanitize_safe_html( $value ) {
return wp_kses_post( $value );
}
/**
* Sanitize script textarea.
*
* Admins with unfiltered_html can save scripts.
*
* @param string $value Value.
* @return string
*/
function rx_theme_sanitize_script( $value ) {
if ( current_user_can( 'unfiltered_html' ) ) {
return $value;
}
return wp_kses_post( $value );
}
/**
* Sanitize multiline URLs.
*
* @param string $value Value.
* @return string
*/
function rx_theme_sanitize_multiline_urls( $value ) {
$lines = preg_split( '/\r\n|\r|\n/', (string) $value );
$clean = array();
foreach ( $lines as $line ) {
$line = trim( $line );
if ( empty( $line ) ) {
continue;
}
$clean[] = esc_url_raw( $line );
}
return implode( "\n", $clean );
}
/**
* Sanitize all theme options.
*
* @param array $input Input.
* @return array
*/
function rx_theme_sanitize_options( $input ) {
$defaults = rx_theme_default_options();
$output = rx_theme_get_option();
if ( ! is_array( $input ) ) {
return $output;
}
$checkboxes = array(
'enable_dark_mode',
'enable_sticky_sidebar',
'enable_back_to_top',
'enable_preloader',
'enable_smooth_scroll',
'show_site_title',
'show_site_tagline',
'enable_sticky_header',
'enable_top_bar',
'enable_header_search',
'enable_header_social',
'enable_mobile_menu',
'enable_footer_widgets',
'enable_footer_menu',
'enable_footer_social',
'enable_footer_back_top',
'enable_google_fonts',
'show_post_thumbnail',
'show_post_author',
'show_post_date',
'show_post_category',
'show_post_tags',
'show_post_excerpt',
'enable_related_posts',
'enable_author_box',
'enable_post_navigation',
'enable_comments',
'enable_basic_seo',
'enable_meta_description',
'enable_og_tags',
'enable_schema',
'enable_breadcrumbs',
'enable_noindex_search',
'enable_noindex_404',
'enable_dns_prefetch',
'enable_preconnect',
'enable_preload_fonts',
'enable_lazy_loading',
'disable_emoji_scripts',
'disable_wp_embed',
'remove_wp_version',
'enable_defer_js',
'enable_async_js',
'enable_ads',
'enable_woocommerce_style',
'woo_show_cart_header',
'disable_xmlrpc',
'disable_rest_user_links',
'remove_shortlink',
);
foreach ( $checkboxes as $key ) {
$output[ $key ] = isset( $input[ $key ] ) ? rx_theme_sanitize_checkbox( $input[ $key ] ) : 0;
}
$url_fields = array(
'custom_logo_url',
'retina_logo_url',
'favicon_url',
'footer_logo_url',
'og_default_image',
'facebook_url',
'twitter_url',
'linkedin_url',
'instagram_url',
'youtube_url',
'pinterest_url',
'tiktok_url',
'github_url',
'telegram_url',
'whatsapp_url',
);
foreach ( $url_fields as $key ) {
if ( isset( $input[ $key ] ) ) {
$output[ $key ] = esc_url_raw( $input[ $key ] );
}
}
$text_fields = array(
'top_bar_text',
'top_bar_phone',
'top_bar_email',
'footer_copyright',
'body_font_family',
'heading_font_family',
'read_more_text',
'default_meta_description',
'google_analytics_id',
'google_tag_manager_id',
'facebook_pixel_id',
'bing_webmaster_code',
'google_site_verification',
'contact_phone',
'contact_email',
'contact_address',
'defer_exclude_handles',
'async_exclude_handles',
);
foreach ( $text_fields as $key ) {
if ( isset( $input[ $key ] ) ) {
$output[ $key ] = sanitize_text_field( $input[ $key ] );
}
}
$color_fields = array(
'primary_color',
'secondary_color',
'accent_color',
'body_bg_color',
'body_text_color',
'heading_color',
'link_color',
'link_hover_color',
'header_bg_color',
'footer_bg_color',
'footer_text_color',
);
foreach ( $color_fields as $key ) {
if ( isset( $input[ $key ] ) ) {
$output[ $key ] = sanitize_hex_color( $input[ $key ] ) ? sanitize_hex_color( $input[ $key ] ) : $defaults[ $key ];
}
}
$int_fields = array(
'container_width' => array( 720, 1920 ),
'body_font_size' => array( 10, 30 ),
'excerpt_length' => array( 5, 100 ),
'related_posts_count' => array( 1, 12 ),
'archive_columns' => array( 1, 6 ),
'woo_products_per_page' => array( 1, 60 ),
'woo_columns' => array( 1, 6 ),
);
foreach ( $int_fields as $key => $range ) {
if ( isset( $input[ $key ] ) ) {
$value = absint( $input[ $key ] );
$output[ $key ] = min( max( $value, $range[0] ), $range[1] );
}
}
$float_fields = array(
'body_line_height' => array( 1, 3 ),
'heading_line_height' => array( 1, 3 ),
);
foreach ( $float_fields as $key => $range ) {
if ( isset( $input[ $key ] ) ) {
$value = floatval( $input[ $key ] );
$output[ $key ] = min( max( $value, $range[0] ), $range[1] );
}
}
if ( isset( $input['site_layout'] ) ) {
$output['site_layout'] = rx_theme_sanitize_select(
$input['site_layout'],
array( 'full-width', 'left-sidebar', 'right-sidebar', 'no-sidebar' ),
$defaults['site_layout']
);
}
if ( isset( $input['header_layout'] ) ) {
$output['header_layout'] = rx_theme_sanitize_select(
$input['header_layout'],
array( 'default', 'centered', 'split', 'minimal' ),
$defaults['header_layout']
);
}
if ( isset( $input['footer_layout'] ) ) {
$output['footer_layout'] = rx_theme_sanitize_select(
$input['footer_layout'],
array( 'one-column', 'two-columns', 'three-columns', 'four-columns' ),
$defaults['footer_layout']
);
}
if ( isset( $input['blog_layout'] ) ) {
$output['blog_layout'] = rx_theme_sanitize_select(
$input['blog_layout'],
array( 'list', 'grid', 'masonry' ),
$defaults['blog_layout']
);
}
if ( isset( $input['woo_shop_layout'] ) ) {
$output['woo_shop_layout'] = rx_theme_sanitize_select(
$input['woo_shop_layout'],
array( 'grid', 'list' ),
$defaults['woo_shop_layout']
);
}
$textarea_safe_html = array(
'contact_map_embed',
'ad_header',
'ad_before_content',
'ad_after_content',
'ad_sidebar',
'ad_footer',
);
foreach ( $textarea_safe_html as $key ) {
if ( isset( $input[ $key ] ) ) {
$output[ $key ] = rx_theme_sanitize_safe_html( $input[ $key ] );
}
}
$script_fields = array(
'header_scripts',
'footer_scripts',
'custom_js',
);
foreach ( $script_fields as $key ) {
if ( isset( $input[ $key ] ) ) {
$output[ $key ] = rx_theme_sanitize_script( $input[ $key ] );
}
}
if ( isset( $input['custom_css'] ) ) {
$output['custom_css'] = wp_strip_all_tags( $input['custom_css'] );
}
if ( isset( $input['dns_prefetch_urls'] ) ) {
$output['dns_prefetch_urls'] = rx_theme_sanitize_multiline_urls( $input['dns_prefetch_urls'] );
}
if ( isset( $input['preconnect_urls'] ) ) {
$output['preconnect_urls'] = rx_theme_sanitize_multiline_urls( $input['preconnect_urls'] );
}
if ( isset( $input['preload_font_urls'] ) ) {
$output['preload_font_urls'] = rx_theme_sanitize_multiline_urls( $input['preload_font_urls'] );
}
if ( isset( $input['google_fonts_url'] ) ) {
$output['google_fonts_url'] = esc_url_raw( $input['google_fonts_url'] );
}
return $output;
}
/**
* Register admin settings.
*/
function rx_theme_register_options() {
register_setting(
'rx_theme_options_group',
RX_THEME_OPTION_KEY,
array(
'type' => 'array',
'sanitize_callback' => 'rx_theme_sanitize_options',
'default' => rx_theme_default_options(),
)
);
}
add_action( 'admin_init', 'rx_theme_register_options' );
/**
* Add admin menu page.
*/
function rx_theme_options_menu() {
add_theme_page(
esc_html__( 'RX Theme Options', 'rx-theme' ),
esc_html__( 'RX Theme Options', 'rx-theme' ),
'manage_options',
'rx-theme-options',
'rx_theme_options_page'
);
}
add_action( 'admin_menu', 'rx_theme_options_menu' );
/**
* Enqueue admin assets.
*
* @param string $hook Hook.
*/
function rx_theme_options_admin_assets( $hook ) {
if ( 'appearance_page_rx-theme-options' !== $hook ) {
return;
}
wp_enqueue_style( 'wp-color-picker' );
wp_enqueue_media();
wp_enqueue_script( 'wp-color-picker' );
$css = '
.rx-options-wrap { max-width: 1200px; }
.rx-options-header { background:#111827;color:#fff;padding:24px;border-radius:10px;margin:20px 0; }
.rx-options-header h1 { color:#fff;margin:0 0 8px; }
.rx-options-tabs { display:flex;gap:8px;flex-wrap:wrap;margin-bottom:20px; }
.rx-options-tab { background:#fff;border:1px solid #ccd0d4;padding:10px 14px;border-radius:6px;text-decoration:none;color:#1d2327;font-weight:600; }
.rx-options-tab.active { background:#2271b1;color:#fff;border-color:#2271b1; }
.rx-section { background:#fff;border:1px solid #ccd0d4;border-radius:8px;margin-bottom:20px;padding:20px; }
.rx-section h2 { margin-top:0;border-bottom:1px solid #eee;padding-bottom:10px; }
.rx-field { display:grid;grid-template-columns:260px 1fr;gap:20px;padding:16px 0;border-bottom:1px solid #f0f0f0; }
.rx-field:last-child { border-bottom:none; }
.rx-field label { font-weight:600; }
.rx-field input[type="text"],
.rx-field input[type="url"],
.rx-field input[type="email"],
.rx-field input[type="number"],
.rx-field textarea,
.rx-field select { width:100%;max-width:680px; }
.rx-field textarea { min-height:110px; }
.rx-help { color:#646970;font-size:13px;margin-top:6px; }
.rx-upload-row { display:flex;gap:8px;align-items:center;max-width:680px; }
.rx-upload-row input { flex:1; }
@media(max-width:782px){ .rx-field{grid-template-columns:1fr;} }
';
wp_add_inline_style( 'wp-color-picker', $css );
$js = "
jQuery(function($){
$('.rx-color-field').wpColorPicker();
$(document).on('click', '.rx-upload-button', function(e){
e.preventDefault();
var button = $(this);
var input = button.closest('.rx-upload-row').find('input');
var frame = wp.media({
title: 'Select or Upload Media',
button: { text: 'Use this file' },
multiple: false
});
frame.on('select', function(){
var attachment = frame.state().get('selection').first().toJSON();
input.val(attachment.url).trigger('change');
});
frame.open();
});
$(document).on('click', '.rx-clear-button', function(e){
e.preventDefault();
$(this).closest('.rx-upload-row').find('input').val('').trigger('change');
});
$('.rx-options-tab').on('click', function(e){
e.preventDefault();
var target = $(this).attr('href');
$('.rx-options-tab').removeClass('active');
$(this).addClass('active');
$('.rx-section').hide();
$(target).show();
window.location.hash = target;
});
var hash = window.location.hash;
if(hash && $(hash).length){
$('.rx-options-tab[href=\"' + hash + '\"]').trigger('click');
}else{
$('.rx-options-tab:first').trigger('click');
}
});
";
wp_add_inline_script( 'wp-color-picker', $js );
}
add_action( 'admin_enqueue_scripts', 'rx_theme_options_admin_assets' );
/**
* Render text field.
*
* @param string $key Key.
* @param string $label Label.
* @param string $help Help.
* @param string $type Type.
*/
function rx_theme_render_text_field( $key, $label, $help = '', $type = 'text' ) {
$value = rx_theme_get_option( $key );
?>
<div class="rx-field">
<label for="rx_<?php echo esc_attr( $key ); ?>"><?php echo esc_html( $label ); ?></label>
<div>
<input
type="<?php echo esc_attr( $type ); ?>"
id="rx_<?php echo esc_attr( $key ); ?>"
name="<?php echo esc_attr( RX_THEME_OPTION_KEY ); ?>[<?php echo esc_attr( $key ); ?>]"
value="<?php echo esc_attr( $value ); ?>"
/>
<?php if ( $help ) : ?>
<p class="rx-help"><?php echo esc_html( $help ); ?></p>
<?php endif; ?>
</div>
</div>
<?php
}
/**
* Render number field.
*
* @param string $key Key.
* @param string $label Label.
* @param string $help Help.
* @param int $min Min.
* @param int $max Max.
* @param string $step Step.
*/
function rx_theme_render_number_field( $key, $label, $help = '', $min = 0, $max = 9999, $step = '1' ) {
$value = rx_theme_get_option( $key );
?>
<div class="rx-field">
<label for="rx_<?php echo esc_attr( $key ); ?>"><?php echo esc_html( $label ); ?></label>
<div>
<input
type="number"
id="rx_<?php echo esc_attr( $key ); ?>"
name="<?php echo esc_attr( RX_THEME_OPTION_KEY ); ?>[<?php echo esc_attr( $key ); ?>]"
value="<?php echo esc_attr( $value ); ?>"
min="<?php echo esc_attr( $min ); ?>"
max="<?php echo esc_attr( $max ); ?>"
step="<?php echo esc_attr( $step ); ?>"
/>
<?php if ( $help ) : ?>
<p class="rx-help"><?php echo esc_html( $help ); ?></p>
<?php endif; ?>
</div>
</div>
<?php
}
/**
* Render textarea field.
*
* @param string $key Key.
* @param string $label Label.
* @param string $help Help.
*/
function rx_theme_render_textarea_field( $key, $label, $help = '' ) {
$value = rx_theme_get_option( $key );
?>
<div class="rx-field">
<label for="rx_<?php echo esc_attr( $key ); ?>"><?php echo esc_html( $label ); ?></label>
<div>
<textarea
id="rx_<?php echo esc_attr( $key ); ?>"
name="<?php echo esc_attr( RX_THEME_OPTION_KEY ); ?>[<?php echo esc_attr( $key ); ?>]"
rows="6"
><?php echo esc_textarea( $value ); ?></textarea>
<?php if ( $help ) : ?>
<p class="rx-help"><?php echo esc_html( $help ); ?></p>
<?php endif; ?>
</div>
</div>
<?php
}
/**
* Render checkbox field.
*
* @param string $key Key.
* @param string $label Label.
* @param string $help Help.
*/
function rx_theme_render_checkbox_field( $key, $label, $help = '' ) {
$value = rx_theme_get_option( $key );
?>
<div class="rx-field">
<label for="rx_<?php echo esc_attr( $key ); ?>"><?php echo esc_html( $label ); ?></label>
<div>
<label>
<input
type="checkbox"
id="rx_<?php echo esc_attr( $key ); ?>"
name="<?php echo esc_attr( RX_THEME_OPTION_KEY ); ?>[<?php echo esc_attr( $key ); ?>]"
value="1"
<?php checked( 1, $value ); ?>
/>
<?php esc_html_e( 'Enable', 'rx-theme' ); ?>
</label>
<?php if ( $help ) : ?>
<p class="rx-help"><?php echo esc_html( $help ); ?></p>
<?php endif; ?>
</div>
</div>
<?php
}
/**
* Render select field.
*
* @param string $key Key.
* @param string $label Label.
* @param array $choices Choices.
* @param string $help Help.
*/
function rx_theme_render_select_field( $key, $label, $choices, $help = '' ) {
$value = rx_theme_get_option( $key );
?>
<div class="rx-field">
<label for="rx_<?php echo esc_attr( $key ); ?>"><?php echo esc_html( $label ); ?></label>
<div>
<select
id="rx_<?php echo esc_attr( $key ); ?>"
name="<?php echo esc_attr( RX_THEME_OPTION_KEY ); ?>[<?php echo esc_attr( $key ); ?>]"
>
<?php foreach ( $choices as $choice_value => $choice_label ) : ?>
<option value="<?php echo esc_attr( $choice_value ); ?>" <?php selected( $value, $choice_value ); ?>>
<?php echo esc_html( $choice_label ); ?>
</option>
<?php endforeach; ?>
</select>
<?php if ( $help ) : ?>
<p class="rx-help"><?php echo esc_html( $help ); ?></p>
<?php endif; ?>
</div>
</div>
<?php
}
/**
* Render color field.
*
* @param string $key Key.
* @param string $label Label.
* @param string $help Help.
*/
function rx_theme_render_color_field( $key, $label, $help = '' ) {
$value = rx_theme_get_option( $key );
?>
<div class="rx-field">
<label for="rx_<?php echo esc_attr( $key ); ?>"><?php echo esc_html( $label ); ?></label>
<div>
<input
type="text"
class="rx-color-field"
id="rx_<?php echo esc_attr( $key ); ?>"
name="<?php echo esc_attr( RX_THEME_OPTION_KEY ); ?>[<?php echo esc_attr( $key ); ?>]"
value="<?php echo esc_attr( $value ); ?>"
/>
<?php if ( $help ) : ?>
<p class="rx-help"><?php echo esc_html( $help ); ?></p>
<?php endif; ?>
</div>
</div>
<?php
}
/**
* Render media upload field.
*
* @param string $key Key.
* @param string $label Label.
* @param string $help Help.
*/
function rx_theme_render_upload_field( $key, $label, $help = '' ) {
$value = rx_theme_get_option( $key );
?>
<div class="rx-field">
<label for="rx_<?php echo esc_attr( $key ); ?>"><?php echo esc_html( $label ); ?></label>
<div>
<div class="rx-upload-row">
<input
type="url"
id="rx_<?php echo esc_attr( $key ); ?>"
name="<?php echo esc_attr( RX_THEME_OPTION_KEY ); ?>[<?php echo esc_attr( $key ); ?>]"
value="<?php echo esc_url( $value ); ?>"
/>
<button class="button rx-upload-button"><?php esc_html_e( 'Upload', 'rx-theme' ); ?></button>
<button class="button rx-clear-button"><?php esc_html_e( 'Clear', 'rx-theme' ); ?></button>
</div>
<?php if ( $help ) : ?>
<p class="rx-help"><?php echo esc_html( $help ); ?></p>
<?php endif; ?>
</div>
</div>
<?php
}
/**
* Render options page.
*/
function rx_theme_options_page() {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
?>
<div class="wrap rx-options-wrap">
<div class="rx-options-header">
<h1><?php esc_html_e( 'RX Theme Options', 'rx-theme' ); ?></h1>
<p><?php esc_html_e( 'Control branding, layout, colors, SEO, performance, scripts, social links, ads, footer, and more.', 'rx-theme' ); ?></p>
</div>
<form method="post" action="options.php">
<?php settings_fields( 'rx_theme_options_group' ); ?>
<div class="rx-options-tabs">
<a class="rx-options-tab" href="#rx-general"><?php esc_html_e( 'General', 'rx-theme' ); ?></a>
<a class="rx-options-tab" href="#rx-branding"><?php esc_html_e( 'Branding', 'rx-theme' ); ?></a>
<a class="rx-options-tab" href="#rx-header"><?php esc_html_e( 'Header', 'rx-theme' ); ?></a>
<a class="rx-options-tab" href="#rx-footer"><?php esc_html_e( 'Footer', 'rx-theme' ); ?></a>
<a class="rx-options-tab" href="#rx-colors"><?php esc_html_e( 'Colors', 'rx-theme' ); ?></a>
<a class="rx-options-tab" href="#rx-typography"><?php esc_html_e( 'Typography', 'rx-theme' ); ?></a>
<a class="rx-options-tab" href="#rx-blog"><?php esc_html_e( 'Blog', 'rx-theme' ); ?></a>
<a class="rx-options-tab" href="#rx-seo"><?php esc_html_e( 'SEO', 'rx-theme' ); ?></a>
<a class="rx-options-tab" href="#rx-performance"><?php esc_html_e( 'Performance', 'rx-theme' ); ?></a>
<a class="rx-options-tab" href="#rx-scripts"><?php esc_html_e( 'Scripts', 'rx-theme' ); ?></a>
<a class="rx-options-tab" href="#rx-social"><?php esc_html_e( 'Social', 'rx-theme' ); ?></a>
<a class="rx-options-tab" href="#rx-contact"><?php esc_html_e( 'Contact', 'rx-theme' ); ?></a>
<a class="rx-options-tab" href="#rx-ads"><?php esc_html_e( 'Ads', 'rx-theme' ); ?></a>
<a class="rx-options-tab" href="#rx-woocommerce"><?php esc_html_e( 'WooCommerce', 'rx-theme' ); ?></a>
<a class="rx-options-tab" href="#rx-security"><?php esc_html_e( 'Security', 'rx-theme' ); ?></a>
</div>
<section id="rx-general" class="rx-section">
<h2><?php esc_html_e( 'General Settings', 'rx-theme' ); ?></h2>
<?php
rx_theme_render_select_field(
'site_layout',
'Site Layout',
array(
'full-width' => 'Full Width',
'left-sidebar' => 'Left Sidebar',
'right-sidebar' => 'Right Sidebar',
'no-sidebar' => 'No Sidebar',
)
);
rx_theme_render_number_field( 'container_width', 'Container Width', 'Main container width in pixels.', 720, 1920 );
rx_theme_render_checkbox_field( 'enable_dark_mode', 'Dark Mode', 'Enable dark mode class support.' );
rx_theme_render_checkbox_field( 'enable_sticky_sidebar', 'Sticky Sidebar' );
rx_theme_render_checkbox_field( 'enable_back_to_top', 'Back To Top Button' );
rx_theme_render_checkbox_field( 'enable_preloader', 'Page Preloader' );
rx_theme_render_checkbox_field( 'enable_smooth_scroll', 'Smooth Scroll' );
?>
</section>
<section id="rx-branding" class="rx-section">
<h2><?php esc_html_e( 'Branding Settings', 'rx-theme' ); ?></h2>
<?php
rx_theme_render_upload_field( 'custom_logo_url', 'Custom Logo URL' );
rx_theme_render_upload_field( 'retina_logo_url', 'Retina Logo URL' );
rx_theme_render_upload_field( 'favicon_url', 'Favicon URL' );
rx_theme_render_upload_field( 'footer_logo_url', 'Footer Logo URL' );
rx_theme_render_checkbox_field( 'show_site_title', 'Show Site Title' );
rx_theme_render_checkbox_field( 'show_site_tagline', 'Show Site Tagline' );
?>
</section>
<section id="rx-header" class="rx-section">
<h2><?php esc_html_e( 'Header Settings', 'rx-theme' ); ?></h2>
<?php
rx_theme_render_select_field(
'header_layout',
'Header Layout',
array(
'default' => 'Default',
'centered' => 'Centered',
'split' => 'Split',
'minimal' => 'Minimal',
)
);
rx_theme_render_checkbox_field( 'enable_sticky_header', 'Sticky Header' );
rx_theme_render_checkbox_field( 'enable_top_bar', 'Top Bar' );
rx_theme_render_text_field( 'top_bar_text', 'Top Bar Text' );
rx_theme_render_text_field( 'top_bar_phone', 'Top Bar Phone' );
rx_theme_render_text_field( 'top_bar_email', 'Top Bar Email', '', 'email' );
rx_theme_render_checkbox_field( 'enable_header_search', 'Header Search' );
rx_theme_render_checkbox_field( 'enable_header_social', 'Header Social Icons' );
rx_theme_render_checkbox_field( 'enable_mobile_menu', 'Mobile Menu' );
?>
</section>
<section id="rx-footer" class="rx-section">
<h2><?php esc_html_e( 'Footer Settings', 'rx-theme' ); ?></h2>
<?php
rx_theme_render_select_field(
'footer_layout',
'Footer Layout',
array(
'one-column' => 'One Column',
'two-columns' => 'Two Columns',
'three-columns' => 'Three Columns',
'four-columns' => 'Four Columns',
)
);
rx_theme_render_text_field( 'footer_copyright', 'Footer Copyright', 'Use {year} and {site_name} placeholders.' );
rx_theme_render_checkbox_field( 'enable_footer_widgets', 'Footer Widgets' );
rx_theme_render_checkbox_field( 'enable_footer_menu', 'Footer Menu' );
rx_theme_render_checkbox_field( 'enable_footer_social', 'Footer Social Icons' );
rx_theme_render_checkbox_field( 'enable_footer_back_top', 'Footer Back To Top' );
?>
</section>
<section id="rx-colors" class="rx-section">
<h2><?php esc_html_e( 'Color Settings', 'rx-theme' ); ?></h2>
<?php
rx_theme_render_color_field( 'primary_color', 'Primary Color' );
rx_theme_render_color_field( 'secondary_color', 'Secondary Color' );
rx_theme_render_color_field( 'accent_color', 'Accent Color' );
rx_theme_render_color_field( 'body_bg_color', 'Body Background Color' );
rx_theme_render_color_field( 'body_text_color', 'Body Text Color' );
rx_theme_render_color_field( 'heading_color', 'Heading Color' );
rx_theme_render_color_field( 'link_color', 'Link Color' );
rx_theme_render_color_field( 'link_hover_color', 'Link Hover Color' );
rx_theme_render_color_field( 'header_bg_color', 'Header Background Color' );
rx_theme_render_color_field( 'footer_bg_color', 'Footer Background Color' );
rx_theme_render_color_field( 'footer_text_color', 'Footer Text Color' );
?>
</section>
<section id="rx-typography" class="rx-section">
<h2><?php esc_html_e( 'Typography Settings', 'rx-theme' ); ?></h2>
<?php
rx_theme_render_text_field( 'body_font_family', 'Body Font Family', 'Example: Arial, system, Roboto, Open Sans.' );
rx_theme_render_text_field( 'heading_font_family', 'Heading Font Family' );
rx_theme_render_number_field( 'body_font_size', 'Body Font Size', 'Pixel value.', 10, 30 );
rx_theme_render_number_field( 'body_line_height', 'Body Line Height', 'Example: 1.7', 1, 3, '0.1' );
rx_theme_render_number_field( 'heading_line_height', 'Heading Line Height', 'Example: 1.3', 1, 3, '0.1' );
rx_theme_render_checkbox_field( 'enable_google_fonts', 'Enable Google Fonts' );
rx_theme_render_text_field( 'google_fonts_url', 'Google Fonts URL', 'Paste full Google Fonts CSS URL.', 'url' );
?>
</section>
<section id="rx-blog" class="rx-section">
<h2><?php esc_html_e( 'Blog Settings', 'rx-theme' ); ?></h2>
<?php
rx_theme_render_select_field(
'blog_layout',
'Blog Layout',
array(
'list' => 'List',
'grid' => 'Grid',
'masonry' => 'Masonry',
)
);
rx_theme_render_number_field( 'archive_columns', 'Archive Columns', '', 1, 6 );
rx_theme_render_checkbox_field( 'show_post_thumbnail', 'Show Post Thumbnail' );
rx_theme_render_checkbox_field( 'show_post_author', 'Show Post Author' );
rx_theme_render_checkbox_field( 'show_post_date', 'Show Post Date' );
rx_theme_render_checkbox_field( 'show_post_category', 'Show Post Category' );
rx_theme_render_checkbox_field( 'show_post_tags', 'Show Post Tags' );
rx_theme_render_checkbox_field( 'show_post_excerpt', 'Show Post Excerpt' );
rx_theme_render_number_field( 'excerpt_length', 'Excerpt Length', 'Number of words.', 5, 100 );
rx_theme_render_text_field( 'read_more_text', 'Read More Text' );
rx_theme_render_checkbox_field( 'enable_related_posts', 'Related Posts' );
rx_theme_render_number_field( 'related_posts_count', 'Related Posts Count', '', 1, 12 );
rx_theme_render_checkbox_field( 'enable_author_box', 'Author Box' );
rx_theme_render_checkbox_field( 'enable_post_navigation', 'Post Navigation' );
rx_theme_render_checkbox_field( 'enable_comments', 'Comments' );
?>
</section>
<section id="rx-seo" class="rx-section">
<h2><?php esc_html_e( 'SEO Settings', 'rx-theme' ); ?></h2>
<?php
rx_theme_render_checkbox_field( 'enable_basic_seo', 'Basic SEO' );
rx_theme_render_checkbox_field( 'enable_meta_description', 'Meta Description' );
rx_theme_render_textarea_field( 'default_meta_description', 'Default Meta Description' );
rx_theme_render_checkbox_field( 'enable_og_tags', 'Open Graph Tags' );
rx_theme_render_upload_field( 'og_default_image', 'Default Open Graph Image' );
rx_theme_render_checkbox_field( 'enable_schema', 'Basic Schema Markup' );
rx_theme_render_checkbox_field( 'enable_breadcrumbs', 'Breadcrumbs' );
rx_theme_render_checkbox_field( 'enable_noindex_search', 'Noindex Search Pages' );
rx_theme_render_checkbox_field( 'enable_noindex_404', 'Noindex 404 Pages' );
?>
</section>
<section id="rx-performance" class="rx-section">
<h2><?php esc_html_e( 'Performance Settings', 'rx-theme' ); ?></h2>
<?php
rx_theme_render_checkbox_field( 'enable_dns_prefetch', 'DNS Prefetch' );
rx_theme_render_textarea_field( 'dns_prefetch_urls', 'DNS Prefetch URLs', 'One URL per line.' );
rx_theme_render_checkbox_field( 'enable_preconnect', 'Preconnect' );
rx_theme_render_textarea_field( 'preconnect_urls', 'Preconnect URLs', 'One URL per line.' );
rx_theme_render_checkbox_field( 'enable_preload_fonts', 'Preload Fonts' );
rx_theme_render_textarea_field( 'preload_font_urls', 'Preload Font URLs', 'One font URL per line.' );
rx_theme_render_checkbox_field( 'enable_lazy_loading', 'Lazy Loading' );
rx_theme_render_checkbox_field( 'disable_emoji_scripts', 'Disable Emoji Scripts' );
rx_theme_render_checkbox_field( 'disable_wp_embed', 'Disable WP Embed' );
rx_theme_render_checkbox_field( 'remove_wp_version', 'Remove WordPress Version' );
rx_theme_render_checkbox_field( 'enable_defer_js', 'Defer JavaScript' );
rx_theme_render_text_field( 'defer_exclude_handles', 'Defer Exclude Handles', 'Comma-separated script handles.' );
rx_theme_render_checkbox_field( 'enable_async_js', 'Async JavaScript' );
rx_theme_render_text_field( 'async_exclude_handles', 'Async Exclude Handles', 'Comma-separated script handles.' );
?>
</section>
<section id="rx-scripts" class="rx-section">
<h2><?php esc_html_e( 'Scripts and Custom Code', 'rx-theme' ); ?></h2>
<?php
rx_theme_render_text_field( 'google_analytics_id', 'Google Analytics ID', 'Example: G-XXXXXXXXXX' );
rx_theme_render_text_field( 'google_tag_manager_id', 'Google Tag Manager ID', 'Example: GTM-XXXXXXX' );
rx_theme_render_text_field( 'facebook_pixel_id', 'Facebook Pixel ID' );
rx_theme_render_text_field( 'google_site_verification', 'Google Site Verification Code' );
rx_theme_render_text_field( 'bing_webmaster_code', 'Bing Webmaster Verification Code' );
rx_theme_render_textarea_field( 'header_scripts', 'Header Scripts', 'Added before closing </head>. Use carefully.' );
rx_theme_render_textarea_field( 'footer_scripts', 'Footer Scripts', 'Added before closing </body>. Use carefully.' );
rx_theme_render_textarea_field( 'custom_css', 'Custom CSS' );
rx_theme_render_textarea_field( 'custom_js', 'Custom JS', 'JS only, without opening script tag.' );
?>
</section>
<section id="rx-social" class="rx-section">
<h2><?php esc_html_e( 'Social Links', 'rx-theme' ); ?></h2>
<?php
rx_theme_render_text_field( 'facebook_url', 'Facebook URL', '', 'url' );
rx_theme_render_text_field( 'twitter_url', 'Twitter/X URL', '', 'url' );
rx_theme_render_text_field( 'linkedin_url', 'LinkedIn URL', '', 'url' );
rx_theme_render_text_field( 'instagram_url', 'Instagram URL', '', 'url' );
rx_theme_render_text_field( 'youtube_url', 'YouTube URL', '', 'url' );
rx_theme_render_text_field( 'pinterest_url', 'Pinterest URL', '', 'url' );
rx_theme_render_text_field( 'tiktok_url', 'TikTok URL', '', 'url' );
rx_theme_render_text_field( 'github_url', 'GitHub URL', '', 'url' );
rx_theme_render_text_field( 'telegram_url', 'Telegram URL', '', 'url' );
rx_theme_render_text_field( 'whatsapp_url', 'WhatsApp URL', '', 'url' );
?>
</section>
<section id="rx-contact" class="rx-section">
<h2><?php esc_html_e( 'Contact Settings', 'rx-theme' ); ?></h2>
<?php
rx_theme_render_text_field( 'contact_phone', 'Contact Phone' );
rx_theme_render_text_field( 'contact_email', 'Contact Email', '', 'email' );
rx_theme_render_text_field( 'contact_address', 'Contact Address' );
rx_theme_render_textarea_field( 'contact_map_embed', 'Google Map Embed Code' );
?>
</section>
<section id="rx-ads" class="rx-section">
<h2><?php esc_html_e( 'Advertisement Settings', 'rx-theme' ); ?></h2>
<?php
rx_theme_render_checkbox_field( 'enable_ads', 'Enable Ads' );
rx_theme_render_textarea_field( 'ad_header', 'Header Ad Code' );
rx_theme_render_textarea_field( 'ad_before_content', 'Before Content Ad Code' );
rx_theme_render_textarea_field( 'ad_after_content', 'After Content Ad Code' );
rx_theme_render_textarea_field( 'ad_sidebar', 'Sidebar Ad Code' );
rx_theme_render_textarea_field( 'ad_footer', 'Footer Ad Code' );
?>
</section>
<section id="rx-woocommerce" class="rx-section">
<h2><?php esc_html_e( 'WooCommerce Settings', 'rx-theme' ); ?></h2>
<?php
rx_theme_render_checkbox_field( 'enable_woocommerce_style', 'WooCommerce Theme Style' );
rx_theme_render_select_field(
'woo_shop_layout',
'Shop Layout',
array(
'grid' => 'Grid',
'list' => 'List',
)
);
rx_theme_render_number_field( 'woo_products_per_page', 'Products Per Page', '', 1, 60 );
rx_theme_render_number_field( 'woo_columns', 'Product Columns', '', 1, 6 );
rx_theme_render_checkbox_field( 'woo_show_cart_header', 'Show Cart Icon In Header' );
?>
</section>
<section id="rx-security" class="rx-section">
<h2><?php esc_html_e( 'Security and Cleanup', 'rx-theme' ); ?></h2>
<?php
rx_theme_render_checkbox_field( 'disable_xmlrpc', 'Disable XML-RPC' );
rx_theme_render_checkbox_field( 'disable_rest_user_links', 'Remove REST API User Links' );
rx_theme_render_checkbox_field( 'remove_shortlink', 'Remove Shortlink' );
?>
</section>
<?php submit_button( esc_html__( 'Save RX Theme Options', 'rx-theme' ) ); ?>
</form>
</div>
<?php
}
/**
* Add body classes based on options.
*
* @param array $classes Body classes.
* @return array
*/
function rx_theme_body_classes( $classes ) {
$classes[] = 'rx-layout-' . sanitize_html_class( rx_theme_get_option( 'site_layout' ) );
$classes[] = 'rx-header-' . sanitize_html_class( rx_theme_get_option( 'header_layout' ) );
$classes[] = 'rx-blog-' . sanitize_html_class( rx_theme_get_option( 'blog_layout' ) );
if ( rx_theme_get_option( 'enable_dark_mode' ) ) {
$classes[] = 'rx-dark-mode';
}
if ( rx_theme_get_option( 'enable_sticky_header' ) ) {
$classes[] = 'rx-sticky-header-enabled';
}
if ( rx_theme_get_option( 'enable_sticky_sidebar' ) ) {
$classes[] = 'rx-sticky-sidebar-enabled';
}
return $classes;
}
add_filter( 'body_class', 'rx_theme_body_classes' );
/**
* Output dynamic CSS.
*/
function rx_theme_dynamic_css() {
$body_font = rx_theme_get_option( 'body_font_family' );
$heading_font = rx_theme_get_option( 'heading_font_family' );
if ( 'system' === $body_font ) {
$body_font = '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif';
}
if ( 'system' === $heading_font ) {
$heading_font = '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif';
}
$css = '
:root {
--rx-primary-color: ' . esc_html( rx_theme_get_option( 'primary_color' ) ) . ';
--rx-secondary-color: ' . esc_html( rx_theme_get_option( 'secondary_color' ) ) . ';
--rx-accent-color: ' . esc_html( rx_theme_get_option( 'accent_color' ) ) . ';
--rx-body-bg-color: ' . esc_html( rx_theme_get_option( 'body_bg_color' ) ) . ';
--rx-body-text-color: ' . esc_html( rx_theme_get_option( 'body_text_color' ) ) . ';
--rx-heading-color: ' . esc_html( rx_theme_get_option( 'heading_color' ) ) . ';
--rx-link-color: ' . esc_html( rx_theme_get_option( 'link_color' ) ) . ';
--rx-link-hover-color: ' . esc_html( rx_theme_get_option( 'link_hover_color' ) ) . ';
--rx-header-bg-color: ' . esc_html( rx_theme_get_option( 'header_bg_color' ) ) . ';
--rx-footer-bg-color: ' . esc_html( rx_theme_get_option( 'footer_bg_color' ) ) . ';
--rx-footer-text-color: ' . esc_html( rx_theme_get_option( 'footer_text_color' ) ) . ';
--rx-container-width: ' . absint( rx_theme_get_option( 'container_width' ) ) . 'px;
--rx-body-font-family: ' . esc_html( $body_font ) . ';
--rx-heading-font-family: ' . esc_html( $heading_font ) . ';
--rx-body-font-size: ' . absint( rx_theme_get_option( 'body_font_size' ) ) . 'px;
--rx-body-line-height: ' . esc_html( rx_theme_get_option( 'body_line_height' ) ) . ';
--rx-heading-line-height: ' . esc_html( rx_theme_get_option( 'heading_line_height' ) ) . ';
}
body {
background: var(--rx-body-bg-color);
color: var(--rx-body-text-color);
font-family: var(--rx-body-font-family);
font-size: var(--rx-body-font-size);
line-height: var(--rx-body-line-height);
}
h1, h2, h3, h4, h5, h6 {
color: var(--rx-heading-color);
font-family: var(--rx-heading-font-family);
line-height: var(--rx-heading-line-height);
}
a {
color: var(--rx-link-color);
}
a:hover {
color: var(--rx-link-hover-color);
}
.rx-container,
.container,
.site-container {
max-width: var(--rx-container-width);
margin-left: auto;
margin-right: auto;
}
.site-header {
background: var(--rx-header-bg-color);
}
.site-footer {
background: var(--rx-footer-bg-color);
color: var(--rx-footer-text-color);
}
.site-footer a {
color: var(--rx-footer-text-color);
}
.rx-sticky-header-enabled .site-header {
position: sticky;
top: 0;
z-index: 999;
}
.rx-sticky-sidebar-enabled .widget-area {
position: sticky;
top: 90px;
}
.rx-back-to-top {
position: fixed;
right: 20px;
bottom: 20px;
z-index: 9999;
display: inline-flex;
align-items: center;
justify-content: center;
width: 44px;
height: 44px;
border-radius: 999px;
text-decoration: none;
background: var(--rx-primary-color);
color: #fff;
}
.rx-dark-mode {
--rx-body-bg-color: #0f172a;
--rx-body-text-color: #e5e7eb;
--rx-heading-color: #ffffff;
--rx-header-bg-color: #111827;
--rx-footer-bg-color: #020617;
}
';
$custom_css = rx_theme_get_option( 'custom_css' );
if ( ! empty( $custom_css ) ) {
$css .= "\n" . $custom_css;
}
echo '<style id="rx-theme-dynamic-css">' . wp_strip_all_tags( $css ) . '</style>' . "\n";
}
add_action( 'wp_head', 'rx_theme_dynamic_css', 99 );
/**
* Enqueue Google fonts if enabled.
*/
function rx_theme_enqueue_google_fonts() {
if ( ! rx_theme_get_option( 'enable_google_fonts' ) ) {
return;
}
$url = rx_theme_get_option( 'google_fonts_url' );
if ( empty( $url ) ) {
return;
}
wp_enqueue_style(
'rx-google-fonts',
esc_url( $url ),
array(),
null
);
}
add_action( 'wp_enqueue_scripts', 'rx_theme_enqueue_google_fonts' );
/**
* Output resource hints.
*/
function rx_theme_resource_hints() {
if ( rx_theme_get_option( 'enable_dns_prefetch' ) ) {
$urls = preg_split( '/\r\n|\r|\n/', rx_theme_get_option( 'dns_prefetch_urls' ) );
foreach ( $urls as $url ) {
$url = trim( $url );
if ( $url ) {
echo '<link rel="dns-prefetch" href="' . esc_url( $url ) . '">' . "\n";
}
}
}
if ( rx_theme_get_option( 'enable_preconnect' ) ) {
$urls = preg_split( '/\r\n|\r|\n/', rx_theme_get_option( 'preconnect_urls' ) );
foreach ( $urls as $url ) {
$url = trim( $url );
if ( $url ) {
echo '<link rel="preconnect" href="' . esc_url( $url ) . '" crossorigin>' . "\n";
}
}
}
if ( rx_theme_get_option( 'enable_preload_fonts' ) ) {
$urls = preg_split( '/\r\n|\r|\n/', rx_theme_get_option( 'preload_font_urls' ) );
foreach ( $urls as $url ) {
$url = trim( $url );
if ( $url ) {
echo '<link rel="preload" href="' . esc_url( $url ) . '" as="font" type="font/woff2" crossorigin>' . "\n";
}
}
}
}
add_action( 'wp_head', 'rx_theme_resource_hints', 1 );
/**
* Output verification tags.
*/
function rx_theme_verification_tags() {
$google = rx_theme_get_option( 'google_site_verification' );
$bing = rx_theme_get_option( 'bing_webmaster_code' );
if ( ! empty( $google ) ) {
echo '<meta name="google-site-verification" content="' . esc_attr( $google ) . '">' . "\n";
}
if ( ! empty( $bing ) ) {
echo '<meta name="msvalidate.01" content="' . esc_attr( $bing ) . '">' . "\n";
}
}
add_action( 'wp_head', 'rx_theme_verification_tags', 2 );
/**
* Output analytics scripts.
*/
function rx_theme_analytics_scripts() {
$ga_id = rx_theme_get_option( 'google_analytics_id' );
$gtm_id = rx_theme_get_option( 'google_tag_manager_id' );
$pixel = rx_theme_get_option( 'facebook_pixel_id' );
if ( ! empty( $gtm_id ) ) :
?>
<script>
(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','<?php echo esc_js( $gtm_id ); ?>');
</script>
<?php
endif;
if ( ! empty( $ga_id ) ) :
?>
<script async src="https://www.googletagmanager.com/gtag/js?id=<?php echo esc_attr( $ga_id ); ?>"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '<?php echo esc_js( $ga_id ); ?>');
</script>
<?php
endif;
if ( ! empty( $pixel ) ) :
?>
<script>
!function(f,b,e,v,n,t,s)
{if(f.fbq)return;n=f.fbq=function(){n.callMethod?
n.callMethod.apply(n,arguments):n.queue.push(arguments)};
if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';
n.queue=[];t=b.createElement(e);t.async=!0;
t.src=v;s=b.getElementsByTagName(e)[0];
s.parentNode.insertBefore(t,s)}(window, document,'script',
'https://connect.facebook.net/en_US/fbevents.js');
fbq('init', '<?php echo esc_js( $pixel ); ?>');
fbq('track', 'PageView');
</script>
<?php
endif;
}
add_action( 'wp_head', 'rx_theme_analytics_scripts', 20 );
/**
* Output custom header scripts.
*/
function rx_theme_custom_header_scripts() {
$scripts = rx_theme_get_option( 'header_scripts' );
if ( ! empty( $scripts ) ) {
echo "\n<!-- RX Header Scripts -->\n";
echo $scripts . "\n"; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
}
add_action( 'wp_head', 'rx_theme_custom_header_scripts', 100 );
/**
* Output footer scripts and custom JS.
*/
function rx_theme_custom_footer_scripts() {
$scripts = rx_theme_get_option( 'footer_scripts' );
$custom = rx_theme_get_option( 'custom_js' );
if ( ! empty( $scripts ) ) {
echo "\n<!-- RX Footer Scripts -->\n";
echo $scripts . "\n"; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
if ( ! empty( $custom ) ) {
echo "\n<script id=\"rx-custom-js\">\n";
echo $custom; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo "\n</script>\n";
}
}
add_action( 'wp_footer', 'rx_theme_custom_footer_scripts', 100 );
/**
* Add basic SEO meta tags.
*/
function rx_theme_basic_seo_tags() {
if ( ! rx_theme_get_option( 'enable_basic_seo' ) ) {
return;
}
if ( rx_theme_get_option( 'enable_noindex_search' ) && is_search() ) {
echo '<meta name="robots" content="noindex,follow">' . "\n";
}
if ( rx_theme_get_option( 'enable_noindex_404' ) && is_404() ) {
echo '<meta name="robots" content="noindex,follow">' . "\n";
}
if ( rx_theme_get_option( 'enable_meta_description' ) ) {
$description = '';
if ( is_singular() ) {
global $post;
if ( $post instanceof WP_Post ) {
$description = has_excerpt( $post ) ? get_the_excerpt( $post ) : wp_trim_words( wp_strip_all_tags( $post->post_content ), 28 );
}
}
if ( empty( $description ) ) {
$description = rx_theme_get_option( 'default_meta_description' );
}
if ( empty( $description ) ) {
$description = get_bloginfo( 'description' );
}
if ( ! empty( $description ) ) {
echo '<meta name="description" content="' . esc_attr( wp_strip_all_tags( $description ) ) . '">' . "\n";
}
}
if ( rx_theme_get_option( 'enable_og_tags' ) ) {
$title = wp_get_document_title();
$url = is_singular() ? get_permalink() : home_url( add_query_arg( array(), $GLOBALS['wp']->request ?? '' ) );
$description = rx_theme_get_option( 'default_meta_description' );
$image = rx_theme_get_option( 'og_default_image' );
if ( is_singular() ) {
global $post;
if ( $post instanceof WP_Post ) {
$description = has_excerpt( $post ) ? get_the_excerpt( $post ) : wp_trim_words( wp_strip_all_tags( $post->post_content ), 28 );
if ( has_post_thumbnail( $post ) ) {
$image = get_the_post_thumbnail_url( $post, 'large' );
}
}
}
echo '<meta property="og:title" content="' . esc_attr( $title ) . '">' . "\n";
echo '<meta property="og:type" content="' . ( is_singular() ? 'article' : 'website' ) . '">' . "\n";
echo '<meta property="og:url" content="' . esc_url( $url ) . '">' . "\n";
if ( ! empty( $description ) ) {
echo '<meta property="og:description" content="' . esc_attr( wp_strip_all_tags( $description ) ) . '">' . "\n";
}
if ( ! empty( $image ) ) {
echo '<meta property="og:image" content="' . esc_url( $image ) . '">' . "\n";
}
}
}
add_action( 'wp_head', 'rx_theme_basic_seo_tags', 5 );
/**
* Add JSON-LD schema.
*/
function rx_theme_schema_markup() {
if ( ! rx_theme_get_option( 'enable_schema' ) ) {
return;
}
$schema = array(
'@context' => 'https://schema.org',
'@type' => 'WebSite',
'name' => get_bloginfo( 'name' ),
'url' => home_url( '/' ),
);
if ( is_singular( 'post' ) ) {
global $post;
if ( $post instanceof WP_Post ) {
$schema = array(
'@context' => 'https://schema.org',
'@type' => 'Article',
'headline' => get_the_title( $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' => get_permalink( $post ),
);
if ( has_post_thumbnail( $post ) ) {
$schema['image'] = get_the_post_thumbnail_url( $post, 'large' );
}
}
}
echo '<script type="application/ld+json">' . wp_json_encode( $schema, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE ) . '</script>' . "\n";
}
add_action( 'wp_head', 'rx_theme_schema_markup', 30 );
/**
* Disable emojis.
*/
function rx_theme_disable_emojis() {
if ( ! rx_theme_get_option( 'disable_emoji_scripts' ) ) {
return;
}
remove_action( 'wp_head', 'print_emoji_detection_script', 7 );
remove_action( 'admin_print_scripts', 'print_emoji_detection_script' );
remove_action( 'wp_print_styles', 'print_emoji_styles' );
remove_action( 'admin_print_styles', 'print_emoji_styles' );
remove_filter( 'the_content_feed', 'wp_staticize_emoji' );
remove_filter( 'comment_text_rss', 'wp_staticize_emoji' );
remove_filter( 'wp_mail', 'wp_staticize_emoji_for_email' );
}
add_action( 'init', 'rx_theme_disable_emojis' );
/**
* Disable WP embed.
*/
function rx_theme_disable_embed() {
if ( ! rx_theme_get_option( 'disable_wp_embed' ) ) {
return;
}
wp_deregister_script( 'wp-embed' );
}
add_action( 'wp_footer', 'rx_theme_disable_embed' );
/**
* Remove WordPress version.
*
* @return string
*/
function rx_theme_remove_wp_version() {
if ( rx_theme_get_option( 'remove_wp_version' ) ) {
return '';
}
return get_bloginfo( 'version' );
}
add_filter( 'the_generator', 'rx_theme_remove_wp_version' );
/**
* Remove shortlink.
*/
function rx_theme_remove_shortlink() {
if ( rx_theme_get_option( 'remove_shortlink' ) ) {
remove_action( 'wp_head', 'wp_shortlink_wp_head', 10 );
remove_action( 'template_redirect', 'wp_shortlink_header', 11 );
}
}
add_action( 'init', 'rx_theme_remove_shortlink' );
/**
* Disable XML-RPC.
*
* @param bool $enabled Enabled.
* @return bool
*/
function rx_theme_disable_xmlrpc( $enabled ) {
if ( rx_theme_get_option( 'disable_xmlrpc' ) ) {
return false;
}
return $enabled;
}
add_filter( 'xmlrpc_enabled', 'rx_theme_disable_xmlrpc' );
/**
* Remove REST user links.
*
* @param array $response Response.
* @param object $user User.
* @param object $request Request.
* @return array
*/
function rx_theme_remove_rest_user_links( $response, $user, $request ) {
if ( rx_theme_get_option( 'disable_rest_user_links' ) && isset( $response->data['link'] ) ) {
unset( $response->data['link'] );
}
return $response;
}
add_filter( 'rest_prepare_user', 'rx_theme_remove_rest_user_links', 10, 3 );
/**
* Add defer or async to scripts.
*
* @param string $tag Script tag.
* @param string $handle Handle.
* @param string $src Source.
* @return string
*/
function rx_theme_script_loader_tag( $tag, $handle, $src ) {
if ( is_admin() ) {
return $tag;
}
$defer_enabled = rx_theme_get_option( 'enable_defer_js' );
$async_enabled = rx_theme_get_option( 'enable_async_js' );
if ( ! $defer_enabled && ! $async_enabled ) {
return $tag;
}
$defer_excludes = array_map( 'trim', explode( ',', rx_theme_get_option( 'defer_exclude_handles' ) ) );
$async_excludes = array_map( 'trim', explode( ',', rx_theme_get_option( 'async_exclude_handles' ) ) );
if ( $async_enabled && ! in_array( $handle, $async_excludes, true ) ) {
return str_replace( ' src', ' async src', $tag );
}
if ( $defer_enabled && ! in_array( $handle, $defer_excludes, true ) ) {
return str_replace( ' src', ' defer src', $tag );
}
return $tag;
}
add_filter( 'script_loader_tag', 'rx_theme_script_loader_tag', 10, 3 );
/**
* Lazy loading images.
*
* @param string $content Content.
* @return string
*/
function rx_theme_lazy_loading_content_images( $content ) {
if ( ! rx_theme_get_option( 'enable_lazy_loading' ) ) {
return $content;
}
if ( false === strpos( $content, '<img' ) ) {
return $content;
}
return preg_replace( '/<img(?![^>]+loading=)/i', '<img loading="lazy"', $content );
}
add_filter( 'the_content', 'rx_theme_lazy_loading_content_images' );
/**
* Excerpt length.
*
* @param int $length Length.
* @return int
*/
function rx_theme_excerpt_length( $length ) {
return absint( rx_theme_get_option( 'excerpt_length', $length ) );
}
add_filter( 'excerpt_length', 'rx_theme_excerpt_length' );
/**
* Excerpt more.
*
* @param string $more More.
* @return string
*/
function rx_theme_excerpt_more( $more ) {
return '...';
}
add_filter( 'excerpt_more', 'rx_theme_excerpt_more' );
/**
* Comment open control.
*
* @param bool $open Open.
* @param int $post_id Post ID.
* @return bool
*/
function rx_theme_comments_open_control( $open, $post_id ) {
if ( ! rx_theme_get_option( 'enable_comments' ) && is_singular() ) {
return false;
}
return $open;
}
add_filter( 'comments_open', 'rx_theme_comments_open_control', 10, 2 );
/**
* Get footer copyright with placeholders.
*
* @return string
*/
function rx_theme_get_footer_copyright() {
$text = rx_theme_get_option( 'footer_copyright' );
$text = str_replace(
array( '{year}', '{site_name}' ),
array( date_i18n( 'Y' ), get_bloginfo( 'name' ) ),
$text
);
return wp_kses_post( $text );
}
/**
* Render social links.
*/
function rx_theme_social_links() {
$socials = array(
'facebook_url' => 'Facebook',
'twitter_url' => 'X',
'linkedin_url' => 'LinkedIn',
'instagram_url' => 'Instagram',
'youtube_url' => 'YouTube',
'pinterest_url' => 'Pinterest',
'tiktok_url' => 'TikTok',
'github_url' => 'GitHub',
'telegram_url' => 'Telegram',
'whatsapp_url' => 'WhatsApp',
);
echo '<ul class="rx-social-links">';
foreach ( $socials as $key => $label ) {
$url = rx_theme_get_option( $key );
if ( ! empty( $url ) ) {
echo '<li><a href="' . esc_url( $url ) . '" target="_blank" rel="noopener noreferrer">' . esc_html( $label ) . '</a></li>';
}
}
echo '</ul>';
}
/**
* Render breadcrumb.
*/
function rx_theme_breadcrumbs() {
if ( ! rx_theme_get_option( 'enable_breadcrumbs' ) ) {
return;
}
if ( is_front_page() ) {
return;
}
echo '<nav class="rx-breadcrumbs" aria-label="' . esc_attr__( 'Breadcrumbs', 'rx-theme' ) . '">';
echo '<a href="' . esc_url( home_url( '/' ) ) . '">' . esc_html__( 'Home', 'rx-theme' ) . '</a>';
if ( is_category() || is_single() ) {
echo ' <span>/</span> ';
$category = get_the_category();
if ( ! empty( $category ) ) {
echo '<a href="' . esc_url( get_category_link( $category[0]->term_id ) ) . '">' . esc_html( $category[0]->name ) . '</a>';
}
if ( is_single() ) {
echo ' <span>/</span> ';
echo '<span>' . esc_html( get_the_title() ) . '</span>';
}
} elseif ( is_page() ) {
echo ' <span>/</span> ';
echo '<span>' . esc_html( get_the_title() ) . '</span>';
} elseif ( is_search() ) {
echo ' <span>/</span> ';
echo '<span>' . esc_html__( 'Search', 'rx-theme' ) . '</span>';
} elseif ( is_404() ) {
echo ' <span>/</span> ';
echo '<span>' . esc_html__( '404', 'rx-theme' ) . '</span>';
}
echo '</nav>';
}
/**
* Render ad slot.
*
* @param string $slot Slot key.
*/
function rx_theme_ad_slot( $slot ) {
if ( ! rx_theme_get_option( 'enable_ads' ) ) {
return;
}
$key = 'ad_' . $slot;
$code = rx_theme_get_option( $key );
if ( ! empty( $code ) ) {
echo '<div class="rx-ad rx-ad-' . esc_attr( $slot ) . '">';
echo $code; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo '</div>';
}
}
/**
* Add before and after content ads automatically.
*
* @param string $content Content.
* @return string
*/
function rx_theme_content_ads( $content ) {
if ( ! is_singular( 'post' ) || ! in_the_loop() || ! is_main_query() ) {
return $content;
}
if ( ! rx_theme_get_option( 'enable_ads' ) ) {
return $content;
}
ob_start();
rx_theme_ad_slot( 'before_content' );
$before = ob_get_clean();
ob_start();
rx_theme_ad_slot( 'after_content' );
$after = ob_get_clean();
return $before . $content . $after;
}
add_filter( 'the_content', 'rx_theme_content_ads', 8 );
/**
* Render related posts.
*
* @param int|null $post_id Post ID.
*/
function rx_theme_related_posts( $post_id = null ) {
if ( ! rx_theme_get_option( 'enable_related_posts' ) ) {
return;
}
$post_id = $post_id ? absint( $post_id ) : get_the_ID();
if ( ! $post_id ) {
return;
}
$categories = wp_get_post_categories( $post_id );
if ( empty( $categories ) ) {
return;
}
$query = new WP_Query(
array(
'post_type' => 'post',
'posts_per_page' => absint( rx_theme_get_option( 'related_posts_count', 3 ) ),
'post__not_in' => array( $post_id ),
'category__in' => $categories,
'ignore_sticky_posts' => true,
)
);
if ( ! $query->have_posts() ) {
wp_reset_postdata();
return;
}
echo '<section class="rx-related-posts">';
echo '<h2>' . esc_html__( 'Related Posts', 'rx-theme' ) . '</h2>';
echo '<div class="rx-related-posts-grid">';
while ( $query->have_posts() ) {
$query->the_post();
echo '<article class="rx-related-post">';
if ( has_post_thumbnail() ) {
echo '<a href="' . esc_url( get_permalink() ) . '">' . get_the_post_thumbnail( get_the_ID(), 'medium' ) . '</a>';
}
echo '<h3><a href="' . esc_url( get_permalink() ) . '">' . esc_html( get_the_title() ) . '</a></h3>';
echo '</article>';
}
echo '</div>';
echo '</section>';
wp_reset_postdata();
}
/**
* Render author box.
*/
function rx_theme_author_box() {
if ( ! rx_theme_get_option( 'enable_author_box' ) || ! is_single() ) {
return;
}
$author_id = get_the_author_meta( 'ID' );
echo '<section class="rx-author-box">';
echo get_avatar( $author_id, 80 );
echo '<div class="rx-author-info">';
echo '<h3>' . esc_html( get_the_author_meta( 'display_name', $author_id ) ) . '</h3>';
echo '<p>' . esc_html( get_the_author_meta( 'description', $author_id ) ) . '</p>';
echo '</div>';
echo '</section>';
}
/**
* WooCommerce product count.
*
* @param int $count Count.
* @return int
*/
function rx_theme_woo_products_per_page( $count ) {
return absint( rx_theme_get_option( 'woo_products_per_page', $count ) );
}
add_filter( 'loop_shop_per_page', 'rx_theme_woo_products_per_page', 20 );
/**
* WooCommerce columns.
*
* @param int $columns Columns.
* @return int
*/
function rx_theme_woo_columns( $columns ) {
return absint( rx_theme_get_option( 'woo_columns', $columns ) );
}
add_filter( 'loop_shop_columns', 'rx_theme_woo_columns' );
/**
* Back to top button.
*/
function rx_theme_back_to_top_button() {
if ( ! rx_theme_get_option( 'enable_back_to_top' ) && ! rx_theme_get_option( 'enable_footer_back_top' ) ) {
return;
}
echo '<a class="rx-back-to-top" href="#page" aria-label="' . esc_attr__( 'Back to top', 'rx-theme' ) . '">↑</a>';
}
add_action( 'wp_footer', 'rx_theme_back_to_top_button', 20 );
/**
* Preloader markup.
*/
function rx_theme_preloader_markup() {
if ( ! rx_theme_get_option( 'enable_preloader' ) ) {
return;
}
echo '<div id="rx-preloader" class="rx-preloader"><div class="rx-preloader-spinner"></div></div>';
}
add_action( 'wp_body_open', 'rx_theme_preloader_markup' );
/**
* Preloader script.
*/
function rx_theme_preloader_script() {
if ( ! rx_theme_get_option( 'enable_preloader' ) ) {
return;
}
?>
<script>
window.addEventListener('load', function(){
var preloader = document.getElementById('rx-preloader');
if(preloader){
preloader.style.opacity = '0';
setTimeout(function(){
preloader.remove();
}, 300);
}
});
</script>
<?php
}
add_action( 'wp_footer', 'rx_theme_preloader_script' );
/**
* Add Customizer settings linked to same option array.
*
* @param WP_Customize_Manager $wp_customize Customizer.
*/
function rx_theme_customize_register( $wp_customize ) {
$wp_customize->add_panel(
'rx_theme_panel',
array(
'title' => esc_html__( 'RX Theme Options', 'rx-theme' ),
'description' => esc_html__( 'RX Theme quick customization options.', 'rx-theme' ),
'priority' => 30,
)
);
$wp_customize->add_section(
'rx_theme_colors',
array(
'title' => esc_html__( 'RX Colors', 'rx-theme' ),
'panel' => 'rx_theme_panel',
)
);
$colors = array(
'primary_color' => 'Primary Color',
'secondary_color' => 'Secondary Color',
'accent_color' => 'Accent Color',
'body_bg_color' => 'Body Background Color',
'body_text_color' => 'Body Text Color',
'heading_color' => 'Heading Color',
'link_color' => 'Link Color',
'link_hover_color' => 'Link Hover Color',
'header_bg_color' => 'Header Background Color',
'footer_bg_color' => 'Footer Background Color',
'footer_text_color' => 'Footer Text Color',
);
foreach ( $colors as $key => $label ) {
$wp_customize->add_setting(
RX_THEME_OPTION_KEY . '[' . $key . ']',
array(
'type' => 'option',
'default' => rx_theme_get_option( $key ),
'sanitize_callback' => 'sanitize_hex_color',
)
);
$wp_customize->add_control(
new WP_Customize_Color_Control(
$wp_customize,
'rx_' . $key,
array(
'label' => esc_html( $label ),
'section' => 'rx_theme_colors',
'settings' => RX_THEME_OPTION_KEY . '[' . $key . ']',
)
)
);
}
$wp_customize->add_section(
'rx_theme_layout',
array(
'title' => esc_html__( 'RX Layout', 'rx-theme' ),
'panel' => 'rx_theme_panel',
)
);
$wp_customize->add_setting(
RX_THEME_OPTION_KEY . '[site_layout]',
array(
'type' => 'option',
'default' => rx_theme_get_option( 'site_layout' ),
'sanitize_callback' => function( $value ) {
return rx_theme_sanitize_select(
$value,
array( 'full-width', 'left-sidebar', 'right-sidebar', 'no-sidebar' ),
'right-sidebar'
);
},
)
);
$wp_customize->add_control(
'rx_site_layout',
array(
'label' => esc_html__( 'Site Layout', 'rx-theme' ),
'section' => 'rx_theme_layout',
'settings' => RX_THEME_OPTION_KEY . '[site_layout]',
'type' => 'select',
'choices' => array(
'full-width' => 'Full Width',
'left-sidebar' => 'Left Sidebar',
'right-sidebar' => 'Right Sidebar',
'no-sidebar' => 'No Sidebar',
),
)
);
}
add_action( 'customize_register', 'rx_theme_customize_register' );
/**
* Reset options by URL action.
*
* Example:
* /wp-admin/themes.php?page=rx-theme-options&rx_reset_options=1&_wpnonce=...
*/
function rx_theme_maybe_reset_options() {
if ( ! is_admin() || ! current_user_can( 'manage_options' ) ) {
return;
}
if ( ! isset( $_GET['rx_reset_options'] ) ) {
return;
}
check_admin_referer( 'rx_reset_theme_options' );
update_option( RX_THEME_OPTION_KEY, rx_theme_default_options() );
wp_safe_redirect( admin_url( 'themes.php?page=rx-theme-options&reset=success' ) );
exit;
}
add_action( 'admin_init', 'rx_theme_maybe_reset_options' );
Useful template calls
You can use these inside theme files:
<?php rx_theme_breadcrumbs(); ?>
<?php rx_theme_social_links(); ?>
<?php echo rx_theme_get_footer_copyright(); ?>
<?php rx_theme_related_posts(); ?>
<?php rx_theme_author_box(); ?>
<?php rx_theme_ad_slot( 'header' ); ?>
<?php rx_theme_ad_slot( 'sidebar' ); ?>
<?php rx_theme_ad_slot( 'footer' ); ?>
Recommended folder structure
rx-theme/
├── functions.php
├── style.css
├── header.php
├── footer.php
├── single.php
├── archive.php
├── inc/
│ └── options/
│ └── theme-options.php
This file creates a full admin panel under:
Appearance > RX Theme Options