Skip to content Skip to sidebar

This thread is resolved. Here is a description of the problem and solution.

Problem:
If you're experiencing outdated page previews in WordPress while using WPML, it might be due to WPML's parse_query flow setting a fixed single-post ID ('p') on the WP_Query. This issue occurs because during the preview, WordPress queries the latest autosave revision, but the 'p' set by WPML persists, preventing the latest revision from being fetched.

Solution:
We recommend implementing a minimal, safe fix by modifying the WPML_Query_Parser::parse_query method. Here's a step-by-step guide:
1. Open the file located at

classes/query-filtering/class-wpml-query-parser.php

.
2. Locate the section where the post_type is computed.
3. Add a guard early in the method to clear any leftover single-ID constraints for revision queries. Here's the code you should add:

if ( ! empty( $q->query_vars['post_type'] ) ) {<br />  $post_type = $q->query_vars['post_type'];<br />}<br />$pt_is_revision = ( is_array( $post_type ) && in_array( 'revision', $post_type, true ) ) || $post_type === 'revision';<br />if ( $pt_is_revision ) {<br />  unset( $q->query_vars['p'], $q->query_vars['page_id'], $q->query_vars['name'], $q->query_vars['pagename'] );<br />}

This change ensures that preview requests correctly fetch the most recent autosave revision without being pinned to an old revision ID. Normal WPML routing and translated front-end behavior remain unchanged.

Please note that this solution might be irrelevant if it's outdated or not applicable to your case. We highly recommend checking related known issues at https://wpml.org/known-issues/, verifying the version of the permanent fix, and confirming that you have installed the latest versions of themes and plugins. If the issue persists, please open a new support ticket at WPML support forum.

This is the technical support forum for WPML - the multilingual WordPress plugin.

Everyone can read, but only WPML clients can post here. WPML team is replying on the forum 6 days per week, 22 hours per day.

This topic contains 8 replies, has 0 voices.

Last updated by Carlos Rojas 1 month, 2 weeks ago.

Assisted by: Carlos Rojas.

Author Posts
September 9, 2025 at 6:10 am #17385561

Henning

<b>Background of the issue: </b>
I am trying to address an issue similar to the one reported in https://wpml.org/forums/topic/preview-of-page-is-heavily-outdated-because-of-parse_query-hook/. I am unable to update the topic as replies have been closed. The issue involves WPML’s parse_query flow setting the single-post ID (`p`) on the WP_Query, which affects the preview of pages. During preview, WordPress queries the latest autosave revision, but the `p` set by WPML persists, resulting in an outdated preview. The code involved is in classes/query-filtering/class-wpml-query-parser.php, where WPML’s slug-to-ID conversion sets `p` on the query. A minimal, safe fix involves clearing leftover single-ID constraints for revision queries.

<b>Symptoms: </b>
The preview of the page is heavily outdated because the revision-fetch query inherits a fixed ID, preventing the latest revision from being fetched.

<b>Questions: </b>
When will you address this problem?

<b>Further input:</b>

### Diagnosis

- The ID constraint (AND posts.ID = 4469) comes from WPML’s parse_query flow setting the single-post ID (`p`) on the WP_Query. That conversion is done to resolve slugs to the correct translated post by ID.
- During preview, WordPress briefly queries the latest autosave revision with a query like post_type = 'revision' and post_parent = {original ID}. Because the same WP_Query instance (or its vars) is reused/mutated for this follow-up revision query, the earlier `p` set by WPML persists and forces a specific revision ID, resulting in an outdated preview.

Where it happens:

414:443:classes/query-filtering/class-wpml-query-parser.php

if ( $post_type ) {
  $first_post_type = reset( $post_type );

  if ( $this->sitepress->is_translated_post_type( $first_post_type ) && ! empty( $q->query_vars['name'] ) ) {
    if ( is_post_type_hierarchical( $first_post_type ) ) {
      $requested_page = get_page_by_path( $q->query_vars['name'], OBJECT, $first_post_type );
      if ( $requested_page && 'attachment' !== $requested_page->post_type ) {
        $q->query_vars['p'] = $this->post_translations->element_id_in( $requested_page->ID, $current_language, true );
        unset( $q->query_vars['name'] );
        $q->query_vars[ $first_post_type ] = '';
      }
    } else {
      // ...
      $pid = $this->wpdb->get_var( $pid_prepared );
      if ( ! empty( $pid ) ) {
        $q->query_vars['p'] = $this->post_translations->element_id_in( $pid, $current_language, true );
        unset( $q->query_vars['name'] );
      }
    }
  }
  // ...
}

