Skip to content

Instantly share code, notes, and snippets.

@JiveDig
Last active April 18, 2024 20:08
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JiveDig/5501764b97a967d53af0edb78ff15268 to your computer and use it in GitHub Desktop.
Save JiveDig/5501764b97a967d53af0edb78ff15268 to your computer and use it in GitHub Desktop.
A PHP class for WordPress that allows you to change the author base by user role.

A PHP class for WordPress that allows you to change the author base by user role.

Priorities are used to determine which role to use for users that have multiple roles. In the example code below, the customrole user role is a higher priority than the editor role, so /ninjas/user_nicename/ is the base/url that will be used if a user is both roles.

Make sure you flush permalinks after using or modifying this code!

Understanding the config

base: The url base, for /homies/{user_nicename}.
redirect: The status to use when redirecting the existing /author/{user_nicename} urls.
priority: The priority of this role vs other roles with custom bases. Higher priorities will take precedence.

How to use

/**
 * Change the author base by user role.
 *
 * @return void
 */
add_action( 'after_setup_theme', function() {
	// Bail if class does not exist.
	if ( ! class_exists( 'Mai_User_Role_Base' ) ) {
		return;
	}

	new Mai_User_Role_Base(
		[
			'editor' =>  [
				'base'     => 'homies',
				'redirect' => 301,
				'priority' => 0,
			],
			'customrole' =>  [
				'base'     => 'ninjas',
				'redirect' => 301,
				'priority' => 10,
			],
		],
	);
});
<?php
// Prevent direct file access.
defined( 'ABSPATH' ) || die;
if ( ! class_exists( 'Mai_User_Role_Base' ) ):
/**
* The User Role Base class.
*
* @version 0.1.0
*
* @link https://gist.github.com/JiveDig/5501764b97a967d53af0edb78ff15268
* @link https://wordpress.stackexchange.com/questions/330812/changing-author-slug-for-a-custom-role-without-using-plugin
*
* base: The url base, for `/homies/{user_nicename}`.
* redirect: The status to use when redirecting the existing `/author/{user_nicename}` urls.
* priority: The priority of this role vs other roles with custom bases. Higher priorities will take precedence.
*
* Example usage:
* new Mai_User_Role_Base(
* [
* 'customrole' => [
* 'base' => 'homies',
* 'redirect' => 301,
* 'priority' => 0,
* ],
* 'editor' => [
* 'base' => 'ninjas',
* 'redirect' => 301,
* 'priority' => 10,
* ],
* ],
* );
*/
class Mai_User_Role_Base {
protected $config;
/**
* Construct the class.
*
* @param array $config The configuration. An array of arrays of role, base, and status.
*
* @since 0.1.0
*/
function __construct( $config = [] ) {
// Set the data.
$this->config = $this->sanitize_config( $config );
// Run hooks.
$this->hooks();
}
/**
* Add hooks.
*
* @since 0.1.0
*
* @return void
*/
function hooks() {
add_action( 'init', [ $this, 'add_permastruct' ] );
add_action( 'template_redirect', [ $this, 'add_redirect' ] );
add_filter( 'author_link', [ $this, 'author_link' ], 10, 3 );
}
/**
* Add permastruct.
*
* @since 0.1.0
*
* @return void
*/
function add_permastruct() {
// Loop through config.
foreach ( $this->config as $role => $values ) {
$base = $values['base'];
// Add the permastruct.
add_permastruct( "%{$role}_{$base}%", "{$base}/%author%", [
'ep_mask' => EP_AUTHORS,
] );
}
}
/**
* Add redirect.
*
* @since 0.1.0
*
* @return void
*/
function add_redirect() {
// Bail if not an author archive.
if ( ! is_author() ) {
return;
}
// Get author.
$author = get_queried_object();
$author_id = $author->ID;
$author_slug = $author->user_nicename;
$role = $this->get_user_role( $author_id );
// Bail if no valid roles.
if ( ! $role ) {
return;
}
// Get the base and redirect.
$base = $this->config[ $role ]['base'];
$status = $this->config[ $role ]['redirect'];
// Build strings to compare.
$compare = "/{$base}/" . $author_slug . '/';
$request = trailingslashit( $_SERVER['REQUEST_URI'] );
// Bail if already has the correct base.
if ( $compare === $request ) {
return;
}
// Redirect to the correct author url.
wp_safe_redirect( user_trailingslashit( home_url( "/{$base}/" . $author_slug ) ), $status );
exit;
}
/**
* Change the author link url.
*
* @since 0.1.0
*
* @param string $link The author link.
* @param int $author_id The author ID.
* @param string $author_nicename The author nicename.
*
* @return string
*/
function author_link( $link, $author_id, $author_nicename ) {
$role = $this->get_user_role( $author_id );
// Bail if not a valid role.
if ( ! $role ) {
return $link;
}
// Get the new link.
$base = $this->config[ $role ]['base'];
$link = "/{$base}/" . $author_nicename;
$link = home_url( user_trailingslashit( $link ) );
return esc_url( $link );
}
/**
* Gets the highest priority valid user role.
*
* @since 0.1.0
*
* @param int $user_id The user ID.
*
* @return bool
*/
function get_user_role( $user_id ) {
// Set cache.
static $cache = [];
// If we have cache, return it.
if ( isset( $cache[ $user_id ] ) ) {
return $cache[ $user_id ];
}
// Get and set.
$roles = $this->get_valid_roles( $user_id );
$cache[ $user_id ] = reset( $roles );
return $cache[ $user_id ];
}
/**
* Check if the user has a role we need to handle.
*
* @since 0.1.0
*
* @param int $user_id The user ID.
*
* @return bool
*/
function get_valid_roles( $user_id ) {
// Set cache.
static $cache = [];
// If we have cache, return it.
if ( isset( $cache[ $user_id ] ) ) {
return $cache[ $user_id ];
}
// Get and set.
$user = get_userdata( $user_id );
$cache[ $user_id ] = $user ? array_intersect( array_keys( $this->config ), (array) $user->roles ) : [];
return $cache[ $user_id ];
}
/**
* Sanitize the config.
*
* @since 0.1.0
*
* @param array $config The config.
*
* @return array
*/
function sanitize_config( $config ) {
$sanitized = [];
$roles = wp_roles()->roles;
// Loop through config.
foreach ( $config as $role => $values ) {
// Set data defaults.
$values = wp_parse_args( $values, [
'base' => '',
'redirect' => 301,
'priority' => 0,
] );
// Skip if not a valid role or missing base.
if ( ! ( isset( $roles[ $role ] ) && $values['base'] ) ) {
continue;
}
// Set the role, base, and status.
foreach ( $values as $key => $value ) {
switch ( $key ) {
case 'redirect':
$values[ $key ] = $value ? absint( $value ) : 301;
break;
case 'priority':
$values[ $key ] = $value ? absint( $value ) : 0;
break;
default:
$values[ $key ] = sanitize_key( $value );
break;
}
}
// Add to sanitized array.
$sanitized[ $role ] = $values;
}
// Sort the original array by priority (descending order for highest first).
uasort( $sanitized, function( $a, $b ) {
return $b['priority'] <=> $a['priority'];
});
return $sanitized;
}
}
endif;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment