I had a number of ghost edits on my site too. It looks like they were over 5 years old, and they were actually edits that were already approved but for some reason XenForo still thinks they are queued. I could not find a situation that would cause that. The only solution for that would be to remove the orphaned records from xf_approval_queue. Possibly there was a bug around 2020 that was fixed around that time, but I cannot find any code change related to it. Unless you can confirm the exact same behavior, my assumption is that these were generated during development testing and are irrelevant to any real usage.
However, I was able to imagine a situation where an edit doesn't show in the queue but is still flagged as needing approval. The only potential cause I could find for that was automated edits. Sometimes this might occur during specific upgrades, but you can do it manually using mass edits. Basically if you have edits in the approval queue and those edits happen to match the mass edit replace criteria, a new edit is auto-generated with the changes. Unlike editing manually, when the page is locked for editing until the edit is reviewed, auto-generating an edit bypasses this. Now because the edit waiting for approval is a moot edit (there are newer edits), the system doesn't allow moderators to approve/deny.
This is a bit annoying because the system will change in 4.2, where we can have multiple new edits that need to be merged. But we can't do this in the current version. Instead, we just have to show the entry in the queue and only allow moderators to Deny.
In
src/addons/vw/vw/_core/model/ui/tab/revision/vw.php, find and remove:
Code:
if ($item['dateline'] < $extreme['current_dateline'])
{
return false;
}
else if ($item['dateline'] == $extreme['current_dateline'])
{
// test for rollback to pending
$page = vw_Hard_Core::controller('Fetch')->get('Page', $item['itemid']);
if (!$page OR !isset($page['has_pending']))
{
return false;
}
}
In
src/addons/vw/vw/Handler/ApprovalQueue/Revision.php, find:
Code:
class Revision extends base
{
AFTER it, add:
Code:
public function getTemplateData(\XF\Entity\ApprovalQueue $unapprovedItem)
{
$params = parent::getTemplateData($unapprovedItem);
if (!\vw_Hard_Core::model('Version')->installed('4.2.0 Alpha 0'))
{
$item = $params['content']->toArray();
$itemid = $item['pageid'];
$extreme = \vw_Hard_Core::controller('Fetch/Page')->to_the_extreme($itemid);
$ok = true;
if ($item['dateline'] < $extreme['current_dateline'])
{
$ok = false;
}
else if ($item['dateline'] == $extreme['current_dateline'])
{
// test for rollback to pending
$page = \vw_Hard_Core::controller('Fetch')->get('Page', $item['itemid']);
if (!$page OR !isset($page['has_pending']))
{
$ok = false;
}
}
if (!$ok)
{
unset($params['vwActions']['approve']);
}
}
return $params;
}
Marking this as Fixed in the next release, since we will now show moot edits in the approval queue with the only option being to Deny them, rather than hiding them.
This has been more thoroughly fixed in the next release, by decoupling the permissions checks in can_approve_tab. We have individualized checks for can_approve_tab vs can_deny_tab. They normally mean the same thing, except for edits, where approval can only be performed against the newest edit in the current version. A new can_approval_tab is now used to determine whether to show approval queue entries or the Change Moderation Status tab. It emulates the behavior from previous versions by returning true if the user can at least 1 of can_approve_tab or can_deny_tab.