Polylang 1.2 beta is ready for tests
-
More informations are available on blog post.
You can report bugs here.
-
Thank you, Chouby,
I can confirm that the findings I reported are fixed now with PLL 1.2dev54.
I have a new finding for you to check out:
Up until PLL 1.1.6, the WP e-Commerce products page custom post type (wpsc-product) permalink structure would be modified like this (in my case):
https://www.mydomain.com/en/products-page/<product category>/<product slug/
https://www.mydomain.com/es/products-page/<translated product category>/<translated product slug/Now, with PLL 1.2dev54, the language slug is missing:
https://www.mydomain.com/products-page/<product category>/<product slug/
https://www.mydomain.com/products-page/<translated product category>/<translated product slug/This is what I traced:
/* The child theme is about to display a product using the WP e-Commerce theme backed up grid view script */ ...themes/twentytwelve-dark/wpsc-grid_view.php ... <div class="product_grid_display group"> <?php while (wpsc_have_products()) : wpsc_the_product(); ?> <div class="product_grid_item product_view_<?php echo wpsc_the_product_id(); ?>"> <?php if(wpsc_the_product_thumbnail()) :?> <div class="item_image"> <a href="<?php echo wpsc_the_product_permalink(); ?>"> // <--- Here's the product permalink request. ... ...wp-includes/link-template.php function get_post_permalink( $id = 0, $leavename = false, $sample = false ) { // line 178 ... $post_link = $wp_rewrite->get_extra_permastruct($post->post_type); // line 186 $post->post_type == 'wpsc-product' ... ...wp-includes/rewrite.php function extra_permastructs( $id = 0, $leavename = false, $sample = false ) { ... if ( isset($this->extra_permastructs[$name]) ) // line 1042 return $this->extra_permastructs[$name]['struct']; // WP_Rewrite->extra_permastructs['wpsc-product']['struct'] == products-page/%wpsc_product_category%/%wpsc-product% ...wp-includes/link-template.php function get_post_permalink( $id = 0, $leavename = false, $sample = false ) { // line 178 ... $post_link = str_replace("%$post->post_type%", $slug, $post_link); // line 198 $slug == <product slug>, $post_link == products-page/%wpsc_product_category%/<product slug> ... $post_link = home_url( user_trailingslashit($post_link) ); // line 200 $post_link == https://www.mywebsite.com/products-page/%wpsc_product_category%/<product slug>/ ... return apply_filters('post_type_link', $post_link, $post, $leavename, $sample); // line 209 ...wp-includes/plugin.php function apply_filters($tag, $value) { // line 137 $tag == 'post_type_link' foreach( (array) current($wp_filter[$tag]) as $the_ ) // line 170 if ( !is_null($the_['function']) ){ // the_['function'][0] == 'PLL_Frontend_Filters', the_['function'][1] == 'post_link' $args[1] = $value; // $args[1] = 'https://www.mywebsite.com/products-page/%wpsc_product_category%/<product slug>/' $value = call_user_func_array($the_['function'], array_slice($args, 1, (int) $the_['accepted_args'])); } ...polylang/include/filters-base.php public function post_link($link, $post) { // line 45 $link == 'https://www.mywebsite.com/products-page/%wpsc_product_category%/<product slug>/' static $links = array(); // $links['https://www.mywebsite.com/pagina-de-productos/'] == https://www.mywebsite.com/es/pagina-de-productos/' // $links['https://www.mywebsite.com/products-page/'] == https://www.mywebsite.com/en/products-page/ // $links['https://www.mywebsite.com/contacto/'] == https://www.mywebsite.com/es/contacto/ ... return $links[$link] = $post->post_status != 'publish' ? $link : $this->links_model->add_language_to_link($link, $this->model->get_post_language($post->ID)); // line 58 ...polylang/include/links-directory.php public function add_language_to_link($url, $lang) { // line 43 ... $base = $this->options['rewrite'] ? '' : 'language/'; // line 48 $base == NULL (don't want /language/ appended to permalink) $slug = $this->options['default_lang'] == $lang->slug && $this->options['hide_default'] ? '' : $base.$lang->slug.'/'; // $slug == 'es/' return str_replace($this->home.'/'.$wp_rewrite->root, $this->home.'/'.$wp_rewrite->root.$slug, $url); // $this->home == 'https://www.mywebsite.com', $wp_rewrite->root == NULL, $url == https://www.mywebsite.com/products-page/%wpsc_product_category%/<product slug>/ ...wp-includes/plugin.php function apply_filters($tag, $value) { // line 137 $tag == 'post_type_link' foreach( (array) current($wp_filter[$tag]) as $the_ ) // line 170 if ( !is_null($the_['function']) ){ // the_['function'][0] == 'wpsc_product_link' (WARNING: PLL_Frontend_Filters' post_link filter was applied too soon!!!!!!) $args[1] = $value; // $args[1] = 'https://www.mywebsite.com/es/products-page/%wpsc_product_category%/<product slug>/' $value = call_user_func_array($the_['function'], array_slice($args, 1, (int) $the_['accepted_args'])); } ...wp-e-commerce/wpsc-core/wpsc-functions.php function wpsc_product_link( $permalink, $post, $leavename ) { // line 1318 $permalink == 'https://www.mywebsite.com/es/products-page/%wpsc_product_category%/<product slug>/' global $wp_query, $wpsc_page_titles, $wpsc_query, $wp_current_filter; $rewritecode = array( // $rewritecode[0] == %wpsc_product_category% '%wpsc_product_category%', // $rewritecode[1] == %postname% $leavename ? '' : '%postname%', ); if ( is_object( $post ) ) { // In wordpress 2.9 we got a post object $post_id = $post->ID; // gets the $post_id as an integer value } else { // In wordpress 3.0 we get a post ID $post_id = $post; $post = get_post( $post_id ); } // Only applies to WPSC products, don't stop on permalinks of other CPTs // Fixes https://code.google.com/p/wp-e-commerce/issues/detail?id=271 if ($post->post_type != 'wpsc-product') return $permalink; $permalink_structure = get_option( 'permalink_structure' ); // $permalink_structure == /blog/%category%/%postname%/ // This may become customiseable later $our_permalink_structure = str_replace( basename( home_url() ), '', $wpsc_page_titles['products'] ) . "/%wpsc_product_category%/%postname%/"; // $our_permalink_structure == products-page/%wpsc_product_category%/%postname%/ (here's the problem!!!!) // Mostly the same conditions used for posts, but restricted to items with a post type of "wpsc-product " if ( '' != $permalink_structure && !in_array( $post->post_status, array( 'draft', 'pending' ) ) ) { $product_categories = wpsc_get_product_terms( $post_id, 'wpsc_product_category' ); // $product_categories == <array of translated product categories> $product_category_slugs = array( ); foreach ( $product_categories as $product_category ) { $product_category_slugs[] = $product_category->slug; // $product_categories_slugs == <array of translated product categories slugs> } // If the product is associated with multiple categories, determine which one to pick if ( count( $product_categories ) == 0 ) { $category_slug = 'uncategorized'; } elseif ( count( $product_categories ) > 1 ) { if ( (isset( $wp_query->query_vars['products'] ) && $wp_query->query_vars['products'] != null) && in_array( $wp_query->query_vars['products'], $product_category_slugs ) ) { $product_category = $wp_query->query_vars['products']; } else { $link = $product_categories[0]->slug; if ( ! in_array( 'wp_head', $wp_current_filter) && isset( $wpsc_query->query_vars['wpsc_product_category'] ) ) { $current_cat = $wpsc_query->query_vars['wpsc_product_category']; if ( in_array( $current_cat, $product_category_slugs ) ) $link = $current_cat; } $product_category = $link; // $product_category == <current product's product category> } $category_slug = $product_category; } else { // If the product is associated with only one category, we only have one choice if ( !isset( $product_categories[0] ) ) $product_categories[0] = ''; $product_category = $product_categories[0]; if ( !is_object( $product_category ) ) $product_category = new stdClass(); if ( !isset( $product_category->slug ) ) $product_category->slug = null; $category_slug = $product_category->slug; } $post_name = $post->post_name; // $post_name == <product slug> if ( get_option( 'product_category_hierarchical_url', 0 ) ) { $selected_term = get_term_by( 'slug', $category_slug, 'wpsc_product_category' ); if ( is_object( $selected_term ) ) { $term_chain = array( $selected_term->slug ); while ( $selected_term->parent ) { $selected_term = get_term( $selected_term->parent, 'wpsc_product_category' ); array_unshift( $term_chain, $selected_term->slug ); } $category_slug = implode( '/', $term_chain ); } } if( isset( $category_slug ) && empty( $category_slug ) ) $category_slug = 'product'; // $category_slug == <current product's product category> $category_slug = apply_filters( 'wpsc_product_permalink_cat_slug', $category_slug, $post_id ); $rewritereplace = array( //$rewritereplace == array of (<current product's product category>, <product slug>) $category_slug, $post_name ); $permalink = str_replace( $rewritecode, $rewritereplace, $our_permalink_structure ); //$permalink == products-page/<current product's product category>/<product slug>/ $permalink = user_trailingslashit( $permalink, 'single' ); $permalink = home_url( $permalink ); //$permalink == https://www.mywebsite.com/products-page/<current product's product category>/<product slug>/ (and the language slug is gone!!!!) } return apply_filters( 'wpsc_product_permalink', $permalink, $post->ID ); } add_filter( 'post_type_link', 'wpsc_product_link', 10, 3 ); // <--- Here's the wpsc_product_link filter setting.
So, PLL’s post_link filter actions are overwritten by the wpsc_product_link filter actions.
To temporarily fix this, I decreased the PLL’s post_link filter priority from 10 to 11, and now I get the language slug the same way as it was shown with PLL 1.1.6.
It seems to me that this is related to the order in which WordPress loads all the plugins.
I remember that the plugins are sorted alphabetically and then loaded, so the Polylang’s filters might be added before the WP e-Commerce filter, and since both filters have the same priority, the Polylang filter is applied first.
Well, at least that’s my theory.
I’ll continue testing to see what else do I find.
Again, thank you Chouby!
@miguelcortereal
I reproduced the message without file and line with PHP 5.2.4. I don’t know when PHP changed the debug_backtrace output but Polylang should be fixed now.When having the same priority, filters and actions are applied in the order plugins add them (if both plugins are adding filters at the same time, then the order in which plugins are executed applies).
In 1.1.6, the post_link filter is added quite late (in a wp_loaded action). It is now added in plugins_load action so much sooner. That’s probably the reason why it applies now before wp-ecommerce one.
I decreased the priority to 20 for all links filters in 1.2dev55 just uploaded.
Thank you for the explanation, Chouby.
I started “learning” PHP with WordPress about 3 weeks ago, so I still either don’t get or don’t know the whole inner workings of WordPress. Any help or orientation is really appreciated.
Now, let’s go to my next finding.
Moving Polylang’s pre_get_posts filters to the parse_query filters is causing me a situation similar to the one I described 2 posts above.
WP e-Commerce filters are again rewriting Polylang’s filters work. Here’s their filter hooked to pre_get_posts, changing the translated custom post id to the english custom post id.
add_filter( 'pre_get_posts', 'wpsc_generate_product_query', 11 ); function wpsc_generate_product_query( $query ) { global $wp_query; $prod_page = wpsc_get_the_post_id_by_shortcode('[productspage]'); $prod_page = get_post($prod_page); remove_filter( 'pre_get_posts', 'wpsc_generate_product_query', 11 ); $query->query_vars['taxonomy'] = null; $query->query_vars['term'] = null; // default product selection if ( $query->query_vars['pagename'] != '' ) { $query->query_vars['post_type'] = 'wpsc-product'; $query->query_vars['pagename'] = ''; $query->is_page = false; $query->is_tax = false; $query->is_archive = true; $query->is_singular = false; $query->is_single = false; } // If wpsc_item is not null, we are looking for a product or a product category, check for category if ( isset( $query->query_vars['wpsc_item'] ) && ($query->query_vars['wpsc_item'] != '') ) { $test_term = get_term_by( 'slug', $query->query_vars['wpsc_item'], 'wpsc_product_category' ); if ( $test_term->slug == $query->query_vars['wpsc_item'] ) { // if category exists (slug matches slug), set products to value of wpsc_item $query->query_vars['products'] = $query->query_vars['wpsc_item']; } else { // otherwise set name to value of wpsc_item $query->query_vars['name'] = $query->query_vars['wpsc_item']; } } if ( isset( $query->query_vars['products'] ) && ($query->query_vars['products'] != null) && ($query->query_vars['name'] != null) ) { unset( $query->query_vars['taxonomy'] ); unset( $query->query_vars['term'] ); $query->query_vars['post_type'] = 'wpsc-product'; $query->is_tax = false; $query->is_archive = true; $query->is_singular = false; $query->is_single = false; } if( isset($wp_query->query_vars['wpsc_product_category']) && !isset($wp_query->query_vars['wpsc-product'])){ $query->query_vars['wpsc_product_category'] = $wp_query->query_vars['wpsc_product_category']; $query->query_vars['taxonomy'] = $wp_query->query_vars['taxonomy']; $query->query_vars['term'] = $wp_query->query_vars['term']; }elseif( '' != ($default_category = get_option('wpsc_default_category')) && !isset($wp_query->query_vars['wpsc-product'])){ $default_term = get_term($default_category,'wpsc_product_category'); if(!empty($default_term) && empty($wp_query->query_vars['category_name'])){ $query->query_vars['taxonomy'] = 'wpsc_product_category'; $query->query_vars['term'] = $default_term->slug; $query->is_tax = true; }elseif(isset($wp_query->query_vars['name']) && $wp_query->is_404 && $wp_query->query_vars['category_name'] != $prod_page->post_name){ unset( $query->query_vars['taxonomy'] ); unset( $query->query_vars['term'] ); $query->query_vars['wpsc-product'] = $wp_query->query_vars['name']; $query->query_vars['name'] = $wp_query->query_vars['name']; }else{ $query->is_tax = true; $term = get_term_by('slug',$wp_query->query_vars['name'], 'wpsc_product_category' ); if(!empty($term)){ $query->query_vars['taxonomy'] = 'wpsc_product_category'; $query->query_vars['wpsc_product_category__in'] = array($term->term_taxonomy_id); $query->query_vars['wpsc_product_category'] = $wp_query->query_vars['name']; $query->query_vars['term'] = $wp_query->query_vars['name']; }elseif(is_numeric($default_category)){ $query->query_vars['taxonomy'] = 'wpsc_product_category'; }else{ $query->is_tax = false; } } } //If Product Tag Taxonomy if (isset($wp_query->query_vars['product_tag']) && $wp_query->query_vars['product_tag']){ $query->query_vars['product_tag'] = $wp_query->query_vars['product_tag']; $query->query_vars['term'] = $wp_query->query_vars['term']; $query->query_vars['taxonomy'] = 'product_tag'; $query->is_tax = true; } if(1 == get_option('use_pagination')){ $query->query_vars['posts_per_page'] = get_option('wpsc_products_per_page'); if( isset( $_GET['items_per_page'] ) ) { if ( is_numeric( $_GET['items_per_page'] ) ) { $query->query_vars['posts_per_page'] = (int) $_GET['items_per_page']; } elseif ( $_GET['items_per_page'] == 'all' ) { $query->query_vars['posts_per_page'] = -1; $query->query_vars['nopaging'] = 1; } } } else { $query->query_vars['posts_per_page'] = -1; $query->query_vars['nopaging'] = 1; } if ( $query->is_tax == true ) new wpsc_products_by_category( $query ); return $query; }
These are the modifications I had to revert in your code in order for it to work as it was before with PLL 1.2dev54 (without 404s):
diff -r polylang12dev55/frontend/choose-lang.php polylang12dev54/frontend/choose-lang.php 33c33 > add_filter('pre_get_posts', array(&$this, 'parse_main_query'), 1); // sets the language in special cases --- < add_filter('parse_query', array(&$this, 'parse_main_query'), 2); // sets the language in special cases diff -r polylang12dev55/frontend/frontend-filters.php polylang12dev54/frontend/frontend-filters.php 38c38 > add_filter('pre_get_posts', array(&$this, 'pre_get_posts'), 5); // filters posts according to the language --- < add_filter('parse_query', array(&$this, 'parse_query'), 4); // filters posts according to the language 139c138 > public function pre_get_posts($query) { --- < public function parse_query($query) {
By the way, I’m now testing Polylang using PHP 5.4.17. I haven’t detect any situation when compared to PHP 5.2.X, which I was using before.
If you require any additional information regarding this situation, feel free to ask me.
Thank you, Chouby!
Ignore what I wrote in my previous post.
I did further testing, and found out that if I only lower the priority of the filter located at line 38 in the fronted-filters.php file from:
add_filter('parse_query', array(&$this, 'parse_query'), 4);
to
add_filter('parse_query', array(&$this, 'parse_query'), 6);
I no longer get the 404 error when displaying the translated WP e-Commerce’s custom post products page.
I don’t know why. The only other WP e-Commerce filters/actions I find hooked to parse_query are:
add_filter( 'parse_query', 'wpsc_mark_product_query', 12 );
and to pre_get_posts:
add_filter( 'pre_get_posts', 'wpsc_split_the_query', 8 ); add_action( 'pre_get_posts', array( &$hide_subcatsprods, 'get_posts' ) ); add_filter( 'pre_get_posts', 'wpsc_generate_product_query', 11 ); add_action( 'pre_get_posts', 'wpsc_product_list_exclude_child_categories', 15 );
I’m sorry for misleading.
Thank you, Chouby.
It has nothing to do with wp-ecommerce. Correcting a bug, I did not pay attention that I re-introduced these 404 errors on pages. I just uploaded 1.2dev56 and hopefully it is OK now.
Glad you did it, I’ve spent the last hours spinning around a 404 error.
But you have something else to look for, in my case upon activation of dev56 it returns this:
Fatal error: Class ‘PLL_Links’ not found in /wp-content/plugins/polylang/admin/admin.php on line 161
Sorry. I added a new file and forgot to add it in the lists of files to upload ?? That should be fixed now.
It was easy then. Downloading it ??
I can report that the 404 is corrected now.
But now the translated custom posts (‘wpsc-products’) are not shown. $GLOBALS[‘post’] has their english counter parts instead, when using a language different than english.
So, after clicking the custom page permalink shown like this:
https://www.mywebsite.com/es/pagina-de-productos/
All the products (wpsc-product) custom posts permalinks inside that page show their permalinks like this (using a language different than english):
https://www.mywebsite.com/en/products-page/<english category>/<english product slug>
The products page permalink still remains in spanish. The ‘products-page’ slug is the only one I expected to be in english, because it’s the behavior I’ve been carrying since I started using Polylang.
I’m still checking what is now causing this with PLL 1.2dev56
And here’s something I found (I don’t know if this existed before PLL 1.2dev56):
Inside the file …polylang/frontend/frontend-auto-translate.php, there’s a pre_get_posts($query) function. At line 140 it shows the following foreach:
// name, pagename can only take one slug foreach (array('name', 'pagename') as $key) { if (!empty($qv[$key])) { // no function to get post by name except get_posts itself $post_type = empty($qv['post_type']) ? 'post' : $qv['post_type']; $id = $wpdb->get_var($wpdb->prepare("SELECT ID from $wpdb->posts WHERE post_type=%s AND post_name=%s", $post_type, $qv[$key])); $qv[$key] = ($id && ($tr_id = pll_get_post($id)) && $tr = get_post($tr_id)) ? $tr->post_name : $qv[$key]; } }
I have a Wp e-Commerce custom page that shows the following data when reaching that foreach:
$qv['name'] == NULL; $qv['pagename'] == 'products-page']; $qv['post_type'] == 'wpsc-product';
That custom page is stored in the wp_posts table with a ‘post_type’ == ‘page’, so PLL’s query doesn’t find the post ID since the post types don’t match.
I switched the ‘post_type’ part of the query for a post_status=’publish’, and the query found the english version of that post, and in the next row, it found the translated page, so $qv[‘pagename’] is now set to the translated name as expected.
Using post_status = ‘publish’, I’m limiting the post IDs this query might bring back. but I’m not sure if that’s good enough, though.
I’ll continue testing to see what else I can find.
For the first issue, how did it work with 1.1.6?
I am not aware that Polylang is compatible with WP-Ecommerce (I never tested it) and it probably require some tweaks.
For the second issue, I fear the problem is not with Polylang. When you query a post by name, you must add the post type in the query because WordPress does allow using the same name in different post types.
So if for some reason, a custom post of type ‘wpsc-product’ is stored in DB with post type ‘page’, there is something wrong. You should check that it is still the case with wp-ecommerce only to see if there is no interference with some plugin which creates this issue.
Polylang has only minor, non show stopping issues when used with WP e-Commerce.
The only situations I find, for the moment, is that the custom pages slugs, when viewing a single product, are the only items not translated in the complete permalink and that certain functionality is tied to their specific english custom pages post ID. For the last issue, I added a filter which fixes that, as described below. Everything else works fine.
To answer your questions, for the first issue, this is how it worked up until PLL 1.1.6 and PLL 1.2dev551 (lowering the parse_query filter priority to 6):
The custom products page will show:
In English:
https://www.mywebsite.com/en/products-page/In Spanish:
https://www.mywebsite.com/es/pagina-de-productos/Which is still the same behavior now obtained with PLL 1.2dev56.
Up until PLL 1.1.6 and PLL 1.2dev551, the custom products posts permalinks shown in a grid view inside the custom products page are:
In English:
https://www.mywebsite.com/en/products-page/<english product category>/<english product slug>
In Spanish:
https://www.mywebsite.com/es/products-page/<spanish product category>/<spanish product slug>
But now with PLL 1.2dev56 I only get the English version for either language.
Since WP e-Commerce uses the post ID to identify that their custom page is shown in order to apply to it their grid view template, I created a filter in my child theme’s function.php file, and hooked it to the function they use to get their english custom page id and used pll_get_post to send back the translated custom page post ID instead, and to update $wp_query->queried_object and $wp_query->queried_object_id with the translated post info, since WP e-Commerce uses queried_object_id to verify that it is in fact their custom page post ID.
It works great showing the translated custom posts in the grid view inside the translated custom page up unit PLL 1.2dev551, but with PLL 1.2dev56 I now get all the posts in both languages in either language of the custom products page post.
Each custom product post now shows their expected permalink, based on their language, though.
For the second issue, I find it odd, because when WP e-Commerce creates the custom products page, it declares it with a ‘page’ type, and later on I find in $wp_query that its type is referred to as ‘wpsc-product’, which is the custom products posts (not page) type. I have other WP e-Commerce related plugins, so maybe one of them is at fault here. I’ll have to check, though.
So, what could have happened in PLL 1.2dev56 that might create the first issue’s behavior?
Thank you, Chouby!
EDIT PS: The PLL’s change in behavior I had for the first issue (from always showing the posts permalinks from English posts in both languages to showing ALL the posts permalinks from both languages IN both languages) is happening after I started updating $wp_query->queried_object and $wp_query->queried_object_id with the custom products page information as WP e-Commerce requires. I’m guessing PLL is using either of them to validate something.
I had to update $wp_query->queried_object and $wp_query->queried_object_id, because every time the WP e-Commerce function that gets the post id by short code would evaluate $wp_query->queried_object_id, it would get back the PLL’s Spanish Language Model ID after my filter was applied (I’m guessing evaluating pll_get_post will leave that information there), instead of the english custom page post ID WP e-Commerce was expecting, which wasn’t convenient for me either.
OK. So if I well understand. No change from 1.1.6 to 1.2dev56. Am I right?
I am not sure to follow you but maybe you have issues due to auto translate feature (the code is in frontend/frontend-auto-translate.php). The feature can be disabled by setting PLL_AUTO_TRANSLATE to false in wp-config.php
No change from 1.1.6 to 1.2dev55, if on 1.2dev55 I lower the parse_query filter priority to 6, as I described 10 posts above to avoid the page’s 404s.
1.2dev56 introduces the issues I described.
I only get the posts in english inside the custom page, no matter which language I switch to, or after modifying $wp_query->queried_object and $wp_query->queried_object_id with the translated custom page ID as needed by WP e-Commerce, I get ALL the posts in both languages in the same custom page, no matter which language I switch to.
Is this related to PLL_AUTO_TRANSLATE?
Some say a picture is worth a 1000 words.
Here’s the issue I have when switching to English
Here’s the issue I have when switching to Spanish
This happens when I use PLL 1.2dev56, not with 1.2dev55 if I lower the parse_query filter priority to 6, nor with PLL 1.1.6 or below.
EDIT: I added define(‘PLL_AUTO_TRANSLATE’, ‘false’); in the wp-config.php file, as requested, cleared WP Super Cache cache and browser cache and I still get what’s shown in the pictures.
- The topic ‘Polylang 1.2 beta is ready for tests’ is closed to new replies.