Skip to content

Commit 825dd4b

Browse files
authored
Merge pull request #10333 from creative-commoners/pulls/4.10/fix-group-code-dedupe
FIX Resolve deduping problem with group codes.
2 parents 67d5c15 + e0c4f01 commit 825dd4b

File tree

3 files changed

+76
-36
lines changed

3 files changed

+76
-36
lines changed

src/Security/Group.php

+25-20
Original file line numberDiff line numberDiff line change
@@ -482,16 +482,7 @@ public function getTreeTitle()
482482
*/
483483
public function setCode($val)
484484
{
485-
$currentGroups = Group::get()
486-
->map('Code', 'Title')
487-
->toArray();
488-
$code = Convert::raw2url($val);
489-
$count = 2;
490-
while (isset($currentGroups[$code])) {
491-
$code = Convert::raw2url($val . '-' . $count);
492-
$count++;
493-
}
494-
$this->setField("Code", $code);
485+
$this->setField('Code', Convert::raw2url($val));
495486
}
496487

497488
public function validate()
@@ -522,16 +513,6 @@ public function validate()
522513
->map('Code', 'Title')
523514
->toArray();
524515

525-
if (isset($currentGroups[$this->Code])) {
526-
$result->addError(
527-
_t(
528-
'SilverStripe\\Security\\Group.ValidationIdentifierAlreadyExists',
529-
'A Group ({group}) already exists with the same {identifier}',
530-
['group' => $this->Code, 'identifier' => 'Code']
531-
)
532-
);
533-
}
534-
535516
if (in_array($this->Title, $currentGroups)) {
536517
$result->addError(
537518
_t(
@@ -566,6 +547,9 @@ public function onBeforeWrite()
566547
if (!$this->Code && $this->Title != _t(__CLASS__ . '.NEWGROUP', "New Group")) {
567548
$this->setCode($this->Title);
568549
}
550+
551+
// Make sure the code for this group is unique.
552+
$this->dedupeCode();
569553
}
570554

571555
public function onBeforeDelete()
@@ -726,4 +710,25 @@ public function requireDefaultRecords()
726710

727711
// Members are populated through Member->requireDefaultRecords()
728712
}
713+
714+
/**
715+
* Code needs to be unique as it is used to identify a specific group. Ensure no duplicate
716+
* codes are created.
717+
*
718+
* @deprecated 5.0 Remove deduping in favour of throwing a validation error for duplicates.
719+
*/
720+
private function dedupeCode(): void
721+
{
722+
$currentGroups = Group::get()
723+
->exclude('ID', $this->ID)
724+
->map('Code', 'Title')
725+
->toArray();
726+
$code = $this->Code;
727+
$count = 2;
728+
while (isset($currentGroups[$code])) {
729+
$code = $this->Code . '-' . $count;
730+
$count++;
731+
}
732+
$this->setField('Code', $code);
733+
}
729734
}

tests/php/Security/GroupCsvBulkLoaderTest.php

+18-15
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ public function testNewImport()
2424

2525
public function testOverwriteExistingImport()
2626
{
27+
// This group will be overwritten.
2728
$existinggroup = new Group();
2829
$existinggroup->Title = 'Old Group Title';
2930
$existinggroup->Code = 'newgroup1';
@@ -33,13 +34,15 @@ public function testOverwriteExistingImport()
3334
$results = $loader->load(__DIR__ . '/GroupCsvBulkLoaderTest/GroupCsvBulkLoaderTest.csv');
3435

3536
$created = $results->Created()->toArray();
36-
$this->assertEquals(count($created), 1);
37-
$this->assertEquals($created[0]->Code, 'newchildgroup1');
37+
$this->assertEquals(1, count($created));
38+
$this->assertEquals('newchildgroup1', $created[0]->Code);
39+
$this->assertEquals('New Child Group 1', $created[0]->Title);
3840

41+
// This overrides the group because the code matches, which takes precedence over the ID.
3942
$updated = $results->Updated()->toArray();
40-
$this->assertEquals(count($updated), 1);
41-
$this->assertEquals($updated[0]->Code, 'newgroup1-2');
42-
$this->assertEquals($updated[0]->Title, 'New Group 1');
43+
$this->assertEquals(1, count($updated));
44+
$this->assertEquals('newgroup1', $updated[0]->Code);
45+
$this->assertEquals('New Group 1', $updated[0]->Title);
4346
}
4447

4548
public function testImportPermissions()
@@ -48,17 +51,17 @@ public function testImportPermissions()
4851
$results = $loader->load(__DIR__ . '/GroupCsvBulkLoaderTest/GroupCsvBulkLoaderTest_withExisting.csv');
4952

5053
$created = $results->Created()->toArray();
51-
$this->assertEquals(count($created), 1);
52-
$this->assertEquals($created[0]->Code, 'newgroup1');
53-
$this->assertEquals($created[0]->Permissions()->column('Code'), ['CODE1']);
54+
$this->assertEquals(1, count($created));
55+
$this->assertEquals('newgroup1', $created[0]->Code);
56+
$this->assertEquals(['CODE1'], $created[0]->Permissions()->column('Code'));
5457

5558
$updated = $results->Updated()->toArray();
56-
$this->assertEquals(count($updated), 1);
57-
$this->assertEquals($updated[0]->Code, 'existinggroup');
58-
$array1=$updated[0]->Permissions()->column('Code');
59-
$array2=['CODE1', 'CODE2'];
60-
sort($array1);
61-
sort($array2);
62-
$this->assertEquals($array1, $array2);
59+
$this->assertEquals(1, count($updated));
60+
$this->assertEquals('existinggroup', $updated[0]->Code);
61+
$actual = $updated[0]->Permissions()->column('Code');
62+
$expected = ['CODE1', 'CODE2'];
63+
sort($actual);
64+
sort($expected);
65+
$this->assertEquals($expected, $actual);
6366
}
6467
}

tests/php/Security/GroupTest.php

+33-1
Original file line numberDiff line numberDiff line change
@@ -334,8 +334,40 @@ public function testGroupTitleDuplication()
334334
$this->assertEquals('duplicate-2', $group->Code);
335335

336336
$group = new Group();
337-
$group->Title = 'Duplicate';
337+
$group->Title = 'Any Title';
338+
$group->Code = 'duplicate';
338339
$group->write();
339340
$this->assertEquals('duplicate-3', $group->Code);
341+
342+
$group1 = new Group();
343+
$group1->Title = 'Any Title1';
344+
$group1->Code = 'some-code';
345+
$group2 = new Group();
346+
$group2->Title = 'Any Title2';
347+
$group2->Code = 'some-code';
348+
$group1->write();
349+
$group2->write();
350+
$this->assertEquals('some-code', $group1->Code);
351+
$this->assertEquals('some-code-2', $group2->Code);
352+
}
353+
354+
public function testSettingCodeRepeatedly()
355+
{
356+
// Setting the code to the code it already was doesn't modify it
357+
$group = $this->objFromFixture(Group::class, 'group1');
358+
$previousCode = $group->Code;
359+
$group->Code = $previousCode;
360+
$group->write();
361+
$this->assertEquals($previousCode, $group->Code);
362+
363+
// Setting the code to a new code does modify it
364+
$group->Code = 'new-code';
365+
$group->write();
366+
$this->assertEquals('new-code', $group->Code);
367+
368+
// The old code can be reused
369+
$group->Code = $previousCode;
370+
$group->write();
371+
$this->assertEquals($previousCode, $group->Code);
340372
}
341373
}

0 commit comments

Comments
 (0)