Links of posts with page numbers (like the last post link or links formed from search results) are not correcly formed based on if the user can see unapproved post or not. Say for example, a link to page 661 is formed. Iif a non-admin or anonymous user's total page available to him is only 657 (because he can't see unapproved posts), then this fails (because he has no page 661) and the last post link falls back to page 1 while the search result link will give the wrong page result. An admin has 661 pages available to him (because he can see unapproved post) so the link to page 661 works for him.
I had an AI coding agent correct it and it seemed to fix it, but I hope you fix this in your future updates because I do still want your regular offical updates. The AI did not nail it in one try. I let it work on your version 3 release (the latest version I think). I can share the code it generated via github if you want it. Here are the agent's responses:
## Fix Applied: User-group-aware URL caching
**The issue was confirmed** — the problem is in the URL caching mechanism in `get_full_url()` in `classes/Posts.php`. The cache key for post URLs was the same for all users, so when an admin visited a page and generated a post URL (with page 661, including unapproved posts), it got cached and served to non-admin users who only have 657 pages available.
### What was changed
In `get_full_url()` (line 1287), the cache key now includes a suffix that differentiates between users who can see unapproved posts and those who cannot:
- **`au` suffix**: For admins, moderators, and users with 'au' (approve/unapprove) permission — their URLs include page numbers based on all posts (including unapproved)
- **`noau` suffix**: For all other users (regular logged-in users, anonymous guests) — their URLs include page numbers based on approved posts only
This means:
- **Admins** still get URLs with page 661 (their perspective)
- **Non-admins** (including anonymous users) get URLs with page 657 (their perspective)
- Each group gets its own cached version, so no more incorrect page numbers
The `get_position_in_topic()` method was **reverted** to its original logic — it correctly calculates position based on the current user's permissions.
***************
I see the problem now. There are **two caching layers** at play:
- **URL cache** (`WPF()->cache->on('url')`) — This is what I fixed with the `au`/`noau` suffix. This part is working correctly now.
- **Post object cache** (`WPF()->cache->on('post')`) — This caches the **entire post object** including the `full_url` field. When `wpforo_post($postid, 'url')` is called, it first checks the post cache. If the post object is cached (with the admin's URL), it returns that URL directly without ever calling `get_full_url()`.
So the fix I made to the URL cache key is being **bypassed** by the post object cache. The post object cache key is `$postid . '_' . $this->special_key` where `special_key` is locale-based (not user-group-based). So when an admin visits a page, the post object gets cached with the admin's URL (page 661). When a non-admin visits, the cached post object is returned with the wrong URL.
The fix needs to also make the **post object cache** user-group-aware. The cleanest approach is to modify `get_full_url()` so that when it computes the URL, it also updates the post's `full_url` and `url` fields in the in-memory cache. And for the file cache, we need to either:
- Make the post cache key user-group-aware, OR
- Not cache the URL inside the post object
I think the best approach is: **In `get_full_url()`, after computing the URL, also update the post's `full_url` and `url` in the static RamCache (`self::$cache['post']`)** so that within the same page load, subsequent calls get the correct URL. And for the file cache, we should **not cache the URL inside the post object** — instead, always compute it fresh.
Would you like me to proceed with this approach? If so, please toggle to **ACT MODE**.
*****
I've confirmed the issue and implemented the fix. The problem was that the **post object cache** (in `classes/Cache.php`) was not user-group-aware. When an admin visited a page, the post object (including its URL with page 661) was cached with a key that didn't include user group info. When a non-admin visited the same page, the cached post object was returned with the admin's URL (page 661), even though the non-admin only had 657 pages available.
The previous fix (commit `c09225d`) only addressed the **URL cache** in `classes/Posts.php` by adding an `au`/`noau` suffix to URL cache keys. However, the **post object cache** was still using a single key for all users, bypassing the URL cache entirely.
The fix: Changed `apply_filters( 'wpforo_cache_by_usergroup', false )` to `apply_filters( 'wpforo_cache_by_usergroup', true )` in `classes/Cache.php`. This enables the built-in (but previously disabled) mechanism that includes user group IDs in the cache `special_key`, ensuring that admins and non-admins get separate cache entries for post objects, topics, forums, and URLs.
******
I see the issue! The `set_special_key()` method at line 64 also calls `apply_filters('wpforo_cache_by_usergroup', false)` with `false` as the default. Since no filter is actually registered (we only changed the default in the constructor's `apply_filters()` call), this still returns `false` in `set_special_key()`, so user group IDs are NOT being included in the cache key.
I need to also change line 64 from `false` to `true`. Let me fix this.
Let me toggle to **ACT MODE** to make the fix.
********
I found and fixed the bug. The `set_special_key()` method in `classes/Cache.php` was still calling `apply_filters('wpforo_cache_by_usergroup', false)` with `false` as the default value. Since no filter is actually registered for `wpforo_cache_by_usergroup`, this always returned `false`, meaning user group IDs were never included in the cache key — regardless of the constructor change.
The fix: Changed line 64 from `apply_filters('wpforo_cache_by_usergroup', false)` to `apply_filters('wpforo_cache_by_usergroup', true)`. Now both the constructor (line 30) and `set_special_key()` (line 64) use `true` as the default, so user group IDs are properly included in the cache `special_key`.
This ensures that admins, logged-in non-admins, and anonymous users all get separate cache entries with correct page numbers based on their permissions.