Skip to content
This repository was archived by the owner on Sep 21, 2022. It is now read-only.
This repository was archived by the owner on Sep 21, 2022. It is now read-only.

Suggestion: Add URLManager #79

@perruche

Description

@perruche

Add URLManager to implement some basic nice to have rewrite rules

Exemple for this common pattern:
Permalinks are set to /%category%/%postname%/ and category_base is set to "blog"

We want the following URL:

  • /blog/ for the posts list page
  • /blog/page/%paged% for the posts list page with pagination
  • /blog/%category/ for an archive page
  • /blog/%category/page/%paged%+ for an archive page with pagination
  • /blog/%category%/%postname%/ for a single post

Exemple file to achieve this result below

<?php
/**
 * Bootstraps URLs and rewrite rules.
 *
 * @package Studiometa
 */

namespace Studiometa\Managers;

use Studiometa\Managers\ManagerInterface;

/** Class */
class URLManager implements ManagerInterface {
	// phpcs:ignore Generic.Commenting.DocComment.MissingShort
	/**
	 * @inheritDoc
	 */
	public function run() {
		add_action( 'init', array( $this, 'add_rewrite_rules' ) );
		add_filter( 'pre_post_link', array( $this, 'meta_alter_pre_post_link' ), 10, 2 );
		add_filter( 'rewrite_rules_array', array( $this, 'meta_alter_rewrite_rules_array' ), 10, 1 );
	}

	/**
	 * Add rewrite rules
	 *
	 * @return void
	 */
	public function add_rewrite_rules() {
		$category_base = get_option( 'category_base' );

		// Add a rule for home.php, since url schema is /%category%/%postname% when querying $category_base/page/2 WordPress is looking for a category with the name "page".
		add_rewrite_rule(
			'(' . $category_base . '+)/page/?([0-9]{1,})/?$',
			'index.php?pagename=$matches[1]&paged=$matches[2]',
			'top'
		);

		// Add a rule to specify the $category_base prefix for posts permalink.
		add_rewrite_rule(
			$category_base . '/[a-z-]+/?([a-z-]+)/?$',
			'index.php?pagename=$matches[1]',
			'top'
		);
	}

	/**
	 * Alter posts permalink structure before it is processed by WP.
	 *
	 * @param string  $permalink Current permalink.
	 * @param WP_Post $post Current post.
	 *
	 * @return string
	 */
	public function meta_alter_pre_post_link( $permalink, $post ) {
		$category_base = get_option( 'category_base' );

		if ( 'post' !== $post->post_type ) {
			return $permalink;
		}

		return '/' . $category_base . '/%category%/%postname%/';
	}

	/**
	 * Add custom rewrite rules to global Rewrite Rules array.
	 *
	 * @param array $rules Current rewrite rules.
	 *
	 * @return array
	 */
	public function meta_alter_rewrite_rules_array( $rules ) {
		$category_base = get_option( 'category_base' );
		$current_url   = trim( esc_url_raw( add_query_arg( array() ) ), '/' );
		$segments      = explode( '/', wp_parse_url( $current_url, PHP_URL_PATH ) );

		if ( empty( end( $segments ) ) ) {
			array_pop( $segments );
		}

		if (
			( 3 === count( $segments ) && $category_base === $segments[0] ) ||
			( 4 === count( $segments ) && ICL_LANGUAGE_CODE === $segments[0] && $category_base === $segments[1] ) // Manage i18n.
		) {
			foreach ( $rules as $key => $rule ) {
				if ( $category_base . '/(.+?)/?$' === $key ) {
					unset( $rules[ $key ] );
				}
			}
		}

		return $rules;
	}
}

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions