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 🙁