That `p` then carries into the subsequent revision query, adding “AND posts.ID = …”.

### Root cause

- WPML’s slug-to-ID conversion sets `p` on the query.
- The revision-fetch query (post_type `revision`) inherits/retains `p`, so MySQL is filtered by a fixed ID instead of returning the latest revision.

### Minimal, safe fix

- For revision queries, explicitly clear any leftover single-ID constraints before WPML makes further adjustments. This ensures WordPress can select the latest autosave revision.

Add a guard early in `WPML_Query_Parser::parse_query` (right after `$post_type` is computed):

389:399:classes/query-filtering/class-wpml-query-parser.php

$post_type = 'post';
if ( ! empty( $q->query_vars['post_type'] ) ) {
  $post_type = $q->query_vars['post_type'];
}

// NEW: don't force a specific ID on revision queries (e.g., editor preview autosaves)
$pt_is_revision = ( is_array( $post_type ) && in_array( 'revision', $post_type, true ) ) || $post_type === 'revision';
if ( $pt_is_revision ) {
  unset( $q->query_vars['p'], $q->query_vars['page_id'], $q->query_vars['name'], $q->query_vars['pagename'] );
}

Notes:
- Admin screens are already excluded at the top of the method, so this won’t affect the wp-admin “Revisions” UI.
- We do not early-return; other non-invasive adjustments can still run, but there’s nothing WPML needs to alter for `revision`.

### Optional hardening

- Wrap the slug-to-ID conversion block itself in a condition that avoids applying it to non-main queries. Example: only convert when `$q->is_main_query()`; however, this is broader and could affect secondary queries in themes/plugins. The targeted `revision` guard above is safer.

### Outcome

- Preview requests will correctly fetch the most recent autosave revision without being pinned to an old revision ID.
- Normal WPML routing and translated front-end behavior remain unchanged.

- Fixed the root cause: leftover `p` on subsequent `revision` queries caused by slug-to-ID conversion in `parse_query`.
- Proposed a small guard in `WPML_Query_Parser::parse_query` to unset `p`/`page_id`/`name`/`pagename` when post_type is `revision`, ensuring previews fetch the latest autosave.

September 9, 2025 at 10:01 am #17386517

Carlos Rojas
WPML Supporter since 03/2017

Languages: English (English ) Spanish (Español )

Timezone: Europe/Madrid (GMT+01:00)

Hello,
Thank you for contacting us

I have created a sandbox site with a fresh new WordPress + WPML installation where you can access via this link: hidden link

Please access the Sandbox site and try to reproduce the issue. If the issue persists in this minimal setup, create a video showing the steps to reproduce the problem and share a link in your next message.

Looking forward to your message.
Regards,
Carlos

September 9, 2025 at 11:29 am #17386897

Henning

Hi Carlos,

please refer to the ticket https://wpml.org/forums/topic/repost-preview-of-page-is-still-heavily-outdated-because-of-parse_query-hook/ – you have been presented with a staging environment where the problem is reproducible so it won't make much sense for me to re-create something that is already existent...

Talking to the ticket issuer, they seem to have found a temporary workaround:

"Posts with too many revisions cause the previews to become outdated. If I delete some of them and limit the number of revisions, the preview works again."

But ideally WPML would apply the suggested fix and make sure that previews are not being passed a fixed post ID.

Can't you consider this? What makes us stay in this dreaded support-loop which causes all sides effort and time...?

Thanks & regards

Henning

September 9, 2025 at 1:07 pm #17387245

Carlos Rojas
WPML Supporter since 03/2017

Languages: English (English ) Spanish (Español )

Timezone: Europe/Madrid (GMT+01:00)

Hi Henning,
Thank you very much for your message

