Opened 15 years ago
Closed 15 years ago
#16627 closed defect (bug) (fixed)
Rewrite query vars are stripped from custom taxonomy page URLs via redirect_canonical()
| Reported by: |
|
Owned by: | |
|---|---|---|---|
| Milestone: | 3.1.1 | Priority: | normal |
| Severity: | normal | Version: | 3.1 |
| Component: | Canonical | Keywords: | |
| Focuses: | Cc: |
Description
In wp-includes/canonical.php, version 3.1 changed lines 155-177 from
if ( $term_count <= 1 && !empty($obj->term_id) && ( $tax_url = get_term_link((int)$obj->term_id, $obj->taxonomy) )
&& !is_wp_error($tax_url) && $redirect['query'] ) {
/* Not important */
$tax_url = parse_url($tax_url);
if ( ! empty($tax_url['query']) ) { // Custom taxonomies may only be accessable via ?taxonomy=..&term=..
parse_str($tax_url['query'], $query_vars);
$redirect['query'] = add_query_arg($query_vars, $redirect['query']);
} else { // Taxonomy is accessable via a "pretty-URL"
$redirect['path'] = $tax_url['path'];
}
}
to (lines 153-174)
if ( $term_count <= 1 && !empty($obj->term_id) && ( $tax_url = get_term_link((int)$obj->term_id, $obj->taxonomy) ) && !is_wp_error($tax_url) ) {
if ( !empty($redirect['query']) ) {
/* Not important */
}
$tax_url = parse_url($tax_url);
if ( ! empty($tax_url['query']) ) { // Custom taxonomies may only be accessable via ?taxonomy=..&term=..
parse_str($tax_url['query'], $query_vars);
$redirect['query'] = add_query_arg($query_vars, $redirect['query']);
} else { // Taxonomy is accessable via a "pretty-URL"
$redirect['path'] = $tax_url['path'];
}
}
The difference here is that in the new version, the $redirect['path'] is always set to the taxonomy path, eliminating any query vars added via custom rewrite rule, regardless of whether there are query vars in $redirect['query'] or not.
Attachments (1)
Change History (23)
#4
@
15 years ago
A test case would be helpful here. What is an example URL that is failing? What does the registration code for the taxonomy look like?
#5
@
15 years ago
Here's what I am using. Worked in 3.0.5, not in 3.1:
// create the custom taxonomies
function btf_create_taxonomies() {
register_taxonomy('textures', 'post', array('hierarchical' => false, 'label' => 'Texture Categories', 'query_var' => true, 'rewrite' => true));
register_taxonomy('wallpapers', 'post', array('hierarchical' => false, 'label' => 'Wallpaper Categories', 'query_var' => true, 'rewrite' => true));
}
add_action('init', 'btf_create_taxonomies', 0);
// add the custom query var
function btf_query_vars($query_vars) {
$query_vars[] = 'sort';
return $query_vars;
}
add_filter('query_vars', 'btf_query_vars');
// I had some issues with custom query vars and paging,
// so I wrote this to correct the query string values
function btf_request($query_string) {
if (isset($query_string['name']) && $query_string['name'] === 'page'
&& isset($query_string['page'])) {
unset($query_string['name']);
$query_string['paged'] = str_replace('/', '', $query_string['page']);
}
$sort = array('date', 'popularity', 'comments', 'downloads', 'rating', 'votes');
if (isset($query_string['name']) && isset($query_string['category_name'])
&& btf_ends_with('/sort', $query_string['category_name'])) {
if (strpos($query_string['name'], '-') > 0) {
$valid = explode('-', $query_string['name']);
$s = $valid[0];
}
else {
$s = $query_string['name'];
}
if (in_array($s, $sort)) {
$parts = explode('/', $query_string['category_name']);
$query_string['sort'] = $query_string['name'];
$query_string['category_name'] = $parts[0];
unset($query_string['name']);
}
}
return $query_string;
}
add_filter('request', 'btf_request');
I hope the btf_request function doesn't over-complicate things. Basically, what I want is to be able to have:
- mysite.com/custom-taxonomy/ - default listing
- mysite.com/custom-taxonomy/sort/downloads - sort by downloads
- mysite.com/custom-taxonomy/sort/downloads/page/2 - sort by downloads, page 2
The code I have above worked fine in 3.0.5. If there is a better way to achieve this, I'm happy to try a different approach.
#6
@
15 years ago
Mine looks very similar to emartin's except I'm using rewrite rules.
Taxonomy code
register_taxonomy('my_taxonomy', 'custom_post_type', array(
'label' => __('My Taxonomy Name'),
'public' => true,
'rewrite' => array('slug' => 'my_slug_prefix'),
'query_var' => 'my_taxonomy_var'
));
Added query vars (using the query_vars filter)
$queryVars[] = 'criteria'; return $queryVars;
Rewrite Rules (using the generate_rewrite_rules action hook)
$rules = array(
'my_slug_prefix/(.+)/(.+)/(asc|desc)' => sprintf(
'index.php?taxonomy=my_taxonomy&my_taxonomy_var=%s&criteria=%s&order=%s',
$rewrite->preg_index(1), $rewrite->preg_index(2), $rewrite->preg_index(3)),
'my_slug_prefix/(.+)/(.+)' => sprintf(
'index.php?taxonomy=my_taxonomy&my_taxonomy_var=%s&criteria=%s',
$rewrite->preg_index(1), $rewrite->preg_index(2))
);
$rewrite->rules = $rules + $rewrite->rules;
Like emartin's, mine worked fine in 3.0.5. Any matching URL is now redirected to the default taxonomy page via canonical.php line 172
$redirect['path'] = $tax_url['path'];
#7
@
15 years ago
[15705] is where the conditional was altered.
That reverted [15462], which was hiding the issue by only processing requests with $_GET variables present.
This particular change is rooted in the fact that non-category, non-tag taxonomies got a canonicalisation treatment.
My initial thought pattern here, is that the function should check to see what $query_vars are present, ie. if anything other than taxonomy & $taxonomy_query_var are present in the rewrite, skip canonicalising based on the term path.
#8
@
15 years ago
My initial thought pattern here, is that the function should check to see what $query_vars are present, ie. if anything other than taxonomy & $taxonomy_query_var are present in the rewrite, skip canonicalising based on the term path.
attachment 16627.diff added
- The above idea in code.
#10
@
15 years ago
The other option is to cripple the canonicalisation for taxonomies for 3.1.x by adding back in the check for $_GET variables present, that'll at least cause canonical to not apply to pure rewrite rules, but as soon as a $_GET variable is added to the mix, it'll kick in again.. as it should've done so in 3.0. and leave above patch for a 3.2 fix.
#12
@
15 years ago
How about doing a redirect only if there are $_GET variables present that are not registered with $wp->add_query_var() ?
#13
@
15 years ago
The alternate to "cripple" it, is to re-instate [15462] - specifically, checking to see if a query is set. Which is a better option for 3.1.1, leaving a proper fix to 3.2
#18
@
15 years ago
- Milestone changed from 3.1.1 to 3.2
- Resolution fixed deleted
- Status changed from closed to reopened
This was never dealt with in trunk
#20
@
15 years ago
With the re-instated patch, term URLs are not canonicalized (though they probably weren't before). If you are using pretty permalinks, then the $redirect['query'] will never be set (looking at http://core.trac.wordpress.org/browser/tags/3.1.2/wp-includes/canonical.php#L153).
This means if the $tax_url is different to the current URL, it will not be redirected. E.g. /tag/Apple/ should redirect to /tag/apple/, but won't be. Removing the $redirect['query'] check fixes the canonical redirect in my case.
Just discovered this issue on my site as well. In my research, I found a few differences that seem to be causing the "issue".
1) In the code just above what @gnoodl mentioned, in 3.0.5, the following code results in a
$term_countof0:$term_count = 0; foreach ( array('category__in', 'category__not_in', 'category__and', 'post__in', 'post__not_in', 'tag__in', 'tag__not_in', 'tag__and', 'tag_slug__in', 'tag_slug__and') as $key ) $term_count += count($wp_query->query_vars[$key]);In 3.1, the new code results in a
$term_countof1:2) In the
ifcondition that @gnoodl mentioned, 3.0.5 includes a check for $redirectquery?, 3.1 does not.In my case, I'm using a custom query variable. Perhaps there is another solution to my problem, but it worked in 3.0.5 and this is the code that causes it to no longer work ;)