silverstripe / silverstripe-framework

Silverstripe Framework, the MVC framework that powers Silverstripe CMS
https://www.silverstripe.org
BSD 3-Clause "New" or "Revised" License
719 stars 820 forks source link

FIX Add eagerloaded data to ALL relevant lists #11139

Closed GuySartorelli closed 4 months ago

GuySartorelli commented 4 months ago

Description

When a record belongs to multiple many_many (and maybe has_many) relations and you eagerload it and chained relations from it, you can end up in a scenario where the eagerloaded data doesn't get added to some of the relation lists it belongs to. More details in the linked issue.

Manual testing steps

  1. Add a breakpoint on DataList::getFinalisedQuery()
  2. Run this code
    use SilverStripe\Security\Member;
    $list = Member::get()->eagerLoad('Groups.Permissions');
    foreach ($list as $member) {
        foreach ($member->DirectGroups() as $group) {
            foreach ($group->Permissions() as $perm) {
                echo '';
            }
        }
    }
  3. Check the trace each time the breakpoint is hit. It should only be hit once directly from the above code.

You could also add a breakpoint in the above code itself, and check that each list being looped over (with exception for the top loop) is an instance of EagerLoadedList, not DataList.

Issues

Pull request checklist

GuySartorelli commented 4 months ago

Note that I have confirmed the new test fails without this fix.

GuySartorelli commented 4 months ago

Oops! Good catch. Targetted to 5.1