FIX: Fix Member_GroupSet::removeAll() (fixes #3948)

This commit is contained in:
Loz Calver 2018-01-24 16:21:29 +00:00
parent 179996b5f9
commit c2cd6b3832
2 changed files with 60 additions and 0 deletions

View File

@ -1791,6 +1791,37 @@ class Member_GroupSet extends ManyManyList {
}
}
public function removeAll() {
$base = ClassInfo::baseDataClass($this->dataClass());
// Remove the join to the join table to avoid MySQL row locking issues.
$query = $this->dataQuery();
$foreignFilter = $query->getQueryParam('Foreign.Filter');
$query->removeFilterOn($foreignFilter);
$selectQuery = $query->query();
$selectQuery->setSelect("\"{$base}\".\"ID\"");
$from = $selectQuery->getFrom();
unset($from[$this->joinTable]);
$selectQuery->setFrom($from);
$selectQuery->setOrderBy(); // ORDER BY in subselects breaks MS SQL Server and is not necessary here
$selectQuery->setDistinct(false);
// Use a sub-query as SQLite does not support setting delete targets in
// joined queries.
$delete = new SQLDelete();
$delete->setFrom("\"{$this->joinTable}\"");
// Use ManyManyList::foreignIDFilter() rather than the one in this class
// otherwise we end up selecting the wrong columns
$delete->addWhere(parent::foreignIDFilter());
$subSelect = $selectQuery->sql($parameters);
$delete->addWhere(array(
"\"{$this->joinTable}\".\"{$this->localKey}\" IN ($subSelect)" => $parameters
));
$delete->execute();
}
/**
* Determine if the following groups IDs can be added
*

View File

@ -385,6 +385,35 @@ class MemberTest extends FunctionalTest {
);
}
/**
* Assertions to check that Member_GroupSet is functionally equivalent to ManyManyList
*/
public function testRemoveGroups()
{
$staffmember = $this->objFromFixture('Member', 'staffmember');
$staffgroup = $this->objFromFixture('Group', 'staffgroup');
$managementgroup = $this->objFromFixture('Group', 'managementgroup');
$this->assertTrue(
$staffmember->inGroups(array($staffgroup, $managementgroup)),
'inGroups() succeeds if a membership is detected on one of many passed groups'
);
$staffmember->Groups()->remove($managementgroup);
$this->assertFalse(
$staffmember->inGroup($managementgroup),
'member was not removed from group using ->Groups()->remove()'
);
$staffmember->Groups()->removeAll();
$this->assertEquals(
0,
$staffmember->Groups()->count(),
'member was not removed from all groups using ->Groups()->removeAll()'
);
}
public function testAddToGroupByCode() {
$grouplessMember = $this->objFromFixture('Member', 'grouplessmember');
$memberlessGroup = $this->objFromFixture('Group','memberlessgroup');