Ok, so – I am working on a magazine style website that requires “regionalised” content.

So for example I have:

  • UK (Includes ALL)
  • Manchester
  • Brighton
  • London

I have already successfully implemented this functionality by including a custom taxonomy for certain content (mainly posts).

I then intercept all queries with a pre_get_posts filter, which to give you an idea looks like this:

protected function regionalize() {
    add_filter( 'pre_get_posts', array( $this, 'pre_posts' ) );
}

function pre_posts( $query ) {
    if ( 
        $query->is_main_query() 
        && ! is_admin() 
        || ( is_archive() || is_search() || is_front_page() || is_home() || is_tax() ) 
    ) {
        if(in_array ( $query->get('post_type'), $this->ENABLED_POST_TYPES )) {
            $query->set( 'tax_query', array( $this->getRegionTaxQuery() ) );    
        }
    }
    return $query;
}

Now as I say again, this is all working perfectly as expected. What I need to now do is create some custom rewrite rules – I don’t have much experience with doing this hence why I am seeking outside help 🙂

I need to be able to prefix ALL urls which are covered by the regionalisation.

So for example:

  • www.mywebsite.com/london/post-name
  • www.mywebsite.com/manchester/post-name

etc…

I am using WP SEO by Yoast so would still like to have the canonical URL set & accessible..

Regionalisation does not apply to pages, only “posts” & “events”.

I had a little go and got 1/4 of the way there doing this:

public function rewrite() {
    global $wp_rewrite;
    $wp_rewrite->page_structure = $wp_rewrite->root .sanitize_title($this->getCurrentRegion()).'/%pagename%';
    $wp_rewrite->flush_rules();     
}

Any ideas? Hope this is clear enough!

UPDATE:

I’ve managed to achieve 90% what I’m asking for by doing the following:

“Resetting” the post types I want to use regionalisation for:

public function rewrite_resets() {

    global $wp_rewrite;

    foreach($this->ENABLED_POST_TYPES as $post_type) {

        $args = get_post_type_object($post_type);
        switch($post_type) {
            case 'post':
                $slug = '/%region%/%postname%';
            break;
            case 'event':
                $slug = '/%region%/events';
            break;
        }
        $args->rewrite["slug"] = $slug;
        $args->rewrite["with_front"] = 0;
        register_post_type($args->name, $args); 

    }   

    // Fixes pages but breaks posts :(
    add_rewrite_rule('^([^/]*)?', 'index.php?pagename=$matches[1]', 'bottom');  


}

This is hooked to init

I then control the permalinks & templates with these functions:

public function post_permalink_structure($post_link, $id = 0, $leavename = FALSE) {
    if ( strpos('%region%', $post_link) === 'FALSE' ) {
      return $post_link;
    }
    $post = get_post($id);
    if ( !is_object($post) || !in_array($post->post_type, $this->ENABLED_POST_TYPES )) {
      return $post_link;
    }
    $terms = wp_get_object_terms($post->ID, 'region');
    if(!$terms) $terms[0]->slug = sanitize_title(self::DEFAULT_REGION);
    return str_replace('%region%', $terms[0]->slug, $post_link);
}

public function intercept_template() {
    global $wp_query, $post;
    if( array_key_exists( 'region', $wp_query->query_vars ) ) {
        if( 
            !has_term(get_query_var('region'), 'region', $post->ID) && 
            is_single() && in_array($post->post_type, $this->ENABLED_POST_TYPES) 
        ) {
            $wp_query->set_404();
            status_header( 404 );
            nocache_headers();
            include TEMPLATEPATH . "/404.php";
            exit;
        }       
    }
}

Now there is another issue (and possibly some other hidden potentially issues with other rewrites which I’m not aware of currently!)

When trying to view pages I now receive a 404 error as this is conflicting with the new rules I set above when resetting the post types.

I know this because I added some code to the 404 template which displayed this for the “About Us” page:

Request: about
Matched Rewrite Rule: ([^/]+)/?$
Matched Rewrite Query: region=about
Loaded Template: 404.php

It’s quite clear what is happening here, it’s detecting region as opposed to pagename.

I have no idea how to solve this 🙁

1 Answer
1

I think you can create a rewrite rule for each “region” to don’t overwrite other important rules you could need (like pages, categories, etc..). I was playing with your code examples and with a small change in rewrite_resets could work:

public function rewrite_resets() {

    global $wp_rewrite;

    foreach($this->ENABLED_POST_TYPES as $post_type) {

        $args = get_post_type_object($post_type);
        switch($post_type) {
            case 'post':
                $slug = '/%region%/%postname%';
            break;
            case 'event':
                $slug = '/%region%/events';
            break;
        }
        $args->rewrite["slug"] = $slug;
        $args->rewrite["with_front"] = 0;
        register_post_type($args->name, $args); 

    }

    $categories = get_terms( 'region', array(
        'orderby'    => 'count',
        'hide_empty' => 0,
    ));

    // Rewrite rule for each taxonomy
    foreach($categories as $_category) {
        add_rewrite_rule('^'.$_category->slug.'/([^/]+)?', 'index.php?name=$matches[1]', 'bottom');
    }

}

This will work if your taxonomy name is “region” (I was playing with the taxonomy “category” the standard, in the end is the same)

In this way you can create a taxonomy region called “London”, like you are doing, and in the same time a page with the same slug (london). This rewrite works only if the url start with the name of the region and has one “path” more. If has tree or one doesn’t match, that’s why don’t break other rewrite rules.

Is just an idea, I hope this help to you 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *