disease-type.php

I’ll build this as a complete advanced WordPress taxonomy file for your rx-theme, focused on a medical “Disease Type” taxonomy: registration, labels, REST support, rewrite rules, admin columns, term meta, schema helpers, breadcrumbs/title helpers, and safe fallbacks.

Below is an advanced complete inc/taxonomies/disease-type.php file for your rx-theme. It creates a powerful hierarchical taxonomy named Disease Type for medical content. WordPress supports custom taxonomies through register_taxonomy(), including REST/Gutenberg support with show_in_rest, rewrite rules, and admin UI settings. Term metadata can be stored and retrieved with functions like get_term_meta(), and taxonomy admin columns can be customized with dynamic taxonomy column hooks.

Create this file:

<?php
/**
 * Disease Type Taxonomy
 *
 * File: inc/taxonomies/disease-type.php
 *
 * @package RxTheme
 * @version 1.0.0
 */

defined( 'ABSPATH' ) || exit;

if ( ! class_exists( 'Rx_Theme_Disease_Type_Taxonomy' ) ) :

final class Rx_Theme_Disease_Type_Taxonomy {

	/**
	 * Taxonomy slug.
	 */
	const TAXONOMY = 'disease_type';

	/**
	 * Main post type fallback.
	 *
	 * Change this if your main disease post type has another slug.
	 */
	const DEFAULT_POST_TYPE = 'post';

	/**
	 * Meta keys.
	 */
	const META_ICON              = '_rx_disease_type_icon';
	const META_COLOR             = '_rx_disease_type_color';
	const META_SEO_TITLE         = '_rx_disease_type_seo_title';
	const META_SEO_DESCRIPTION   = '_rx_disease_type_seo_description';
	const META_INTRO             = '_rx_disease_type_intro';
	const META_PRIORITY          = '_rx_disease_type_priority';
	const META_SCHEMA_NAME       = '_rx_disease_type_schema_name';
	const META_SCHEMA_DESC       = '_rx_disease_type_schema_description';
	const META_FEATURED_IMAGE_ID = '_rx_disease_type_featured_image_id';

	/**
	 * Boot hooks.
	 */
	public static function init() {
		add_action( 'init', array( __CLASS__, 'register_taxonomy' ), 5 );

		add_action( self::TAXONOMY . '_add_form_fields', array( __CLASS__, 'add_term_fields' ) );
		add_action( self::TAXONOMY . '_edit_form_fields', array( __CLASS__, 'edit_term_fields' ), 10, 2 );

		add_action( 'created_' . self::TAXONOMY, array( __CLASS__, 'save_term_meta' ) );
		add_action( 'edited_' . self::TAXONOMY, array( __CLASS__, 'save_term_meta' ) );

		add_filter( 'manage_edit-' . self::TAXONOMY . '_columns', array( __CLASS__, 'admin_columns' ) );
		add_filter( 'manage_' . self::TAXONOMY . '_custom_column', array( __CLASS__, 'admin_column_content' ), 10, 3 );
		add_filter( 'manage_edit-' . self::TAXONOMY . '_sortable_columns', array( __CLASS__, 'sortable_columns' ) );

		add_action( 'admin_enqueue_scripts', array( __CLASS__, 'admin_assets' ) );

		add_filter( 'term_link', array( __CLASS__, 'filter_term_link' ), 10, 3 );

		add_action( 'pre_get_posts', array( __CLASS__, 'taxonomy_archive_query' ) );

		add_filter( 'document_title_parts', array( __CLASS__, 'document_title_parts' ) );
		add_action( 'wp_head', array( __CLASS__, 'output_taxonomy_seo_meta' ), 2 );
		add_action( 'wp_head', array( __CLASS__, 'output_taxonomy_schema' ), 30 );

		add_action( 'rest_api_init', array( __CLASS__, 'register_rest_meta' ) );
	}

	/**
	 * Register Disease Type taxonomy.
	 */
	public static function register_taxonomy() {
		$post_types = self::get_supported_post_types();

		$labels = array(
			'name'                       => _x( 'Disease Types', 'taxonomy general name', 'rx-theme' ),
			'singular_name'              => _x( 'Disease Type', 'taxonomy singular name', 'rx-theme' ),
			'search_items'               => __( 'Search Disease Types', 'rx-theme' ),
			'popular_items'              => __( 'Popular Disease Types', 'rx-theme' ),
			'all_items'                  => __( 'All Disease Types', 'rx-theme' ),
			'parent_item'                => __( 'Parent Disease Type', 'rx-theme' ),
			'parent_item_colon'          => __( 'Parent Disease Type:', 'rx-theme' ),
			'edit_item'                  => __( 'Edit Disease Type', 'rx-theme' ),
			'view_item'                  => __( 'View Disease Type', 'rx-theme' ),
			'update_item'                => __( 'Update Disease Type', 'rx-theme' ),
			'add_new_item'               => __( 'Add New Disease Type', 'rx-theme' ),
			'new_item_name'              => __( 'New Disease Type Name', 'rx-theme' ),
			'separate_items_with_commas' => __( 'Separate disease types with commas', 'rx-theme' ),
			'add_or_remove_items'        => __( 'Add or remove disease types', 'rx-theme' ),
			'choose_from_most_used'      => __( 'Choose from the most used disease types', 'rx-theme' ),
			'not_found'                  => __( 'No disease types found.', 'rx-theme' ),
			'no_terms'                   => __( 'No disease types', 'rx-theme' ),
			'filter_by_item'             => __( 'Filter by disease type', 'rx-theme' ),
			'items_list_navigation'      => __( 'Disease types list navigation', 'rx-theme' ),
			'items_list'                 => __( 'Disease types list', 'rx-theme' ),
			'back_to_items'              => __( 'Back to disease types', 'rx-theme' ),
			'menu_name'                  => __( 'Disease Types', 'rx-theme' ),
		);

		$args = array(
			'labels'                => $labels,
			'description'           => __( 'Classifies diseases by medical type, body system, severity, origin, pathology, or clinical group.', 'rx-theme' ),
			'public'                => true,
			'publicly_queryable'    => true,
			'hierarchical'          => true,
			'show_ui'               => true,
			'show_in_menu'          => true,
			'show_in_nav_menus'     => true,
			'show_tagcloud'         => true,
			'show_in_quick_edit'    => true,
			'show_admin_column'     => true,
			'show_in_rest'          => true,
			'rest_base'             => 'disease-types',
			'rest_namespace'        => 'wp/v2',
			'rest_controller_class' => 'WP_REST_Terms_Controller',
			'query_var'             => self::TAXONOMY,
			'rewrite'               => array(
				'slug'         => 'disease-type',
				'with_front'   => false,
				'hierarchical' => true,
				'ep_mask'      => EP_NONE,
			),
			'capabilities'          => array(
				'manage_terms' => 'manage_categories',
				'edit_terms'   => 'manage_categories',
				'delete_terms' => 'manage_categories',
				'assign_terms' => 'edit_posts',
			),
			'default_term'          => array(
				'name'        => __( 'General Disease', 'rx-theme' ),
				'slug'        => 'general-disease',
				'description' => __( 'General disease classification.', 'rx-theme' ),
			),
			'sort'                  => true,
			'meta_box_cb'           => 'post_categories_meta_box',
		);

		register_taxonomy( self::TAXONOMY, $post_types, $args );
	}

	/**
	 * Supported post types.
	 */
	public static function get_supported_post_types() {
		$post_types = array( self::DEFAULT_POST_TYPE );

		if ( post_type_exists( 'disease' ) ) {
			$post_types[] = 'disease';
		}

		if ( post_type_exists( 'conditions' ) ) {
			$post_types[] = 'conditions';
		}

		if ( post_type_exists( 'medical_article' ) ) {
			$post_types[] = 'medical_article';
		}

		if ( post_type_exists( 'health_article' ) ) {
			$post_types[] = 'health_article';
		}

		/**
		 * Filter supported post types.
		 */
		return apply_filters( 'rx_theme_disease_type_post_types', array_unique( $post_types ) );
	}

	/**
	 * Register REST-visible term meta.
	 */
	public static function register_rest_meta() {
		$meta_fields = array(
			self::META_ICON => array(
				'type'              => 'string',
				'single'            => true,
				'sanitize_callback' => 'sanitize_text_field',
				'auth_callback'     => array( __CLASS__, 'rest_meta_auth' ),
				'show_in_rest'      => true,
			),
			self::META_COLOR => array(
				'type'              => 'string',
				'single'            => true,
				'sanitize_callback' => 'sanitize_hex_color',
				'auth_callback'     => array( __CLASS__, 'rest_meta_auth' ),
				'show_in_rest'      => true,
			),
			self::META_SEO_TITLE => array(
				'type'              => 'string',
				'single'            => true,
				'sanitize_callback' => 'sanitize_text_field',
				'auth_callback'     => array( __CLASS__, 'rest_meta_auth' ),
				'show_in_rest'      => true,
			),
			self::META_SEO_DESCRIPTION => array(
				'type'              => 'string',
				'single'            => true,
				'sanitize_callback' => 'sanitize_textarea_field',
				'auth_callback'     => array( __CLASS__, 'rest_meta_auth' ),
				'show_in_rest'      => true,
			),
			self::META_INTRO => array(
				'type'              => 'string',
				'single'            => true,
				'sanitize_callback' => 'wp_kses_post',
				'auth_callback'     => array( __CLASS__, 'rest_meta_auth' ),
				'show_in_rest'      => true,
			),
			self::META_PRIORITY => array(
				'type'              => 'integer',
				'single'            => true,
				'sanitize_callback' => 'absint',
				'auth_callback'     => array( __CLASS__, 'rest_meta_auth' ),
				'show_in_rest'      => true,
			),
			self::META_SCHEMA_NAME => array(
				'type'              => 'string',
				'single'            => true,
				'sanitize_callback' => 'sanitize_text_field',
				'auth_callback'     => array( __CLASS__, 'rest_meta_auth' ),
				'show_in_rest'      => true,
			),
			self::META_SCHEMA_DESC => array(
				'type'              => 'string',
				'single'            => true,
				'sanitize_callback' => 'sanitize_textarea_field',
				'auth_callback'     => array( __CLASS__, 'rest_meta_auth' ),
				'show_in_rest'      => true,
			),
			self::META_FEATURED_IMAGE_ID => array(
				'type'              => 'integer',
				'single'            => true,
				'sanitize_callback' => 'absint',
				'auth_callback'     => array( __CLASS__, 'rest_meta_auth' ),
				'show_in_rest'      => true,
			),
		);

		foreach ( $meta_fields as $key => $args ) {
			register_term_meta( self::TAXONOMY, $key, $args );
		}
	}

	/**
	 * REST meta permission.
	 */
	public static function rest_meta_auth() {
		return current_user_can( 'manage_categories' );
	}

	/**
	 * Add screen fields.
	 */
	public static function add_term_fields() {
		wp_nonce_field( 'rx_disease_type_meta_save', 'rx_disease_type_meta_nonce' );
		?>
		<div class="form-field rx-term-field">
			<label for="rx_disease_type_icon"><?php esc_html_e( 'Icon Class / Emoji', 'rx-theme' ); ?></label>
			<input type="text" name="rx_disease_type_icon" id="rx_disease_type_icon" value="" placeholder="🫀 or dashicons-heart">
			<p><?php esc_html_e( 'Example: 🫀, 🧠, dashicons-heart, dashicons-plus-alt.', 'rx-theme' ); ?></p>
		</div>

		<div class="form-field rx-term-field">
			<label for="rx_disease_type_color"><?php esc_html_e( 'Color', 'rx-theme' ); ?></label>
			<input type="text" name="rx_disease_type_color" id="rx_disease_type_color" value="#0ea5e9" class="rx-color-field">
			<p><?php esc_html_e( 'Used for badges, cards, archive heading, and frontend styling.', 'rx-theme' ); ?></p>
		</div>

		<div class="form-field rx-term-field">
			<label for="rx_disease_type_seo_title"><?php esc_html_e( 'SEO Title', 'rx-theme' ); ?></label>
			<input type="text" name="rx_disease_type_seo_title" id="rx_disease_type_seo_title" value="">
		</div>

		<div class="form-field rx-term-field">
			<label for="rx_disease_type_seo_description"><?php esc_html_e( 'SEO Description', 'rx-theme' ); ?></label>
			<textarea name="rx_disease_type_seo_description" id="rx_disease_type_seo_description" rows="4"></textarea>
		</div>

		<div class="form-field rx-term-field">
			<label for="rx_disease_type_intro"><?php esc_html_e( 'Archive Intro Text', 'rx-theme' ); ?></label>
			<textarea name="rx_disease_type_intro" id="rx_disease_type_intro" rows="5"></textarea>
			<p><?php esc_html_e( 'Shown above disease type archive content.', 'rx-theme' ); ?></p>
		</div>

		<div class="form-field rx-term-field">
			<label for="rx_disease_type_priority"><?php esc_html_e( 'Priority', 'rx-theme' ); ?></label>
			<input type="number" name="rx_disease_type_priority" id="rx_disease_type_priority" value="10" min="0" step="1">
		</div>

		<div class="form-field rx-term-field">
			<label for="rx_disease_type_schema_name"><?php esc_html_e( 'Schema Name', 'rx-theme' ); ?></label>
			<input type="text" name="rx_disease_type_schema_name" id="rx_disease_type_schema_name" value="">
		</div>

		<div class="form-field rx-term-field">
			<label for="rx_disease_type_schema_description"><?php esc_html_e( 'Schema Description', 'rx-theme' ); ?></label>
			<textarea name="rx_disease_type_schema_description" id="rx_disease_type_schema_description" rows="4"></textarea>
		</div>

		<div class="form-field rx-term-field">
			<label for="rx_disease_type_featured_image_id"><?php esc_html_e( 'Featured Image ID', 'rx-theme' ); ?></label>
			<input type="number" name="rx_disease_type_featured_image_id" id="rx_disease_type_featured_image_id" value="" min="0" step="1">
			<p><?php esc_html_e( 'Enter WordPress media attachment ID.', 'rx-theme' ); ?></p>
		</div>
		<?php
	}

