theme-setup.php

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(
			'&copy; %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.

Leave a Reply

Your email address will not be published. Required fields are marked *