Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**
- * Filter the default permalink structure before WordPress replaces permalink tags.
- *
- * This hook is used to switch the permalink structure only for standard posts
- * that have at least one term assigned in the `jnews-series` taxonomy.
- *
- * Example:
- * Default structure : /%category%/%postname%/
- * Custom structure : /podcast/%jnwes-series%/%postname%/
- */
- add_filter(
- 'pre_post_link',
- function ( $permalink, $post, $leavename ) {
- if ( 'post' !== $post->post_type ) {
- return $permalink;
- }
- $series = wp_get_post_terms( $post->ID, 'jnews-series' );
- $series = is_wp_error( $series ) ? '' : $series;
- $series = is_array( $series ) ? ( ! empty( $series ) ? $series[0] : $series ) : $series;
- if ( ! empty( $series ) && ! is_wp_error( $series ) ) {
- return '/podcast/%jnwes-series%/%postname%/';
- }
- return $permalink;
- },
- 10,
- 3
- );
- /**
- * Replace the custom permalink tag with the actual taxonomy term slug.
- *
- * After `pre_post_link` changes the permalink structure, this hook replaces
- * `%jnwes-series%` with the real slug from the assigned `jnews-series` term.
- *
- * If no valid term is found, it falls back to `uncategorized`.
- */
- add_filter(
- 'post_link',
- function ( $permalink, $post, $leavename ) {
- if ( 'post' !== $post->post_type ) {
- return $permalink;
- }
- if ( false === strpos( $permalink, 'podcast/%jnwes-series%' ) ) {
- return $permalink;
- }
- $series = wp_get_post_terms( $post->ID, 'jnews-series' );
- $series = is_wp_error( $series ) ? '' : $series;
- $series = is_array( $series ) ? ( ! empty( $series ) ? $series[0] : $series ) : $series;
- if ( empty( $series ) || is_wp_error( $series ) ) {
- return str_replace( 'podcast/%jnwes-series%', 'uncategorized', $permalink );
- }
- return str_replace( '%jnwes-series%', $series->slug, $permalink );
- },
- 10,
- 3
- );
- /**
- * Register custom query variables used by the rewrite rule.
- *
- * `jnews_series_slug` is used to store the series term slug taken from the URL.
- * `jnews_series_post_slug` is registered here for possible future use, even though
- * it is not used in the current rewrite target.
- */
- add_filter(
- 'query_vars',
- function ( $vars ) {
- $vars[] = 'jnews_series_slug';
- $vars[] = 'jnews_series_post_slug';
- return $vars;
- }
- );
- /**
- * Add a custom rewrite rule for podcast series single posts.
- *
- * This rule maps URLs like:
- * /podcast/series-slug/post-slug/
- *
- * Into query vars that WordPress can understand:
- * - post_type=post
- * - name=post-slug
- * - jnews_series_slug=series-slug
- *
- * The rule is added at the top so it takes priority over more generic rules.
- */
- add_action(
- 'init',
- function () {
- add_rewrite_rule(
- '^podcast/([^/]+)/([^/]+)/?$',
- 'index.php?post_type=post&name=$matches[2]&jnews_series_slug=$matches[1]',
- 'top'
- );
- }
- );
- /**
- * Modify the main query so WordPress only loads posts that belong to
- * the requested `jnews-series` term from the URL.
- *
- * Without this hook, WordPress may find a post by slug alone, even if the post
- * does not belong to the requested series term.
- *
- * This ensures the URL:
- * /podcast/series-slug/post-slug/
- *
- * Only resolves if `post-slug` is actually assigned to `series-slug`.
- */
- add_action(
- 'pre_get_posts',
- function ( $query ) {
- if ( is_admin() || ! $query->is_main_query() ) {
- return;
- }
- $series_slug = $query->get( 'jnews_series_slug' );
- $post_slug = $query->get( 'name' );
- if ( empty( $series_slug ) || empty( $post_slug ) ) {
- return;
- }
- $query->set( 'post_type', 'post' );
- $query->set(
- 'tax_query',
- array(
- array(
- 'taxonomy' => 'jnews-series',
- 'field' => 'slug',
- 'terms' => $series_slug,
- ),
- )
- );
- }
- );
- /**
- * Redirect non-canonical series URLs to the correct permalink.
- *
- * This hook runs before the template is loaded and compares the current URL
- * against the canonical permalink generated by WordPress.
- *
- * If the requested URL does not match the correct permalink, a 301 redirect
- * is performed to avoid duplicate URLs and keep the permalink consistent.
- */
- add_action(
- 'template_redirect',
- function () {
- if ( ! is_single() ) {
- return;
- }
- $post = get_queried_object();
- if ( ! $post instanceof WP_Post || 'post' !== $post->post_type ) {
- return;
- }
- $requested_series = get_query_var( 'jnews_series_slug' );
- if ( empty( $requested_series ) ) {
- return;
- }
- $canonical = get_permalink( $post );
- $current = home_url( trailingslashit( $GLOBALS['wp']->request ) );
- if ( untrailingslashit( $canonical ) !== untrailingslashit( $current ) ) {
- wp_safe_redirect( $canonical, 301 );
- exit;
- }
- }
- );
Advertisement