	/**
	 * Edit screen fields.
	 */
	public static function edit_term_fields( $term ) {
		$icon        = self::get_meta( $term->term_id, self::META_ICON );
		$color       = self::get_meta( $term->term_id, self::META_COLOR );
		$seo_title   = self::get_meta( $term->term_id, self::META_SEO_TITLE );
		$seo_desc    = self::get_meta( $term->term_id, self::META_SEO_DESCRIPTION );
		$intro       = self::get_meta( $term->term_id, self::META_INTRO );
		$priority    = self::get_meta( $term->term_id, self::META_PRIORITY );
		$schema_name = self::get_meta( $term->term_id, self::META_SCHEMA_NAME );
		$schema_desc = self::get_meta( $term->term_id, self::META_SCHEMA_DESC );
		$image_id    = self::get_meta( $term->term_id, self::META_FEATURED_IMAGE_ID );

		wp_nonce_field( 'rx_disease_type_meta_save', 'rx_disease_type_meta_nonce' );
		?>
		<tr class="form-field rx-term-field">
			<th scope="row">
				<label for="rx_disease_type_icon"><?php esc_html_e( 'Icon Class / Emoji', 'rx-theme' ); ?></label>
			</th>
			<td>
				<input type="text" name="rx_disease_type_icon" id="rx_disease_type_icon" value="<?php echo esc_attr( $icon ); ?>">
				<p class="description"><?php esc_html_e( 'Example: 🫀, 🧠, dashicons-heart, dashicons-plus-alt.', 'rx-theme' ); ?></p>
			</td>
		</tr>

		<tr class="form-field rx-term-field">
			<th scope="row">
				<label for="rx_disease_type_color"><?php esc_html_e( 'Color', 'rx-theme' ); ?></label>
			</th>
			<td>
				<input type="text" name="rx_disease_type_color" id="rx_disease_type_color" class="rx-color-field" value="<?php echo esc_attr( $color ? $color : '#0ea5e9' ); ?>">
			</td>
		</tr>

		<tr class="form-field rx-term-field">
			<th scope="row">
				<label for="rx_disease_type_seo_title"><?php esc_html_e( 'SEO Title', 'rx-theme' ); ?></label>
			</th>
			<td>
				<input type="text" name="rx_disease_type_seo_title" id="rx_disease_type_seo_title" value="<?php echo esc_attr( $seo_title ); ?>" class="regular-text">
			</td>
		</tr>

		<tr class="form-field rx-term-field">
			<th scope="row">
				<label for="rx_disease_type_seo_description"><?php esc_html_e( 'SEO Description', 'rx-theme' ); ?></label>
			</th>
			<td>
				<textarea name="rx_disease_type_seo_description" id="rx_disease_type_seo_description" rows="4" class="large-text"><?php echo esc_textarea( $seo_desc ); ?></textarea>
			</td>
		</tr>

		<tr class="form-field rx-term-field">
			<th scope="row">
				<label for="rx_disease_type_intro"><?php esc_html_e( 'Archive Intro Text', 'rx-theme' ); ?></label>
			</th>
			<td>
				<textarea name="rx_disease_type_intro" id="rx_disease_type_intro" rows="6" class="large-text"><?php echo esc_textarea( $intro ); ?></textarea>
			</td>
		</tr>

		<tr class="form-field rx-term-field">
			<th scope="row">
				<label for="rx_disease_type_priority"><?php esc_html_e( 'Priority', 'rx-theme' ); ?></label>
			</th>
			<td>
				<input type="number" name="rx_disease_type_priority" id="rx_disease_type_priority" value="<?php echo esc_attr( $priority ? $priority : 10 ); ?>" min="0" step="1">
			</td>
		</tr>

		<tr class="form-field rx-term-field">
			<th scope="row">
				<label for="rx_disease_type_schema_name"><?php esc_html_e( 'Schema Name', 'rx-theme' ); ?></label>
			</th>
			<td>
				<input type="text" name="rx_disease_type_schema_name" id="rx_disease_type_schema_name" value="<?php echo esc_attr( $schema_name ); ?>" class="regular-text">
			</td>
		</tr>

		<tr class="form-field rx-term-field">
			<th scope="row">
				<label for="rx_disease_type_schema_description"><?php esc_html_e( 'Schema Description', 'rx-theme' ); ?></label>
			</th>
			<td>
				<textarea name="rx_disease_type_schema_description" id="rx_disease_type_schema_description" rows="4" class="large-text"><?php echo esc_textarea( $schema_desc ); ?></textarea>
			</td>
		</tr>

		<tr class="form-field rx-term-field">
			<th scope="row">
				<label for="rx_disease_type_featured_image_id"><?php esc_html_e( 'Featured Image ID', 'rx-theme' ); ?></label>
			</th>
			<td>
				<input type="number" name="rx_disease_type_featured_image_id" id="rx_disease_type_featured_image_id" value="<?php echo esc_attr( absint( $image_id ) ); ?>" min="0" step="1">
				<?php
				if ( $image_id ) {
					echo '<div class="rx-term-image-preview" style="margin-top:10px;">';
					echo wp_get_attachment_image( absint( $image_id ), 'thumbnail' );
					echo '</div>';
				}
				?>
			</td>
		</tr>
		<?php
	}

	/**
	 * Save term meta.
	 */
	public static function save_term_meta( $term_id ) {
		if ( ! isset( $_POST['rx_disease_type_meta_nonce'] ) ) {
			return;
		}

		$nonce = sanitize_text_field( wp_unslash( $_POST['rx_disease_type_meta_nonce'] ) );

		if ( ! wp_verify_nonce( $nonce, 'rx_disease_type_meta_save' ) ) {
			return;
		}

		if ( ! current_user_can( 'manage_categories' ) ) {
			return;
		}

		$fields = array(
			self::META_ICON              => array( 'field' => 'rx_disease_type_icon', 'sanitize' => 'sanitize_text_field' ),
			self::META_COLOR             => array( 'field' => 'rx_disease_type_color', 'sanitize' => 'sanitize_hex_color' ),
			self::META_SEO_TITLE         => array( 'field' => 'rx_disease_type_seo_title', 'sanitize' => 'sanitize_text_field' ),
			self::META_SEO_DESCRIPTION   => array( 'field' => 'rx_disease_type_seo_description', 'sanitize' => 'sanitize_textarea_field' ),
			self::META_INTRO             => array( 'field' => 'rx_disease_type_intro', 'sanitize' => 'wp_kses_post' ),
			self::META_PRIORITY          => array( 'field' => 'rx_disease_type_priority', 'sanitize' => 'absint' ),
			self::META_SCHEMA_NAME       => array( 'field' => 'rx_disease_type_schema_name', 'sanitize' => 'sanitize_text_field' ),
			self::META_SCHEMA_DESC       => array( 'field' => 'rx_disease_type_schema_description', 'sanitize' => 'sanitize_textarea_field' ),
			self::META_FEATURED_IMAGE_ID => array( 'field' => 'rx_disease_type_featured_image_id', 'sanitize' => 'absint' ),
		);

		foreach ( $fields as $meta_key => $data ) {
			$field = $data['field'];

			if ( ! isset( $_POST[ $field ] ) ) {
				continue;
			}

			$value = wp_unslash( $_POST[ $field ] );

			if ( is_callable( $data['sanitize'] ) ) {
				$value = call_user_func( $data['sanitize'], $value );
			}

			if ( self::META_COLOR === $meta_key && empty( $value ) ) {
				$value = '#0ea5e9';
			}

			update_term_meta( $term_id, $meta_key, $value );
		}
	}