I understand your point; however, the staging site shared with my colleague in the ticket you mentioned doesn't rule out the possibility that this issue happens only with WPML plugins in a new WordPress installation. I don't doubt your findings. I need to reproduce them in a clean installation (like the sandbox site I shared) so I can escalate it properly.

Thank you very much for your understanding!

September 9, 2025 at 1:24 pm #17387277

Henning

Hi Carlos,

thanks for getting back.

What you are asking for is the reproducibility of an edge-case bug in a clean environment which kind of is a contradiction in itself...

This issue has been reported by three users in different scenarios in great technical detail and you have been provided with a code solution already that is easy enough to be implemented and has already been verified in production. It directly correlates to WPML and the code I have pointed towards.

Asking to go back to square one and then probably not being able to reproduce this in a "clean" environment may be adhering to your support terms but doesn't help us users at all...

If you want to close this ticket then sure, go ahead. I am feeling very frustrated and only wanted to share a 'ready-to-deploy' fix with minimal impacts as it only targets editor previews and it would IMHO make more sense for you guys to verify the fix within your build pipeline / test suite instead.

Nevermind, you're only doing your job I guess but it sure doesn't make me want to use WPML any more when this issue isn't being addressed in core and I need to tell my clients to keep using workarounds or fork your plugin internally.

Kind regards,
Henning

September 10, 2025 at 8:05 am #17389399

Carlos Rojas
WPML Supporter since 03/2017

Languages: English (English ) Spanish (Español )

Timezone: Europe/Madrid (GMT+01:00)

Good morning Henning,
Thank you very much for your message

I'm consulting this issue with my colleagues, and I will get back to you as soon as I get an answer.

September 10, 2025 at 8:23 am #17389480

Carlos Rojas
WPML Supporter since 03/2017

Languages: English (English ) Spanish (Español )

Timezone: Europe/Madrid (GMT+01:00)

Hi again,

Our 2nd-tier specialists are already aware of this issue, and they asked if you could test their workaround in your staging site. Here are the steps to follow:
- Edit /wp-content/plugins/sitepress-multilingual-cms/inc/query-filtering/wpml-name-query-filter.class.php
- Replace this function:

private function get_single_slug_adjusted_IDs( $page_name_for_query, $post_parent ) {
    $cache     = new WPML_WP_Cache( get_class( $this ) );
    $cache_key = 'get_single_slug_adjusted_IDs' . $this->post_type . $page_name_for_query . $post_parent;
    $found     = false;

    $pages_with_name = $cache->get( $cache_key, $found );

    if ( ! $found ) {
        $pages_with_name = $this->get_single_slug_adjusted_IDs_from_DB( $page_name_for_query, $post_parent );
        $cache->set( $cache_key, $pages_with_name );
    }

    return array( 'matching_ids' => $pages_with_name );
}

- With this one:

private function get_single_slug_adjusted_IDs( $page_name_for_query, $post_parent ) {
    $cache     = new WPML_WP_Cache( get_class( $this ) );
    $cache_key = 'get_single_slug_adjusted_IDs' . $this->post_type . $page_name_for_query . $post_parent;
    $found     = false;

    $pages_with_name = $cache->get( $cache_key, $found );

    if ($this->post_type == 'revision') {
       return null;
     }

    if ( ! $found ) {
        $pages_with_name = $this->get_single_slug_adjusted_IDs_from_DB( $page_name_for_query, $post_parent );
        $cache->set( $cache_key, $pages_with_name );
    }

    return array( 'matching_ids' => $pages_with_name );
}

- Save the changes and let me know the results

September 11, 2025 at 7:03 am #17392764

Henning

Hi Carlos,

thanks for getting back and being productive in solving this issue.

I have just tested the patch (= skipping the cache with revisions) and can confirm that the problem is not existent any more – previews load the correct content and are functional again.

Looking forward to seeing this being rolled out with the next version.

Thanks again!

September 11, 2025 at 9:28 am #17393357

Carlos Rojas
WPML Supporter since 03/2017

Languages: English (English ) Spanish (Español )

Timezone: Europe/Madrid (GMT+01:00)

Hi Henning,
I'm happy to hear that the issue was solved 🙂

Our developers are already aware of this issue and the workaround. Please don't hesitate to contact us if you need our help in the future with WPML. We are here to help!

Have an excellent day!