diff --git a/src/Integrations/Divi/Design/DiviPresetsSetAbility.php b/src/Integrations/Divi/Design/DiviPresetsSetAbility.php index b84b034..cb8026f 100644 --- a/src/Integrations/Divi/Design/DiviPresetsSetAbility.php +++ b/src/Integrations/Divi/Design/DiviPresetsSetAbility.php @@ -236,6 +236,17 @@ final class DiviPresetsSetAbility implements Ability return null; } + if ($existing === null && isset($item['rename'])) { + $errors[$field . '.rename'] = 'nur zusammen mit preset; für ein neues Preset name verwenden'; + + return null; + } + if ($existing !== null && isset($item['name'])) { + $errors[$field . '.name'] = 'zum Umbenennen rename verwenden'; + + return null; + } + foreach (['name' => $existing === null, 'rename' => $existing !== null] as $key => $applies) { if (! $applies || ! is_string($item[$key] ?? null)) { continue; @@ -269,10 +280,12 @@ final class DiviPresetsSetAbility implements Ability /** Plain text of 1 to 100 characters, or null (ruling: preset names). */ private function cleanName(string $name): ?string { + if (strlen($name) > self::NAME_MAX * 4) { + return null; + } $clean = sanitize_text_field($name); - $length = function_exists('mb_strlen') ? mb_strlen($clean) : strlen($clean); - return $clean === '' || $length > self::NAME_MAX || strlen($name) > self::NAME_MAX * 4 ? null : $clean; + return $clean === '' || mb_strlen($clean) > self::NAME_MAX ? null : $clean; } /** diff --git a/tests/Unit/Integrations/Divi/Design/DiviPresetsSetAbilityTest.php b/tests/Unit/Integrations/Divi/Design/DiviPresetsSetAbilityTest.php index d78fa57..a0b6e0c 100644 --- a/tests/Unit/Integrations/Divi/Design/DiviPresetsSetAbilityTest.php +++ b/tests/Unit/Integrations/Divi/Design/DiviPresetsSetAbilityTest.php @@ -192,6 +192,29 @@ final class DiviPresetsSetAbilityTest extends TestCase self::assertStringContainsString('1–100 Zeichen', $empty['fields']['items[0].rename']); } + public function testNameAndRenameAreExclusive(): void + { + $ability = $this->ability(); + $new = self::assertToolError($ability->execute(['items' => [ + ['module' => 'button', 'name' => 'Neu', 'rename' => 'x'], + ]]), 'validation_failed'); + self::assertStringContainsString('nur zusammen mit preset', $new['fields']['items[0].rename']); + + $change = self::assertToolError($ability->execute(['items' => [ + ['module' => 'button', 'preset' => 'CTA primär', 'name' => 'CTA primär'], + ]]), 'validation_failed'); + self::assertStringContainsString('rename', $change['fields']['items[0].name']); + } + + public function testRenameToAnotherPresetsNameIsRefused(): void + { + $result = self::assertToolError($this->ability()->execute(['items' => [ + ['module' => 'button', 'preset' => 'CTA primär', 'rename' => 'Doppelt'], + ]]), 'validation_failed'); + + self::assertStringContainsString('bbbbbbbbbb', $result['fields']['items[0].rename']); + } + public function testNothingIsWrittenWhenOneItemHasErrors(): void { $writer = Mockery::mock(DesignSystemWriter::class); @@ -202,7 +225,8 @@ final class DiviPresetsSetAbilityTest extends TestCase $ability = $this->ability(true, null, null, $writer); $result = $ability->execute(['items' => [ - ['module' => 'button', 'name' => 'Gut'], + ['module' => 'button', 'name' => 'Gut', + 'attrs' => ['button.decoration.background' => ['desktop' => ['color' => '#333333']]]], ['module' => 'button', 'name' => 'Schlecht', 'attrs' => ['button.innerContent' => ['desktop' => ['text' => 'Hallo']]]], ], 'confirm' => true, 'design_rev' => 'egal']);