	/**
	 * Get safe term meta.
	 */
	public static function get_meta( $term_id, $key, $default = '' ) {
		$value = get_term_meta( absint( $term_id ), $key, true );

		if ( '' === $value || null === $value ) {
			return $default;
		}

		return $value;
	}

	/**
	 * Admin columns.
	 */
	public static function admin_columns( $columns ) {
		$new_columns = array();

		if ( isset( $columns['cb'] ) ) {
			$new_columns['cb'] = $columns['cb'];
		}

		$new_columns['rx_icon']     = __( 'Icon', 'rx-theme' );
		$new_columns['name']        = __( 'Name', 'rx-theme' );
		$new_columns['rx_color']    = __( 'Color', 'rx-theme' );
		$new_columns['rx_priority'] = __( 'Priority', 'rx-theme' );
		$new_columns['rx_image']    = __( 'Image', 'rx-theme' );
		$new_columns['slug']        = __( 'Slug', 'rx-theme' );
		$new_columns['posts']       = __( 'Count', 'rx-theme' );

		return $new_columns;
	}

	/**
	 * Admin column content.
	 */
	public static function admin_column_content( $content, $column_name, $term_id ) {
		switch ( $column_name ) {
			case 'rx_icon':
				$icon = self::get_meta( $term_id, self::META_ICON );
				if ( $icon ) {
					$content = '<span style="font-size:22px;">' . esc_html( $icon ) . '</span>';
				} else {
					$content = '&mdash;';
				}
				break;

			case 'rx_color':
				$color = self::get_meta( $term_id, self::META_COLOR, '#0ea5e9' );
				$content = '<span style="display:inline-block;width:22px;height:22px;border-radius:50%;background:' . esc_attr( $color ) . ';border:1px solid #ddd;vertical-align:middle;"></span> ';
				$content .= '<code>' . esc_html( $color ) . '</code>';
				break;

			case 'rx_priority':
				$content = absint( self::get_meta( $term_id, self::META_PRIORITY, 10 ) );
				break;

			case 'rx_image':
				$image_id = absint( self::get_meta( $term_id, self::META_FEATURED_IMAGE_ID ) );
				if ( $image_id ) {
					$content = wp_get_attachment_image( $image_id, array( 48, 48 ) );
				} else {
					$content = '&mdash;';
				}
				break;
		}

		return $content;
	}

	/**
	 * Sortable columns.
	 */
	public static function sortable_columns( $columns ) {
		$columns['rx_priority'] = 'rx_priority';
		return $columns;
	}

	/**
	 * Admin assets.
	 */
	public static function admin_assets( $hook ) {
		$screen = get_current_screen();

		if ( ! $screen || self::TAXONOMY !== $screen->taxonomy ) {
			return;
		}

		wp_enqueue_style( 'wp-color-picker' );
		wp_enqueue_script( 'wp-color-picker' );

		$inline = "
			jQuery(document).ready(function($){
				$('.rx-color-field').wpColorPicker();
			});
		";

		wp_add_inline_script( 'wp-color-picker', $inline );
	}

	/**
	 * Optional term link filter.
	 */
	public static function filter_term_link( $url, $term, $taxonomy ) {
		if ( self::TAXONOMY !== $taxonomy ) {
			return $url;
		}

		return $url;
	}

	/**
	 * Improve taxonomy archive query.
	 */
	public static function taxonomy_archive_query( $query ) {
		if ( is_admin() || ! $query->is_main_query() ) {
			return;
		}

		if ( $query->is_tax( self::TAXONOMY ) ) {
			$query->set( 'posts_per_page', absint( apply_filters( 'rx_disease_type_archive_posts_per_page', 12 ) ) );
			$query->set( 'ignore_sticky_posts', true );
		}
	}

	/**
	 * Custom document title.
	 */
	public static function document_title_parts( $title ) {
		if ( ! is_tax( self::TAXONOMY ) ) {
			return $title;
		}

		$term = get_queried_object();

		if ( ! $term || is_wp_error( $term ) ) {
			return $title;
		}

		$seo_title = self::get_meta( $term->term_id, self::META_SEO_TITLE );

		if ( $seo_title ) {
			$title['title'] = $seo_title;
		}

		return $title;
	}

