Fix media uploaded in a non-default WPML language never finishing sync - #1281
Open
gabrielcld2 wants to merge 3 commits into
Open
gabrielcld2 wants to merge 3 commits into
gabrielcld2 wants to merge 3 commits into
Conversation
WPML hooks WordPress's `home_url` filter to inject the browsing language into every generated URL. Since rest_url() applies that filter to the REST base before the endpoint path is appended, a non-default language corrupts the background sync loopback URL into e.g. `/wp-json/?lang=fr/cloudinary/v1/queue` instead of a valid route. The loopback request "succeeds" (200) by hitting the REST index rather than the sync endpoint, so queued assets are silently never processed and stay stuck in a "syncing" state.
utkarshcloudinary
left a comment
Collaborator
There was a problem hiding this comment.
Reviewed with help of AI and left feedback.
remove_global_hooks() alone only fixes directory/domain negotiation mode, where WPML separately hooks core's rest_url filter to re-insert the language after the full URL is built. In parameter mode (WPML_Lang_Parameter_Filters), nothing does that, so the cleaned URL was missing ?lang= entirely - not just for the sync loopback, but for every Utils::rest_url() consumer (asset fetch/save, cache purge, analytics, UI state), silently running them under the default language's context. wpml_permalink is WPML's documented API for exactly this and is idempotent across all three negotiation modes. Also wraps the hook removal in try/finally so a thrown exception can't leave WPML's URL filters permanently disabled for the rest of the request, and guards the undocumented remove_global_hooks/ add_global_hooks methods with method_exists(). Addresses review feedback on PR #1281.
Collaborator
Author
|
@utkarshcloudinary thanks for the review! I've addressed the issues you found, and did some manual testing again to confirm the solution still works as expected. Please have another look |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes media uploaded from a non-default WPML language getting permanently stuck in a "syncing" state
Approach
home_urlfilter to inject the browsing language into every generated URL.Utils::rest_url()builds the loopback URL by calling corerest_url( $path ), which applies that filter to the REST base before the endpoint path is appended.http://site/wp-json/?lang=fr/cloudinary/v1/queueinstead ofhttp://site/wp-json/cloudinary/v1/queue?lang=fr.php/integrations/class-wpml.phpby hooking the existingcloudinary_rest_urlfilter:WPML_URL_Filters::remove_global_hooks()/add_global_hooks()pattern (the same mechanism WPML uses internally for its Google Site Kit and canonical-URL compatibility code) to get a clean, language-unfiltered URL, wrapped intry/finallyso a thrown exception can't leave WPML's URL filters disabled for the rest of the request.wpml_permalinkfilter.remove_global_hooks()alone is only enough in directory/domain negotiation mode, where WPML separately hooks core'srest_urlfilter to re-insert the language after the full URL is built. In "language as a parameter" mode there's no such hook, so the clean URL would be missing?lang=entirely — not just for the sync loopback, but for everyUtils::rest_url()consumer (asset fetch/save, cache purge, analytics, UI state), silently running them under the default language's context instead.wpml_permalinkis a no-op when the URL already carries the right language (directory/domain mode) and correctly appends it when it doesn't (parameter mode).remove_global_hooks/add_global_hooksmethods withmethod_exists()in case a future WPML release renames or removes them.QA notes
?lang=fr), upload a new image to the Media Library.media_contextmatches the language it was uploaded in (verified viawp_cloudinary_relationships).media_contextset to the default language.