<?php // Prevent direct file access. defined( 'ABSPATH' ) || die; if ( ! class_exists( 'Mai_User_Role_Base' ) ): /** * The User Role Base class. * * @version 0.2.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 ); // Get the server request. $request = trailingslashit( $_SERVER['REQUEST_URI'] ); // If valid role. if ( $role ) { // Get the base and redirect. $base = $this->config[ $role ]['base']; $status = $this->config[ $role ]['redirect']; // Build strings to compare. $compare = "/{$base}/" . $author_slug . '/'; // Bail if already 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; } // Get author posts url path. $url = esc_url( get_author_posts_url( $author_id, $author_slug ) ); $path = wp_parse_url( $url, PHP_URL_PATH ); // Bail if already the correct path. if ( $path === $request ) { return; } // Redirect to the correct author url. wp_safe_redirect( user_trailingslashit( $url ), 301 ); 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;