	/**
	 * Output taxonomy SEO meta.
	 */
	public static function output_taxonomy_seo_meta() {
		if ( ! is_tax( self::TAXONOMY ) ) {
			return;
		}

		$term = get_queried_object();

		if ( ! $term || is_wp_error( $term ) ) {
			return;
		}

		$description = self::get_meta( $term->term_id, self::META_SEO_DESCRIPTION );

		if ( ! $description ) {
			$description = term_description( $term->term_id, self::TAXONOMY );
			$description = wp_strip_all_tags( $description );
		}

		if ( $description ) {
			echo "\n" . '<meta name="description" content="' . esc_attr( wp_trim_words( $description, 28, '' ) ) . '">' . "\n";
		}

		$color = self::get_meta( $term->term_id, self::META_COLOR, '#0ea5e9' );
		echo '<meta name="theme-color" content="' . esc_attr( $color ) . '">' . "\n";
	}

	/**
	 * Output MedicalWebPage schema for taxonomy archive.
	 */
	public static function output_taxonomy_schema() {
		if ( ! is_tax( self::TAXONOMY ) ) {
			return;
		}

		$term = get_queried_object();

		if ( ! $term || is_wp_error( $term ) ) {
			return;
		}

		$name = self::get_meta( $term->term_id, self::META_SCHEMA_NAME );

		if ( ! $name ) {
			$name = single_term_title( '', false );
		}

		$description = self::get_meta( $term->term_id, self::META_SCHEMA_DESC );

		if ( ! $description ) {
			$description = self::get_meta( $term->term_id, self::META_SEO_DESCRIPTION );
		}

		if ( ! $description ) {
			$description = wp_strip_all_tags( term_description( $term->term_id, self::TAXONOMY ) );
		}

		$image_id  = absint( self::get_meta( $term->term_id, self::META_FEATURED_IMAGE_ID ) );
		$image_url = $image_id ? wp_get_attachment_image_url( $image_id, 'full' ) : '';

		$schema = array(
			'@context'    => 'https://schema.org',
			'@type'       => 'MedicalWebPage',
			'name'        => wp_strip_all_tags( $name ),
			'description' => wp_strip_all_tags( $description ),
			'url'         => get_term_link( $term ),
			'isPartOf'    => array(
				'@type' => 'WebSite',
				'name'  => get_bloginfo( 'name' ),
				'url'   => home_url( '/' ),
			),
			'about'       => array(
				'@type' => 'MedicalCondition',
				'name'  => wp_strip_all_tags( $term->name ),
			),
		);

		if ( $image_url ) {
			$schema['image'] = esc_url_raw( $image_url );
		}

		echo "\n" . '<script type="application/ld+json">' . wp_json_encode( $schema, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE ) . '</script>' . "\n";
	}

	/**
	 * Get all disease types.
	 */
	public static function get_terms( $args = array() ) {
		$defaults = array(
			'taxonomy'   => self::TAXONOMY,
			'hide_empty' => false,
			'orderby'    => 'name',
			'order'      => 'ASC',
		);

		return get_terms( wp_parse_args( $args, $defaults ) );
	}

	/**
	 * Get top-level disease types.
	 */
	public static function get_top_level_terms() {
		return self::get_terms(
			array(
				'parent' => 0,
			)
		);
	}

	/**
	 * Render disease type badge.
	 */
	public static function render_badge( $term_id, $echo = true ) {
		$term = get_term( absint( $term_id ), self::TAXONOMY );

		if ( ! $term || is_wp_error( $term ) ) {
			return '';
		}

		$color = self::get_meta( $term->term_id, self::META_COLOR, '#0ea5e9' );
		$icon  = self::get_meta( $term->term_id, self::META_ICON );

		$html  = '<a class="rx-disease-type-badge" href="' . esc_url( get_term_link( $term ) ) . '" style="--rx-disease-type-color:' . esc_attr( $color ) . ';">';
		$html .= $icon ? '<span class="rx-disease-type-badge__icon">' . esc_html( $icon ) . '</span>' : '';
		$html .= '<span class="rx-disease-type-badge__name">' . esc_html( $term->name ) . '</span>';
		$html .= '</a>';

		if ( $echo ) {
			echo wp_kses_post( $html );
		}

		return $html;
	}

	/**
	 * Render badges for current post.
	 */
	public static function render_post_badges( $post_id = 0, $echo = true ) {
		$post_id = $post_id ? absint( $post_id ) : get_the_ID();

		if ( ! $post_id ) {
			return '';
		}

		$terms = get_the_terms( $post_id, self::TAXONOMY );

		if ( empty( $terms ) || is_wp_error( $terms ) ) {
			return '';
		}

		$html = '<div class="rx-disease-type-badges">';

		foreach ( $terms as $term ) {
			$html .= self::render_badge( $term->term_id, false );
		}

		$html .= '</div>';

		if ( $echo ) {
			echo wp_kses_post( $html );
		}

		return $html;
	}

	/**
	 * Render archive intro.
	 */
	public static function render_archive_intro( $echo = true ) {
		if ( ! is_tax( self::TAXONOMY ) ) {
			return '';
		}

		$term = get_queried_object();

		if ( ! $term || is_wp_error( $term ) ) {
			return '';
		}

		$intro = self::get_meta( $term->term_id, self::META_INTRO );

		if ( ! $intro ) {
			$intro = term_description( $term->term_id, self::TAXONOMY );
		}

		if ( ! $intro ) {
			return '';
		}

		$html = '<div class="rx-disease-type-archive-intro">';
		$html .= wpautop( wp_kses_post( $intro ) );
		$html .= '</div>';

		if ( $echo ) {
			echo wp_kses_post( $html );
		}

		return $html;
	}

	/**
	 * Render disease type card grid.
	 */
	public static function render_term_grid( $args = array(), $echo = true ) {
		$defaults = array(
			'parent'     => 0,
			'hide_empty' => false,
			'orderby'    => 'name',
			'order'      => 'ASC',
		);

		$args  = wp_parse_args( $args, $defaults );
		$terms = self::get_terms( $args );

		if ( empty( $terms ) || is_wp_error( $terms ) ) {
			return '';
		}

		$html = '<div class="rx-disease-type-grid">';

		foreach ( $terms as $term ) {
			$color    = self::get_meta( $term->term_id, self::META_COLOR, '#0ea5e9' );
			$icon     = self::get_meta( $term->term_id, self::META_ICON );
			$image_id = absint( self::get_meta( $term->term_id, self::META_FEATURED_IMAGE_ID ) );
			$intro    = self::get_meta( $term->term_id, self::META_INTRO );

			if ( ! $intro ) {
				$intro = $term->description;
			}

			$html .= '<article class="rx-disease-type-card" style="--rx-disease-type-color:' . esc_attr( $color ) . ';">';
			$html .= '<a href="' . esc_url( get_term_link( $term ) ) . '" class="rx-disease-type-card__link">';

			if ( $image_id ) {
				$html .= '<div class="rx-disease-type-card__image">';
				$html .= wp_get_attachment_image( $image_id, 'medium' );
				$html .= '</div>';
			}

			$html .= '<div class="rx-disease-type-card__body">';

			if ( $icon ) {
				$html .= '<div class="rx-disease-type-card__icon">' . esc_html( $icon ) . '</div>';
			}

			$html .= '<h3 class="rx-disease-type-card__title">' . esc_html( $term->name ) . '</h3>';

			if ( $intro ) {
				$html .= '<p class="rx-disease-type-card__text">' . esc_html( wp_trim_words( wp_strip_all_tags( $intro ), 22 ) ) . '</p>';
			}

			$html .= '<span class="rx-disease-type-card__count">';
			$html .= sprintf(
				esc_html( _n( '%s article', '%s articles', absint( $term->count ), 'rx-theme' ) ),
				number_format_i18n( absint( $term->count ) )
			);
			$html .= '</span>';

			$html .= '</div>';
			$html .= '</a>';
			$html .= '</article>';
		}

		$html .= '</div>';

		if ( $echo ) {
			echo wp_kses_post( $html );
		}

		return $html;
	}

	/**
	 * Breadcrumb data for a disease type.
	 */
	public static function get_term_breadcrumbs( $term_id ) {
		$term = get_term( absint( $term_id ), self::TAXONOMY );

		if ( ! $term || is_wp_error( $term ) ) {
			return array();
		}

		$breadcrumbs = array();
		$ancestors   = array_reverse( get_ancestors( $term->term_id, self::TAXONOMY ) );

		foreach ( $ancestors as $ancestor_id ) {
			$ancestor = get_term( $ancestor_id, self::TAXONOMY );

			if ( $ancestor && ! is_wp_error( $ancestor ) ) {
				$breadcrumbs[] = array(
					'name' => $ancestor->name,
					'url'  => get_term_link( $ancestor ),
				);
			}
		}

		$breadcrumbs[] = array(
			'name' => $term->name,
			'url'  => get_term_link( $term ),
		);

		return $breadcrumbs;
	}

	/**
	 * Render breadcrumb HTML.
	 */
	public static function render_breadcrumbs( $term_id = 0, $echo = true ) {
		if ( ! $term_id && is_tax( self::TAXONOMY ) ) {
			$term = get_queried_object();
			$term_id = $term && ! is_wp_error( $term ) ? $term->term_id : 0;
		}

		if ( ! $term_id ) {
			return '';
		}

		$items = self::get_term_breadcrumbs( $term_id );

		if ( empty( $items ) ) {
			return '';
		}

		$html = '<nav class="rx-disease-type-breadcrumbs" aria-label="' . esc_attr__( 'Disease type breadcrumbs', 'rx-theme' ) . '">';
		$html .= '<a href="' . esc_url( home_url( '/' ) ) . '">' . esc_html__( 'Home', 'rx-theme' ) . '</a>';

		foreach ( $items as $item ) {
			$html .= ' <span aria-hidden="true">›</span> ';
			$html .= '<a href="' . esc_url( $item['url'] ) . '">' . esc_html( $item['name'] ) . '</a>';
		}

		$html .= '</nav>';

		if ( $echo ) {
			echo wp_kses_post( $html );
		}

		return $html;
	}

