WordPress как на ладони

Удаляем в URL префикс главной страницы у дочерних страниц

Для главной страницы сайта установлена статическая страница и у нее есть подстраницы. Задача: убрать в УРЛ префикс этой родительской страницы когда мы переходим на дочернюю.

Немного пояснений на примерах. Допустим имя родительской страницы (префикс который нужно убрать) main-page. Тогда ссылки должны выглядеть следующим образом:

  • Главная страница: /main-page/
  • Дочерняя страница: /main-page/podstranica/podstranica
  • Дочерняя страница: /main-page/podstranica/vnuk/podstranica/vnuk

Также в коде:

  • Предусмотрено, чтобы теперь неправильные URL отдавали 404 страницу.
  • Отключен файл шаблона front-page.php, вместо него нужно использовать базовый вариант шаблона страницы page-*.php.
  • Подправлены хлебные крошки (главный элемент крошек) (для моего плагина Kama Breadcrumbs).
# Delete main page prefix for subpages.
# Works only if static page is set for front page.
Delete_Base_Prefix_For_Front_Sub_Pages::init();

final class Delete_Base_Prefix_For_Front_Sub_Pages {

	// WP_Post|false if current request is front sub page
	static $sub_post = false;

	// WP_Post|false if specific page is set for front page
	static $front_post = 0;

	static $origin_REQUEST_URI = '';

	static function init(){

		self::$front_post = ( 'page' === get_option('show_on_front') && $ID = get_option('page_on_front') ) ? get_post( $ID ) : 0;

		if( self::$front_post ){

			// change permalink
			add_filter( 'page_link',        [ __CLASS__, 'fix_page_link' ] );

			// change request
			add_filter( 'do_parse_request', [ __CLASS__, 'replace_uri' ] );
			add_filter( 'request',          [ __CLASS__, 'replace_uri_back' ] );

			// remove `front-page.php` template file from template hierarchy
			// if static page set for front page. Use, basic `page-*.php` template file in this case.
			add_filter( 'frontpage'.'_template_hierarchy', '__return_empty_array' );

			// 404 for URL with main page prefix
			add_action( 'pre_handle_404', [ __CLASS__, 'block_wrong_url' ] );

			// for plugin Kama Breadcrumbs
			add_filter( 'kama_breadcrumbs_filter_elements', [ __CLASS__, 'fix_breadcrumbs' ] );
		}
	}

	static function fix_page_link( $link ){

		// url begin with prefix
		if(
			self::$front_post && strpos( $link, self::$front_post->post_name ) &&
			preg_match( '~^/'. self::$front_post->post_name .'/([^?]+)~', parse_url( $link, PHP_URL_PATH ), $mm )
		)
			return str_replace( $mm[0], "/$mm[1]", $link );

		return $link;
	}

	static function replace_uri( $true ){

		list( $req_uri ) = explode( '?', $_SERVER['REQUEST_URI'] );

		self::$origin_REQUEST_URI = $_SERVER['REQUEST_URI'];

		$page_real_path = self::$front_post->post_name .'/'. trim( $req_uri, '/' );
		if( self::$sub_post = get_page_by_path( $page_real_path ) )
			$_SERVER['REQUEST_URI'] = $page_real_path;

		return $true;
	}

	static function replace_uri_back( $foo ){

		if( self::$origin_REQUEST_URI )
			$_SERVER['REQUEST_URI'] = self::$origin_REQUEST_URI;

		return $foo; // for filter
	}

	static function block_wrong_url( $false ){

		if ( preg_match( '~^/'. self::$front_post->post_name .'(?:/([^?]+)|/?$)~', self::$origin_REQUEST_URI) ) {
			global $wp_query;
			$wp_query->set_404();
			status_header( 404 );
			nocache_headers();

			return true; // for hook break
		}

		return $false;
	}

	static function fix_breadcrumbs( $elms ){

		if( self::$sub_post && ! empty( $elms['singular_hierar']['page__page_crumbs'] ) ){
			$elms['home'] = array_shift( $elms['singular_hierar']['page__page_crumbs'] );
		}

		return $elms;
	}

}

Код можно вставлять в файл темы functions.php.

5 комментариев
    Войти