2

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 :(

  • So, If I understood correctly, you want to use a taxonomy term (region) in the post URL. This other question and answer is about exactly that: Rewriting a custom-post-type permalink with taxonomy term? – cybmeta Jul 13 '15 at 13:57
  • I do, however, I need to apply this to "posts" and not a custom post type, which seems to make this more difficult? – Nathan Fitzgerald - Fitzgenius Jul 14 '15 at 9:24
  • I have updated my question if you would kindly have a look over! Thank you. :) – Nathan Fitzgerald - Fitzgenius Jul 14 '15 at 11:44
  • I have not the answer for your question, but maybe you should think about a solution via WP Multisite. Each site in the network is a region. Is much better for capability management, templates, themes, plugins, domains and much more. – bueltge Jul 15 '15 at 9:28
  • Thanks bueltge, unfortunately multi-site is not an option for this implementation as it does not cover the scope of the whole project. – Nathan Fitzgerald - Fitzgenius Jul 15 '15 at 9:40
2

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 :)

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.