	/**
	 * Body class helper.
	 */
	public static function body_class( $classes ) {
		if ( is_tax( self::TAXONOMY ) ) {
			$classes[] = 'rx-disease-type-archive';
		}

		return $classes;
	}
}

Rx_Theme_Disease_Type_Taxonomy::init();

endif;

if ( ! function_exists( 'rx_disease_type_badges' ) ) {
	/**
	 * Template helper: show disease type badges for post.
	 */
	function rx_disease_type_badges( $post_id = 0, $echo = true ) {
		return Rx_Theme_Disease_Type_Taxonomy::render_post_badges( $post_id, $echo );
	}
}

if ( ! function_exists( 'rx_disease_type_grid' ) ) {
	/**
	 * Template helper: show disease type grid.
	 */
	function rx_disease_type_grid( $args = array(), $echo = true ) {
		return Rx_Theme_Disease_Type_Taxonomy::render_term_grid( $args, $echo );
	}
}

if ( ! function_exists( 'rx_disease_type_archive_intro' ) ) {
	/**
	 * Template helper: show archive intro.
	 */
	function rx_disease_type_archive_intro( $echo = true ) {
		return Rx_Theme_Disease_Type_Taxonomy::render_archive_intro( $echo );
	}
}

if ( ! function_exists( 'rx_disease_type_breadcrumbs' ) ) {
	/**
	 * Template helper: show disease type breadcrumbs.
	 */
	function rx_disease_type_breadcrumbs( $term_id = 0, $echo = true ) {
		return Rx_Theme_Disease_Type_Taxonomy::render_breadcrumbs( $term_id, $echo );
	}
}

add_filter( 'body_class', array( 'Rx_Theme_Disease_Type_Taxonomy', 'body_class' ) );

Now include it in your theme functions.php:

/**
 * Load RX taxonomy files.
 */
$rx_taxonomy_files = array(
	get_template_directory() . '/inc/taxonomies/disease-type.php',
);

foreach ( $rx_taxonomy_files as $rx_taxonomy_file ) {
	if ( file_exists( $rx_taxonomy_file ) ) {
		require_once $rx_taxonomy_file;
	}
}

Optional CSS for style.css:

.rx-disease-type-badges {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	margin: 12px 0;
}

.rx-disease-type-badge {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 6px 12px;
	border-radius: 999px;
	background: color-mix(in srgb, var(--rx-disease-type-color, #0ea5e9) 12%, white);
	color: var(--rx-disease-type-color, #0ea5e9);
	border: 1px solid color-mix(in srgb, var(--rx-disease-type-color, #0ea5e9) 35%, white);
	font-size: 14px;
	font-weight: 600;
	text-decoration: none;
}

.rx-disease-type-badge:hover {
	background: var(--rx-disease-type-color, #0ea5e9);
	color: #fff;
}

.rx-disease-type-grid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
	gap: 24px;
	margin: 32px 0;
}

.rx-disease-type-card {
	border: 1px solid #e5e7eb;
	border-radius: 18px;
	overflow: hidden;
	background: #fff;
	box-shadow: 0 10px 30px rgba(15, 23, 42, 0.06);
	transition: transform 0.25s ease, box-shadow 0.25s ease;
}

.rx-disease-type-card:hover {
	transform: translateY(-4px);
	box-shadow: 0 16px 45px rgba(15, 23, 42, 0.1);
}

.rx-disease-type-card__link {
	display: block;
	color: inherit;
	text-decoration: none;
}

.rx-disease-type-card__image img {
	display: block;
	width: 100%;
	height: 180px;
	object-fit: cover;
}

.rx-disease-type-card__body {
	padding: 20px;
	border-top: 4px solid var(--rx-disease-type-color, #0ea5e9);
}

.rx-disease-type-card__icon {
	font-size: 34px;
	line-height: 1;
	margin-bottom: 12px;
}

.rx-disease-type-card__title {
	margin: 0 0 10px;
	font-size: 20px;
	line-height: 1.3;
}

.rx-disease-type-card__text {
	margin: 0 0 14px;
	color: #475569;
	font-size: 15px;
	line-height: 1.7;
}

.rx-disease-type-card__count {
	display: inline-flex;
	font-size: 13px;
	font-weight: 700;
	color: var(--rx-disease-type-color, #0ea5e9);
}

.rx-disease-type-archive-intro {
	margin: 24px 0;
	padding: 24px;
	border-left: 5px solid #0ea5e9;
	background: #f8fafc;
	border-radius: 14px;
}

.rx-disease-type-breadcrumbs {
	margin: 16px 0;
	font-size: 14px;
	color: #64748b;
}

.rx-disease-type-breadcrumbs a {
	color: #0f172a;
	text-decoration: none;
}

.rx-disease-type-breadcrumbs a:hover {
	color: #0ea5e9;
}

Use in template files:

<?php rx_disease_type_badges(); ?>

For a disease type grid:

<?php rx_disease_type_grid(); ?>

For taxonomy archive intro:

<?php rx_disease_type_archive_intro(); ?>

For breadcrumbs:

<?php rx_disease_type_breadcrumbs(); ?>

After adding this file, go to WordPress Dashboard → Settings → Permalinks → Save Changes once to refresh rewrite rules.

Leave a Reply

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