Describe the bug
Utils::get_post_id_by_url() caches its result under url-to-postid-<hash> for WEEK_IN_SECONDS, in two places: src/Utils/class-utils.php:446 for the url_to_postid() match, and :481 for the slug match. Nothing invalidates that key — there is no wp_cache_delete() for it, and no hook on post changes.
A cached resolution can therefore disagree with the site for up to a week after the post behind a URL changes. Visibility is checked on return, so this is a freshness and correctness issue rather than an access one.
To Reproduce
On a site with a persistent object cache:
- Create a private page with the slug
example-slug.
- Resolve a URL ending in
/example-slug/ through any feature that maps URLs to posts, so the result is cached.
- Publish a post with the same slug. WordPress keeps slugs unique only within a post type, so a page and a post can share one.
- Resolve the same URL again.
The lookup keeps returning the earlier resolution until the entry expires. Clearing the object cache returns the expected post.
The same cause affects neighbouring cases: a cached post that is later unpublished, deleted, or given a different slug.
Expected behavior
The lookup reflects the current state of the site, or the cached entry is invalidated when the posts behind it change.
Environment
wp-parsely 3.24.x, any WordPress version. Only observable on sites with a persistent object cache; without one the entry lasts a single request.
Additional context
Raised by CodeRabbit on #4662.
Possible directions: invalidate the key on save_post/deleted_post, shorten the TTL, or key the entry so that a stale hit cannot occur. Addressing it at a single call site would leave the other paths above untouched.
Describe the bug
Utils::get_post_id_by_url()caches its result underurl-to-postid-<hash>forWEEK_IN_SECONDS, in two places:src/Utils/class-utils.php:446for theurl_to_postid()match, and:481for the slug match. Nothing invalidates that key — there is nowp_cache_delete()for it, and no hook on post changes.A cached resolution can therefore disagree with the site for up to a week after the post behind a URL changes. Visibility is checked on return, so this is a freshness and correctness issue rather than an access one.
To Reproduce
On a site with a persistent object cache:
example-slug./example-slug/through any feature that maps URLs to posts, so the result is cached.The lookup keeps returning the earlier resolution until the entry expires. Clearing the object cache returns the expected post.
The same cause affects neighbouring cases: a cached post that is later unpublished, deleted, or given a different slug.
Expected behavior
The lookup reflects the current state of the site, or the cached entry is invalidated when the posts behind it change.
Environment
wp-parsely 3.24.x, any WordPress version. Only observable on sites with a persistent object cache; without one the entry lasts a single request.
Additional context
Raised by CodeRabbit on #4662.
Possible directions: invalidate the key on
save_post/deleted_post, shorten the TTL, or key the entry so that a stale hit cannot occur. Addressing it at a single call site would leave the other paths above untouched.