I’ll build this as a full advanced WordPress widget file for
inc/widgets/author-box-widget.php, including admin fields, sanitization, schema-ready output, social links, avatar controls, author meta, CTA buttons, styling options, and safe fallbacks.Below is a complete advanced inc/widgets/author-box-widget.php file for your RX Theme.
<?php
/**
* RX Theme - Advanced Author Box Widget
*
* File: inc/widgets/author-box-widget.php
*
* Features:
* - Current post author or selected author
* - Avatar, name, role, bio, website, email, post count
* - Social links
* - Latest author posts
* - CTA button
* - Follow button/link
* - Schema.org Person JSON-LD
* - Layout/style options
* - Safe escaping and sanitization
*
* @package RX_Theme
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'RX_Author_Box_Widget' ) ) :
class RX_Author_Box_Widget extends WP_Widget {
/**
* Default widget settings.
*/
private function defaults() {
return array(
'title' => esc_html__( 'About the Author', 'rx-theme' ),
'author_source' => 'current_post_author', // current_post_author, selected_author, current_user
'author_id' => 0,
'show_avatar' => 1,
'avatar_size' => 120,
'avatar_shape' => 'circle', // circle, rounded, square
'show_name' => 1,
'show_display_role' => 1,
'custom_role_label' => '',
'show_bio' => 1,
'bio_limit' => 280,
'show_website' => 1,
'show_email' => 0,
'show_post_count' => 1,
'show_registered_date' => 0,
'show_socials' => 1,
'social_style' => 'text', // text, button
'show_latest_posts' => 0,
'latest_posts_count' => 3,
'show_cta' => 0,
'cta_text' => esc_html__( 'View Author Profile', 'rx-theme' ),
'cta_url' => '',
'show_follow' => 0,
'follow_text' => esc_html__( 'Follow Author', 'rx-theme' ),
'follow_url' => '',
'layout' => 'center', // center, left, compact
'box_style' => 'card', // card, minimal, border
'background_color' => '#ffffff',
'text_color' => '#222222',
'accent_color' => '#0073aa',
'enable_schema' => 1,
'extra_class' => '',
);
}
/**
* Constructor.
*/
public function __construct() {
parent::__construct(
'rx_author_box_widget',
esc_html__( 'RX Advanced Author Box', 'rx-theme' ),
array(
'classname' => 'rx_author_box_widget',
'description' => esc_html__( 'Advanced author profile box with avatar, bio, social links, CTA, latest posts, and schema.', 'rx-theme' ),
'customize_selective_refresh' => true,
)
);
}
/**
* Get setting with default.
*/
private function get_setting( $instance, $key ) {
$defaults = $this->defaults();
return isset( $instance[ $key ] ) ? $instance[ $key ] : $defaults[ $key ];
}
/**
* Validate checkbox value.
*/
private function checkbox( $value ) {
return ! empty( $value ) ? 1 : 0;
}
/**
* Sanitize color.
*/
private function sanitize_color( $color, $fallback = '#ffffff' ) {
$color = sanitize_hex_color( $color );
return $color ? $color : $fallback;
}
/**
* Trim text by character length.
*/
private function trim_text( $text, $limit = 280 ) {
$text = wp_strip_all_tags( $text );
$limit = absint( $limit );
if ( $limit < 1 ) {
return $text;
}
if ( function_exists( 'mb_strlen' ) && function_exists( 'mb_substr' ) ) {
if ( mb_strlen( $text ) > $limit ) {
return mb_substr( $text, 0, $limit ) . '...';
}
return $text;
}
if ( strlen( $text ) > $limit ) {
return substr( $text, 0, $limit ) . '...';
}
return $text;
}
/**
* Get author ID based on widget source.
*/
private function get_author_id( $instance ) {
$source = $this->get_setting( $instance, 'author_source' );
$author_id = absint( $this->get_setting( $instance, 'author_id' ) );
if ( 'selected_author' === $source && $author_id > 0 ) {
return $author_id;
}
if ( 'current_user' === $source && is_user_logged_in() ) {
return get_current_user_id();
}
if ( 'current_post_author' === $source && is_singular() ) {
$post_id = get_the_ID();
if ( $post_id ) {
$post_author = absint( get_post_field( 'post_author', $post_id ) );
if ( $post_author > 0 ) {
return $post_author;
}
}
}
if ( $author_id > 0 ) {
return $author_id;
}
$admin_users = get_users(
array(
'role__in' => array( 'administrator', 'editor', 'author' ),
'number' => 1,
'fields' => array( 'ID' ),
)
);
if ( ! empty( $admin_users[0]->ID ) ) {
return absint( $admin_users[0]->ID );
}
return 0;
}
/**
* Get author role.
*/
private function get_author_role( $user ) {
if ( empty( $user->roles ) || ! is_array( $user->roles ) ) {
return '';
}
$roles = wp_roles();
$role_key = $user->roles[0];
if ( isset( $roles->roles[ $role_key ]['name'] ) ) {
return translate_user_role( $roles->roles[ $role_key ]['name'] );
}
return ucfirst( str_replace( '_', ' ', $role_key ) );
}
/**
* Get social links from user meta.
*/
private function get_social_links( $author_id ) {
$socials = array(
'facebook' => array(
'label' => esc_html__( 'Facebook', 'rx-theme' ),
'keys' => array( 'facebook', 'facebook_url', 'rx_facebook' ),
),
'twitter' => array(
'label' => esc_html__( 'X / Twitter', 'rx-theme' ),
'keys' => array( 'twitter', 'twitter_url', 'x_url', 'rx_twitter' ),
),
'linkedin' => array(
'label' => esc_html__( 'LinkedIn', 'rx-theme' ),
'keys' => array( 'linkedin', 'linkedin_url', 'rx_linkedin' ),
),
'instagram' => array(
'label' => esc_html__( 'Instagram', 'rx-theme' ),
'keys' => array( 'instagram', 'instagram_url', 'rx_instagram' ),
),
'youtube' => array(
'label' => esc_html__( 'YouTube', 'rx-theme' ),
'keys' => array( 'youtube', 'youtube_url', 'rx_youtube' ),
),
'github' => array(
'label' => esc_html__( 'GitHub', 'rx-theme' ),
'keys' => array( 'github', 'github_url', 'rx_github' ),
),
'website' => array(
'label' => esc_html__( 'Website', 'rx-theme' ),
'keys' => array( 'website', 'user_url' ),
),
);
$output = array();
foreach ( $socials as $slug => $data ) {
$url = '';
foreach ( $data['keys'] as $key ) {
if ( 'user_url' === $key ) {
$user_data = get_userdata( $author_id );
$value = $user_data ? $user_data->user_url : '';
} else {
$value = get_user_meta( $author_id, $key, true );
}
if ( ! empty( $value ) ) {
$url = esc_url_raw( $value );
break;
}
}
if ( ! empty( $url ) ) {
$output[ $slug ] = array(
'label' => $data['label'],
'url' => $url,
);
}
}
return $output;
}
/**
* Widget front-end output.
*/
public function widget( $args, $instance ) {
$instance = wp_parse_args( (array) $instance, $this->defaults() );
$author_id = $this->get_author_id( $instance );
if ( ! $author_id ) {
return;
}
$user = get_userdata( $author_id );
if ( ! $user ) {
return;
}
$title = apply_filters( 'widget_title', $this->get_setting( $instance, 'title' ), $instance, $this->id_base );
$display_name = $user->display_name ? $user->display_name : $user->user_login;
$bio = get_user_meta( $author_id, 'description', true );
$website = $user->user_url;
$email = $user->user_email;
$posts_url = get_author_posts_url( $author_id );
$post_count = count_user_posts( $author_id, 'post', true );
$avatar_size = absint( $this->get_setting( $instance, 'avatar_size' ) );
$avatar_size = $avatar_size ? $avatar_size : 120;
$layout = sanitize_html_class( $this->get_setting( $instance, 'layout' ) );
$box_style = sanitize_html_class( $this->get_setting( $instance, 'box_style' ) );
$avatar_shape = sanitize_html_class( $this->get_setting( $instance, 'avatar_shape' ) );
$extra_class = sanitize_html_class( $this->get_setting( $instance, 'extra_class' ) );
$bg_color = $this->sanitize_color( $this->get_setting( $instance, 'background_color' ), '#ffffff' );
$text_color = $this->sanitize_color( $this->get_setting( $instance, 'text_color' ), '#222222' );
$accent_color = $this->sanitize_color( $this->get_setting( $instance, 'accent_color' ), '#0073aa' );
$classes = array(
'rx-author-box',
'rx-author-layout-' . $layout,
'rx-author-style-' . $box_style,
'rx-author-avatar-' . $avatar_shape,
);
if ( ! empty( $extra_class ) ) {
$classes[] = $extra_class;
}
$style = sprintf(
'--rx-author-bg:%1$s;--rx-author-text:%2$s;--rx-author-accent:%3$s;',
esc_attr( $bg_color ),
esc_attr( $text_color ),
esc_attr( $accent_color )
);
echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
if ( ! empty( $title ) ) {
echo $args['before_title'] . esc_html( $title ) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
?>
<div class="<?php echo esc_attr( implode( ' ', $classes ) ); ?>" style="<?php echo esc_attr( $style ); ?>">
<style>
.rx-author-box {
background: var(--rx-author-bg);
color: var(--rx-author-text);
padding: 24px;
margin: 0 0 24px;
box-sizing: border-box;
position: relative;
overflow: hidden;
}
.rx-author-style-card {
border-radius: 18px;
box-shadow: 0 10px 30px rgba(0,0,0,.08);
}
.rx-author-style-border {
border: 1px solid rgba(0,0,0,.12);
border-radius: 14px;
}
.rx-author-style-minimal {
padding: 12px 0;
background: transparent;
}
.rx-author-layout-center {
text-align: center;
}
.rx-author-layout-left {
text-align: left;
}
.rx-author-layout-compact {
display: flex;
gap: 16px;
align-items: flex-start;
text-align: left;
}
.rx-author-avatar-wrap {
margin-bottom: 16px;
line-height: 0;
}
.rx-author-layout-compact .rx-author-avatar-wrap {
margin-bottom: 0;
flex: 0 0 auto;
}
.rx-author-avatar-wrap img {
max-width: 100%;
height: auto;
border: 4px solid rgba(255,255,255,.9);
box-shadow: 0 6px 18px rgba(0,0,0,.12);
}
.rx-author-avatar-circle img {
border-radius: 999px;
}
.rx-author-avatar-rounded img {
border-radius: 18px;
}
.rx-author-avatar-square img {
border-radius: 0;
}
.rx-author-name {
font-size: 22px;
line-height: 1.25;
margin: 0 0 6px;
color: var(--rx-author-text);
}
.rx-author-name a {
color: inherit;
text-decoration: none;
}
.rx-author-name a:hover {
color: var(--rx-author-accent);
}
.rx-author-role {
font-size: 14px;
font-weight: 600;
color: var(--rx-author-accent);
margin-bottom: 10px;
}
.rx-author-bio {
font-size: 15px;
line-height: 1.7;
margin: 10px 0 14px;
}
.rx-author-meta {
display: flex;
flex-wrap: wrap;
gap: 8px;
justify-content: center;
margin: 14px 0;
font-size: 13px;
}
.rx-author-layout-left .rx-author-meta,
.rx-author-layout-compact .rx-author-meta {
justify-content: flex-start;
}
.rx-author-meta span,
.rx-author-meta a {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 5px 10px;
border-radius: 999px;
background: rgba(0,0,0,.05);
color: inherit;
text-decoration: none;
}
.rx-author-meta a:hover {
background: var(--rx-author-accent);
color: #fff;
}
.rx-author-socials {
display: flex;
flex-wrap: wrap;
gap: 8px;
justify-content: center;
margin: 16px 0;
}
.rx-author-layout-left .rx-author-socials,
.rx-author-layout-compact .rx-author-socials {
justify-content: flex-start;
}
.rx-author-socials a {
text-decoration: none;
color: var(--rx-author-accent);
font-size: 14px;
font-weight: 600;
}
.rx-author-socials.rx-social-button a {
padding: 7px 12px;
border-radius: 999px;
background: var(--rx-author-accent);
color: #fff;
}
.rx-author-actions {
display: flex;
flex-wrap: wrap;
gap: 10px;
justify-content: center;
margin-top: 16px;
}
.rx-author-layout-left .rx-author-actions,
.rx-author-layout-compact .rx-author-actions {
justify-content: flex-start;
}
.rx-author-button {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 10px 16px;
border-radius: 999px;
background: var(--rx-author-accent);
color: #fff !important;
text-decoration: none;
font-size: 14px;
font-weight: 700;
transition: transform .2s ease, opacity .2s ease;
}
.rx-author-button:hover {
opacity: .9;
transform: translateY(-1px);
}
.rx-author-button.secondary {
background: transparent;
color: var(--rx-author-accent) !important;
border: 1px solid var(--rx-author-accent);
}
.rx-author-latest {
margin-top: 20px;
padding-top: 16px;
border-top: 1px solid rgba(0,0,0,.08);
}
.rx-author-latest-title {
font-size: 16px;
margin: 0 0 10px;
}
.rx-author-latest ul {
list-style: none;
margin: 0;
padding: 0;
}
.rx-author-latest li {
margin: 0 0 8px;
padding: 0;
}
.rx-author-latest a {
color: inherit;
text-decoration: none;
font-weight: 600;
}
.rx-author-latest a:hover {
color: var(--rx-author-accent);
}
@media (max-width: 600px) {
.rx-author-layout-compact {
display: block;
text-align: center;
}
.rx-author-layout-compact .rx-author-avatar-wrap {
margin-bottom: 16px;
}
.rx-author-layout-compact .rx-author-meta,
.rx-author-layout-compact .rx-author-socials,
.rx-author-layout-compact .rx-author-actions {
justify-content: center;
}
}
</style>
<?php if ( $this->checkbox( $this->get_setting( $instance, 'show_avatar' ) ) ) : ?>
<div class="rx-author-avatar-wrap">
<a href="<?php echo esc_url( $posts_url ); ?>" aria-label="<?php echo esc_attr( sprintf( __( 'View all posts by %s', 'rx-theme' ), $display_name ) ); ?>">
<?php
echo get_avatar(
$author_id,
$avatar_size,
'',
$display_name,
array(
'class' => 'rx-author-avatar-img',
)
);
?>
</a>
</div>
<?php endif; ?>
<div class="rx-author-content">
<?php if ( $this->checkbox( $this->get_setting( $instance, 'show_name' ) ) ) : ?>
<h3 class="rx-author-name">
<a href="<?php echo esc_url( $posts_url ); ?>">
<?php echo esc_html( $display_name ); ?>
</a>
</h3>
<?php endif; ?>
<?php
$role_label = $this->get_setting( $instance, 'custom_role_label' );
$role_label = $role_label ? $role_label : $this->get_author_role( $user );
?>
<?php if ( $this->checkbox( $this->get_setting( $instance, 'show_display_role' ) ) && ! empty( $role_label ) ) : ?>
<div class="rx-author-role">
<?php echo esc_html( $role_label ); ?>
</div>
<?php endif; ?>
<?php if ( $this->checkbox( $this->get_setting( $instance, 'show_bio' ) ) && ! empty( $bio ) ) : ?>
<div class="rx-author-bio">
<?php echo esc_html( $this->trim_text( $bio, $this->get_setting( $instance, 'bio_limit' ) ) ); ?>
</div>
<?php endif; ?>
<div class="rx-author-meta">
<?php if ( $this->checkbox( $this->get_setting( $instance, 'show_post_count' ) ) ) : ?>
<span class="rx-author-post-count">
<?php
printf(
esc_html( _n( '%s Article', '%s Articles', $post_count, 'rx-theme' ) ),
esc_html( number_format_i18n( $post_count ) )
);
?>
</span>
<?php endif; ?>
<?php if ( $this->checkbox( $this->get_setting( $instance, 'show_website' ) ) && ! empty( $website ) ) : ?>
<a class="rx-author-website" href="<?php echo esc_url( $website ); ?>" target="_blank" rel="nofollow noopener noreferrer">
<?php esc_html_e( 'Website', 'rx-theme' ); ?>
</a>
<?php endif; ?>
<?php if ( $this->checkbox( $this->get_setting( $instance, 'show_email' ) ) && ! empty( $email ) ) : ?>
<a class="rx-author-email" href="<?php echo esc_url( 'mailto:' . antispambot( $email ) ); ?>">
<?php esc_html_e( 'Email', 'rx-theme' ); ?>
</a>
<?php endif; ?>
<?php if ( $this->checkbox( $this->get_setting( $instance, 'show_registered_date' ) ) ) : ?>
<span class="rx-author-registered">
<?php
printf(
esc_html__( 'Joined %s', 'rx-theme' ),
esc_html( date_i18n( get_option( 'date_format' ), strtotime( $user->user_registered ) ) )
);
?>
</span>
<?php endif; ?>
</div>
<?php
$social_links = $this->get_social_links( $author_id );
$social_style = sanitize_html_class( $this->get_setting( $instance, 'social_style' ) );
?>
<?php if ( $this->checkbox( $this->get_setting( $instance, 'show_socials' ) ) && ! empty( $social_links ) ) : ?>
<div class="rx-author-socials rx-social-<?php echo esc_attr( $social_style ); ?>">
<?php foreach ( $social_links as $social_key => $social ) : ?>
<a class="rx-social-link rx-social-<?php echo esc_attr( $social_key ); ?>" href="<?php echo esc_url( $social['url'] ); ?>" target="_blank" rel="nofollow noopener noreferrer">
<?php echo esc_html( $social['label'] ); ?>
</a>
<?php endforeach; ?>
</div>
<?php endif; ?>
<?php if ( $this->checkbox( $this->get_setting( $instance, 'show_cta' ) ) || $this->checkbox( $this->get_setting( $instance, 'show_follow' ) ) ) : ?>
<div class="rx-author-actions">
<?php
$cta_url = $this->get_setting( $instance, 'cta_url' );
$cta_url = $cta_url ? $cta_url : $posts_url;
?>
<?php if ( $this->checkbox( $this->get_setting( $instance, 'show_cta' ) ) ) : ?>
<a class="rx-author-button" href="<?php echo esc_url( $cta_url ); ?>">
<?php echo esc_html( $this->get_setting( $instance, 'cta_text' ) ); ?>
</a>
<?php endif; ?>
<?php if ( $this->checkbox( $this->get_setting( $instance, 'show_follow' ) ) && $this->get_setting( $instance, 'follow_url' ) ) : ?>
<a class="rx-author-button secondary" href="<?php echo esc_url( $this->get_setting( $instance, 'follow_url' ) ); ?>" target="_blank" rel="nofollow noopener noreferrer">
<?php echo esc_html( $this->get_setting( $instance, 'follow_text' ) ); ?>
</a>
<?php endif; ?>
</div>
<?php endif; ?>
<?php if ( $this->checkbox( $this->get_setting( $instance, 'show_latest_posts' ) ) ) : ?>
<?php
$latest_count = absint( $this->get_setting( $instance, 'latest_posts_count' ) );
$latest_count = $latest_count ? $latest_count : 3;
$latest_posts = new WP_Query(
array(
'author' => $author_id,
'post_type' => 'post',
'post_status' => 'publish',
'posts_per_page' => $latest_count,
'ignore_sticky_posts' => true,
'no_found_rows' => true,
)
);
?>
<?php if ( $latest_posts->have_posts() ) : ?>
<div class="rx-author-latest">
<h4 class="rx-author-latest-title">
<?php esc_html_e( 'Latest Articles', 'rx-theme' ); ?>
</h4>
<ul>
<?php while ( $latest_posts->have_posts() ) : ?>
<?php $latest_posts->the_post(); ?>
<li>
<a href="<?php the_permalink(); ?>">
<?php the_title(); ?>
</a>
</li>
<?php endwhile; ?>
</ul>
</div>
<?php endif; ?>
<?php wp_reset_postdata(); ?>
<?php endif; ?>
</div>
<?php if ( $this->checkbox( $this->get_setting( $instance, 'enable_schema' ) ) ) : ?>
<?php
$schema = array(
'@context' => 'https://schema.org',
'@type' => 'Person',
'name' => $display_name,
'url' => $posts_url,
);
if ( ! empty( $bio ) ) {
$schema['description'] = wp_strip_all_tags( $bio );
}
if ( ! empty( $website ) ) {
$schema['sameAs'] = array_values(
wp_list_pluck( $social_links, 'url' )
);
if ( empty( $schema['sameAs'] ) ) {
$schema['sameAs'] = array( esc_url_raw( $website ) );
}
}
$avatar_url = get_avatar_url( $author_id, array( 'size' => 300 ) );
if ( $avatar_url ) {
$schema['image'] = esc_url_raw( $avatar_url );
}
?>
<script type="application/ld+json">
<?php echo wp_json_encode( $schema, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE ); ?>
</script>
<?php endif; ?>
</div>
<?php
echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
/**
* Widget admin form.
*/
public function form( $instance ) {
$instance = wp_parse_args( (array) $instance, $this->defaults() );
$users = get_users(
array(
'orderby' => 'display_name',
'order' => 'ASC',
'fields' => array( 'ID', 'display_name', 'user_login' ),
)
);
?>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>">
<?php esc_html_e( 'Title:', 'rx-theme' ); ?>
</label>
<input class="widefat"
id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"
name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>"
type="text"
value="<?php echo esc_attr( $this->get_setting( $instance, 'title' ) ); ?>">
</p>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'author_source' ) ); ?>">
<?php esc_html_e( 'Author Source:', 'rx-theme' ); ?>
</label>
<select class="widefat"
id="<?php echo esc_attr( $this->get_field_id( 'author_source' ) ); ?>"
name="<?php echo esc_attr( $this->get_field_name( 'author_source' ) ); ?>">
<option value="current_post_author" <?php selected( $this->get_setting( $instance, 'author_source' ), 'current_post_author' ); ?>>
<?php esc_html_e( 'Current Post Author', 'rx-theme' ); ?>
</option>
<option value="selected_author" <?php selected( $this->get_setting( $instance, 'author_source' ), 'selected_author' ); ?>>
<?php esc_html_e( 'Selected Author', 'rx-theme' ); ?>
</option>
<option value="current_user" <?php selected( $this->get_setting( $instance, 'author_source' ), 'current_user' ); ?>>
<?php esc_html_e( 'Current Logged-in User', 'rx-theme' ); ?>
</option>
</select>
</p>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'author_id' ) ); ?>">
<?php esc_html_e( 'Select Author:', 'rx-theme' ); ?>
</label>
<select class="widefat"
id="<?php echo esc_attr( $this->get_field_id( 'author_id' ) ); ?>"
name="<?php echo esc_attr( $this->get_field_name( 'author_id' ) ); ?>">
<option value="0"><?php esc_html_e( 'Auto / Default', 'rx-theme' ); ?></option>
<?php foreach ( $users as $user ) : ?>
<option value="<?php echo esc_attr( $user->ID ); ?>" <?php selected( absint( $this->get_setting( $instance, 'author_id' ) ), $user->ID ); ?>>
<?php echo esc_html( $user->display_name ? $user->display_name : $user->user_login ); ?>
</option>
<?php endforeach; ?>
</select>
</p>
<hr>
<p>
<input class="checkbox" type="checkbox"
id="<?php echo esc_attr( $this->get_field_id( 'show_avatar' ) ); ?>"
name="<?php echo esc_attr( $this->get_field_name( 'show_avatar' ) ); ?>"
value="1" <?php checked( $this->get_setting( $instance, 'show_avatar' ), 1 ); ?>>
<label for="<?php echo esc_attr( $this->get_field_id( 'show_avatar' ) ); ?>">
<?php esc_html_e( 'Show Avatar', 'rx-theme' ); ?>
</label>
</p>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'avatar_size' ) ); ?>">
<?php esc_html_e( 'Avatar Size:', 'rx-theme' ); ?>
</label>
<input class="small-text"
id="<?php echo esc_attr( $this->get_field_id( 'avatar_size' ) ); ?>"
name="<?php echo esc_attr( $this->get_field_name( 'avatar_size' ) ); ?>"
type="number"
min="40"
max="300"
value="<?php echo esc_attr( absint( $this->get_setting( $instance, 'avatar_size' ) ) ); ?>">
<span><?php esc_html_e( 'px', 'rx-theme' ); ?></span>
</p>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'avatar_shape' ) ); ?>">
<?php esc_html_e( 'Avatar Shape:', 'rx-theme' ); ?>
</label>
<select class="widefat"
id="<?php echo esc_attr( $this->get_field_id( 'avatar_shape' ) ); ?>"
name="<?php echo esc_attr( $this->get_field_name( 'avatar_shape' ) ); ?>">
<option value="circle" <?php selected( $this->get_setting( $instance, 'avatar_shape' ), 'circle' ); ?>><?php esc_html_e( 'Circle', 'rx-theme' ); ?></option>
<option value="rounded" <?php selected( $this->get_setting( $instance, 'avatar_shape' ), 'rounded' ); ?>><?php esc_html_e( 'Rounded', 'rx-theme' ); ?></option>
<option value="square" <?php selected( $this->get_setting( $instance, 'avatar_shape' ), 'square' ); ?>><?php esc_html_e( 'Square', 'rx-theme' ); ?></option>
</select>
</p>
<hr>
<?php
$checkboxes = array(
'show_name' => esc_html__( 'Show Name', 'rx-theme' ),
'show_display_role' => esc_html__( 'Show Role / Label', 'rx-theme' ),
'show_bio' => esc_html__( 'Show Bio', 'rx-theme' ),
'show_website' => esc_html__( 'Show Website', 'rx-theme' ),
'show_email' => esc_html__( 'Show Email', 'rx-theme' ),
'show_post_count' => esc_html__( 'Show Post Count', 'rx-theme' ),
'show_registered_date' => esc_html__( 'Show Registered Date', 'rx-theme' ),
'show_socials' => esc_html__( 'Show Social Links', 'rx-theme' ),
'show_latest_posts' => esc_html__( 'Show Latest Posts', 'rx-theme' ),
'show_cta' => esc_html__( 'Show CTA Button', 'rx-theme' ),
'show_follow' => esc_html__( 'Show Follow Button', 'rx-theme' ),
'enable_schema' => esc_html__( 'Enable Person Schema JSON-LD', 'rx-theme' ),
);
?>
<?php foreach ( $checkboxes as $key => $label ) : ?>
<p>
<input class="checkbox" type="checkbox"
id="<?php echo esc_attr( $this->get_field_id( $key ) ); ?>"
name="<?php echo esc_attr( $this->get_field_name( $key ) ); ?>"
value="1" <?php checked( $this->get_setting( $instance, $key ), 1 ); ?>>
<label for="<?php echo esc_attr( $this->get_field_id( $key ) ); ?>">
<?php echo esc_html( $label ); ?>
</label>
</p>
<?php endforeach; ?>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'custom_role_label' ) ); ?>">
<?php esc_html_e( 'Custom Role Label:', 'rx-theme' ); ?>
</label>
<input class="widefat"
id="<?php echo esc_attr( $this->get_field_id( 'custom_role_label' ) ); ?>"
name="<?php echo esc_attr( $this->get_field_name( 'custom_role_label' ) ); ?>"
type="text"
value="<?php echo esc_attr( $this->get_setting( $instance, 'custom_role_label' ) ); ?>"
placeholder="<?php esc_attr_e( 'Example: Medical Author, Editor, Doctor', 'rx-theme' ); ?>">
</p>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'bio_limit' ) ); ?>">
<?php esc_html_e( 'Bio Character Limit:', 'rx-theme' ); ?>
</label>
<input class="small-text"
id="<?php echo esc_attr( $this->get_field_id( 'bio_limit' ) ); ?>"
name="<?php echo esc_attr( $this->get_field_name( 'bio_limit' ) ); ?>"
type="number"
min="50"
max="2000"
value="<?php echo esc_attr( absint( $this->get_setting( $instance, 'bio_limit' ) ) ); ?>">
</p>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'latest_posts_count' ) ); ?>">
<?php esc_html_e( 'Latest Posts Count:', 'rx-theme' ); ?>
</label>
<input class="small-text"
id="<?php echo esc_attr( $this->get_field_id( 'latest_posts_count' ) ); ?>"
name="<?php echo esc_attr( $this->get_field_name( 'latest_posts_count' ) ); ?>"
type="number"
min="1"
max="10"
value="<?php echo esc_attr( absint( $this->get_setting( $instance, 'latest_posts_count' ) ) ); ?>">
</p>
<hr>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'cta_text' ) ); ?>">
<?php esc_html_e( 'CTA Text:', 'rx-theme' ); ?>
</label>
<input class="widefat"
id="<?php echo esc_attr( $this->get_field_id( 'cta_text' ) ); ?>"
name="<?php echo esc_attr( $this->get_field_name( 'cta_text' ) ); ?>"
type="text"
value="<?php echo esc_attr( $this->get_setting( $instance, 'cta_text' ) ); ?>">
</p>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'cta_url' ) ); ?>">
<?php esc_html_e( 'CTA URL:', 'rx-theme' ); ?>
</label>
<input class="widefat"
id="<?php echo esc_attr( $this->get_field_id( 'cta_url' ) ); ?>"
name="<?php echo esc_attr( $this->get_field_name( 'cta_url' ) ); ?>"
type="url"
value="<?php echo esc_url( $this->get_setting( $instance, 'cta_url' ) ); ?>">
</p>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'follow_text' ) ); ?>">
<?php esc_html_e( 'Follow Text:', 'rx-theme' ); ?>
</label>
<input class="widefat"
id="<?php echo esc_attr( $this->get_field_id( 'follow_text' ) ); ?>"
name="<?php echo esc_attr( $this->get_field_name( 'follow_text' ) ); ?>"
type="text"
value="<?php echo esc_attr( $this->get_setting( $instance, 'follow_text' ) ); ?>">
</p>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'follow_url' ) ); ?>">
<?php esc_html_e( 'Follow URL:', 'rx-theme' ); ?>
</label>
<input class="widefat"
id="<?php echo esc_attr( $this->get_field_id( 'follow_url' ) ); ?>"
name="<?php echo esc_attr( $this->get_field_name( 'follow_url' ) ); ?>"
type="url"
value="<?php echo esc_url( $this->get_setting( $instance, 'follow_url' ) ); ?>">
</p>
<hr>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'layout' ) ); ?>">
<?php esc_html_e( 'Layout:', 'rx-theme' ); ?>
</label>
<select class="widefat"
id="<?php echo esc_attr( $this->get_field_id( 'layout' ) ); ?>"
name="<?php echo esc_attr( $this->get_field_name( 'layout' ) ); ?>">
<option value="center" <?php selected( $this->get_setting( $instance, 'layout' ), 'center' ); ?>><?php esc_html_e( 'Center', 'rx-theme' ); ?></option>
<option value="left" <?php selected( $this->get_setting( $instance, 'layout' ), 'left' ); ?>><?php esc_html_e( 'Left', 'rx-theme' ); ?></option>
<option value="compact" <?php selected( $this->get_setting( $instance, 'layout' ), 'compact' ); ?>><?php esc_html_e( 'Compact', 'rx-theme' ); ?></option>
</select>
</p>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'box_style' ) ); ?>">
<?php esc_html_e( 'Box Style:', 'rx-theme' ); ?>
</label>
<select class="widefat"
id="<?php echo esc_attr( $this->get_field_id( 'box_style' ) ); ?>"
name="<?php echo esc_attr( $this->get_field_name( 'box_style' ) ); ?>">
<option value="card" <?php selected( $this->get_setting( $instance, 'box_style' ), 'card' ); ?>><?php esc_html_e( 'Card', 'rx-theme' ); ?></option>
<option value="border" <?php selected( $this->get_setting( $instance, 'box_style' ), 'border' ); ?>><?php esc_html_e( 'Border', 'rx-theme' ); ?></option>
<option value="minimal" <?php selected( $this->get_setting( $instance, 'box_style' ), 'minimal' ); ?>><?php esc_html_e( 'Minimal', 'rx-theme' ); ?></option>
</select>
</p>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'social_style' ) ); ?>">
<?php esc_html_e( 'Social Style:', 'rx-theme' ); ?>
</label>
<select class="widefat"
id="<?php echo esc_attr( $this->get_field_id( 'social_style' ) ); ?>"
name="<?php echo esc_attr( $this->get_field_name( 'social_style' ) ); ?>">
<option value="text" <?php selected( $this->get_setting( $instance, 'social_style' ), 'text' ); ?>><?php esc_html_e( 'Text', 'rx-theme' ); ?></option>
<option value="button" <?php selected( $this->get_setting( $instance, 'social_style' ), 'button' ); ?>><?php esc_html_e( 'Button', 'rx-theme' ); ?></option>
</select>
</p>
<p>
<label><?php esc_html_e( 'Background Color:', 'rx-theme' ); ?></label>
<input class="widefat"
name="<?php echo esc_attr( $this->get_field_name( 'background_color' ) ); ?>"
type="text"
value="<?php echo esc_attr( $this->get_setting( $instance, 'background_color' ) ); ?>">
</p>
<p>
<label><?php esc_html_e( 'Text Color:', 'rx-theme' ); ?></label>
<input class="widefat"
name="<?php echo esc_attr( $this->get_field_name( 'text_color' ) ); ?>"
type="text"
value="<?php echo esc_attr( $this->get_setting( $instance, 'text_color' ) ); ?>">
</p>
<p>
<label><?php esc_html_e( 'Accent Color:', 'rx-theme' ); ?></label>
<input class="widefat"
name="<?php echo esc_attr( $this->get_field_name( 'accent_color' ) ); ?>"
type="text"
value="<?php echo esc_attr( $this->get_setting( $instance, 'accent_color' ) ); ?>">
</p>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'extra_class' ) ); ?>">
<?php esc_html_e( 'Extra CSS Class:', 'rx-theme' ); ?>
</label>
<input class="widefat"
id="<?php echo esc_attr( $this->get_field_id( 'extra_class' ) ); ?>"
name="<?php echo esc_attr( $this->get_field_name( 'extra_class' ) ); ?>"
type="text"
value="<?php echo esc_attr( $this->get_setting( $instance, 'extra_class' ) ); ?>">
</p>
<?php
}
/**
* Save widget settings.
*/
public function update( $new_instance, $old_instance ) {
$defaults = $this->defaults();
$instance = array();
$instance['title'] = sanitize_text_field( $new_instance['title'] ?? $defaults['title'] );
$instance['author_source'] = sanitize_key( $new_instance['author_source'] ?? $defaults['author_source'] );
$instance['author_id'] = absint( $new_instance['author_id'] ?? 0 );
$allowed_sources = array( 'current_post_author', 'selected_author', 'current_user' );
if ( ! in_array( $instance['author_source'], $allowed_sources, true ) ) {
$instance['author_source'] = 'current_post_author';
}
$checkboxes = array(
'show_avatar',
'show_name',
'show_display_role',
'show_bio',
'show_website',
'show_email',
'show_post_count',
'show_registered_date',
'show_socials',
'show_latest_posts',
'show_cta',
'show_follow',
'enable_schema',
);
foreach ( $checkboxes as $key ) {
$instance[ $key ] = ! empty( $new_instance[ $key ] ) ? 1 : 0;
}
$instance['avatar_size'] = min( 300, max( 40, absint( $new_instance['avatar_size'] ?? $defaults['avatar_size'] ) ) );
$instance['bio_limit'] = min( 2000, max( 50, absint( $new_instance['bio_limit'] ?? $defaults['bio_limit'] ) ) );
$instance['latest_posts_count'] = min( 10, max( 1, absint( $new_instance['latest_posts_count'] ?? $defaults['latest_posts_count'] ) ) );
$instance['avatar_shape'] = sanitize_key( $new_instance['avatar_shape'] ?? $defaults['avatar_shape'] );
$allowed_avatar_shapes = array( 'circle', 'rounded', 'square' );
if ( ! in_array( $instance['avatar_shape'], $allowed_avatar_shapes, true ) ) {
$instance['avatar_shape'] = 'circle';
}
$instance['layout'] = sanitize_key( $new_instance['layout'] ?? $defaults['layout'] );
$allowed_layouts = array( 'center', 'left', 'compact' );
if ( ! in_array( $instance['layout'], $allowed_layouts, true ) ) {
$instance['layout'] = 'center';
}
$instance['box_style'] = sanitize_key( $new_instance['box_style'] ?? $defaults['box_style'] );
$allowed_styles = array( 'card', 'border', 'minimal' );
if ( ! in_array( $instance['box_style'], $allowed_styles, true ) ) {
$instance['box_style'] = 'card';
}
$instance['social_style'] = sanitize_key( $new_instance['social_style'] ?? $defaults['social_style'] );
$allowed_social_styles = array( 'text', 'button' );
if ( ! in_array( $instance['social_style'], $allowed_social_styles, true ) ) {
$instance['social_style'] = 'text';
}
$instance['custom_role_label'] = sanitize_text_field( $new_instance['custom_role_label'] ?? '' );
$instance['cta_text'] = sanitize_text_field( $new_instance['cta_text'] ?? $defaults['cta_text'] );
$instance['cta_url'] = esc_url_raw( $new_instance['cta_url'] ?? '' );
$instance['follow_text'] = sanitize_text_field( $new_instance['follow_text'] ?? $defaults['follow_text'] );
$instance['follow_url'] = esc_url_raw( $new_instance['follow_url'] ?? '' );
$instance['background_color'] = $this->sanitize_color( $new_instance['background_color'] ?? $defaults['background_color'], '#ffffff' );
$instance['text_color'] = $this->sanitize_color( $new_instance['text_color'] ?? $defaults['text_color'], '#222222' );
$instance['accent_color'] = $this->sanitize_color( $new_instance['accent_color'] ?? $defaults['accent_color'], '#0073aa' );
$instance['extra_class'] = sanitize_html_class( $new_instance['extra_class'] ?? '' );
return $instance;
}
}
endif;
/**
* Register RX Author Box Widget.
*/
if ( ! function_exists( 'rx_register_author_box_widget' ) ) {
function rx_register_author_box_widget() {
register_widget( 'RX_Author_Box_Widget' );
}
add_action( 'widgets_init', 'rx_register_author_box_widget' );
}
Add this in your theme functions.php if not already included:
/**
* RX Theme widgets.
*/
$rx_author_widget_file = get_template_directory() . '/inc/widgets/author-box-widget.php';
if ( file_exists( $rx_author_widget_file ) ) {
require_once $rx_author_widget_file;
}
For author social links, this widget checks user meta fields like:
facebook, facebook_url, rx_facebook
twitter, twitter_url, x_url, rx_twitter
linkedin, linkedin_url, rx_linkedin
instagram, instagram_url, rx_instagram
youtube, youtube_url, rx_youtube
github, github_url, rx_github
You can add those fields later in your user profile system or author meta plugin.