Summary
FileRepository::matchPosts() joins fof_upload_files to posts with actor_id = user_id. This means files uploaded by users who have since been deleted (or files embedded in another user's post) can never be matched — and a subsequent --cleanup will delete them.
Steps to reproduce
- User A uploads an image in a post
- User A's account is deleted (but their posts remain)
- Run
php flarum fof:upload --map --cleanup
- The file is deleted because
--map couldn't associate it with any post
Root cause
In src/Repositories/FileRepository.php, matchPosts() uses:
->leftJoin('posts', function (JoinClause $join) use ($table, $db, $prefix) {
$join
->on("$table.actor_id", '=', 'posts.user_id') // ← only matches posts by the uploader
->where(function ($q) use ($table, $db, $prefix) {
$q->where('posts.content', 'like', $db->raw("CONCAT('%', $prefix$table.url, '%')"))
->orWhere('posts.content', 'like', $db->raw("CONCAT('%', $prefix$table.uuid, '%')"));
});
})
The actor_id = user_id constraint limits matching to posts authored by the file's uploader. When that user is deleted (posts.user_id becomes NULL or the user row is gone), the join produces no matches.
This also affects a secondary scenario: if user B quotes or embeds a file originally uploaded by user A, --map won't find that association either.
Suggested fix
Remove the actor_id = user_id join condition. The content matching (LIKE '%url%' OR LIKE '%uuid%') is already sufficient to correctly associate files with posts. The same fix should be applied in matchFilesForPost() if a similar constraint exists there.
The same issue exists in the 1.x branch.
Environment
Summary
FileRepository::matchPosts()joinsfof_upload_filestopostswithactor_id = user_id. This means files uploaded by users who have since been deleted (or files embedded in another user's post) can never be matched — and a subsequent--cleanupwill delete them.Steps to reproduce
php flarum fof:upload --map --cleanup--mapcouldn't associate it with any postRoot cause
In
src/Repositories/FileRepository.php,matchPosts()uses:The
actor_id = user_idconstraint limits matching to posts authored by the file's uploader. When that user is deleted (posts.user_idbecomes NULL or the user row is gone), the join produces no matches.This also affects a secondary scenario: if user B quotes or embeds a file originally uploaded by user A,
--mapwon't find that association either.Suggested fix
Remove the
actor_id = user_idjoin condition. The content matching (LIKE '%url%' OR LIKE '%uuid%') is already sufficient to correctly associate files with posts. The same fix should be applied inmatchFilesForPost()if a similar constraint exists there.The same issue exists in the 1.x branch.
Environment
matchPosts()after PR [2.x] fix: correctly map and clean up files for all upload templates #459 (which fixed URL/UUID matching but left the join condition unchanged)