Skip to content

Commit 920751a

Browse files
committed
Create the TriggerName value object
Signed-off-by: Maurício Meneghini Fauth <mauricio@fauth.dev>
1 parent 3949e5b commit 920751a

File tree

6 files changed

+172
-3
lines changed

6 files changed

+172
-3
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpMyAdmin\Triggers;
6+
7+
use PhpMyAdmin\Dbal\InvalidIdentifierName;
8+
9+
use function __;
10+
use function sprintf;
11+
12+
final class InvalidTriggerName extends InvalidIdentifierName
13+
{
14+
public static function fromEmptyName(): self
15+
{
16+
return new self(__('The trigger name must not be empty.'));
17+
}
18+
19+
/** @psalm-param positive-int $length */
20+
public static function fromLongName(int $length): self
21+
{
22+
return new self(sprintf(__('The trigger name cannot be longer than %d characters.'), $length));
23+
}
24+
25+
public static function fromNameWithTrailingSpace(): self
26+
{
27+
return new self(__('The trigger name cannot end with a space character.'));
28+
}
29+
}

libraries/classes/Triggers/Trigger.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
final class Trigger
1212
{
1313
public function __construct(
14-
public readonly string $name,
14+
public readonly TriggerName $name,
1515
public readonly Timing $timing,
1616
public readonly Event $event,
1717
public readonly TableName $table,
@@ -31,6 +31,8 @@ public static function tryFromArray(array $trigger): self|null
3131
$statement = $trigger['Statement'] ?? $trigger['ACTION_STATEMENT'] ?? null;
3232
$definer = $trigger['Definer'] ?? $trigger['DEFINER'] ?? null;
3333
Assert::string($name);
34+
$name = TriggerName::tryFromValue($name);
35+
Assert::notNull($name);
3436
Assert::string($timing);
3537
$timing = Timing::tryFrom($timing);
3638
Assert::notNull($timing);
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpMyAdmin\Triggers;
6+
7+
use Stringable;
8+
use Webmozart\Assert\Assert;
9+
use Webmozart\Assert\InvalidArgumentException;
10+
11+
final class TriggerName implements Stringable
12+
{
13+
/**
14+
* @see https://dev.mysql.com/doc/refman/en/identifier-length.html
15+
* @see https://mariadb.com/kb/en/identifier-names/#maximum-length
16+
*/
17+
private const MAX_LENGTH = 64;
18+
19+
/** @psalm-var non-empty-string */
20+
private string $name;
21+
22+
/** @throws InvalidTriggerName */
23+
private function __construct(mixed $name)
24+
{
25+
try {
26+
Assert::stringNotEmpty($name);
27+
} catch (InvalidArgumentException) {
28+
throw InvalidTriggerName::fromEmptyName();
29+
}
30+
31+
try {
32+
Assert::maxLength($name, self::MAX_LENGTH);
33+
} catch (InvalidArgumentException) {
34+
throw InvalidTriggerName::fromLongName(self::MAX_LENGTH);
35+
}
36+
37+
try {
38+
Assert::notEndsWith($name, ' ');
39+
} catch (InvalidArgumentException) {
40+
throw InvalidTriggerName::fromNameWithTrailingSpace();
41+
}
42+
43+
$this->name = $name;
44+
}
45+
46+
/** @throws InvalidTriggerName */
47+
public static function fromValue(mixed $name): self
48+
{
49+
return new self($name);
50+
}
51+
52+
public static function tryFromValue(mixed $name): self|null
53+
{
54+
try {
55+
return new self($name);
56+
} catch (InvalidTriggerName) {
57+
return null;
58+
}
59+
}
60+
61+
/** @psalm-return non-empty-string */
62+
public function getName(): string
63+
{
64+
return $this->name;
65+
}
66+
67+
/** @psalm-return non-empty-string */
68+
public function __toString(): string
69+
{
70+
return $this->name;
71+
}
72+
}

libraries/classes/Triggers/Triggers.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -521,7 +521,7 @@ public static function getDetails(
521521
}
522522

523523
$oneResult = [];
524-
$oneResult['name'] = $newTrigger->name;
524+
$oneResult['name'] = $newTrigger->name->getName();
525525
$oneResult['table'] = $newTrigger->table->getName();
526526
$oneResult['action_timing'] = $newTrigger->timing->value;
527527
$oneResult['event_manipulation'] = $newTrigger->event->value;
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpMyAdmin\Tests\Triggers;
6+
7+
use PhpMyAdmin\Triggers\InvalidTriggerName;
8+
use PhpMyAdmin\Triggers\TriggerName;
9+
use PHPUnit\Framework\TestCase;
10+
11+
use function str_repeat;
12+
13+
/**
14+
* @covers \PhpMyAdmin\Triggers\InvalidTriggerName
15+
* @covers \PhpMyAdmin\Triggers\TriggerName
16+
*/
17+
final class TriggerNameTest extends TestCase
18+
{
19+
/** @dataProvider providerForTestValidNames */
20+
public function testValidName(string $validName): void
21+
{
22+
$name = TriggerName::fromValue($validName);
23+
$this->assertEquals($validName, $name->getName());
24+
$this->assertEquals($validName, (string) $name);
25+
}
26+
27+
/** @dataProvider providerForTestValidNames */
28+
public function testTryFromValueValidName(string $validName): void
29+
{
30+
$name = TriggerName::tryFromValue($validName);
31+
$this->assertNotNull($name);
32+
$this->assertEquals($validName, $name->getName());
33+
$this->assertEquals($validName, (string) $name);
34+
}
35+
36+
/** @return iterable<int, string[]> */
37+
public static function providerForTestValidNames(): iterable
38+
{
39+
yield ['name'];
40+
yield ['0'];
41+
yield [str_repeat('a', 64)];
42+
}
43+
44+
/** @dataProvider providerForTestInvalidNames */
45+
public function testInvalidNames(mixed $name, string $exceptionMessage): void
46+
{
47+
$this->assertNull(TriggerName::tryFromValue($name));
48+
$this->expectException(InvalidTriggerName::class);
49+
$this->expectExceptionMessage($exceptionMessage);
50+
TriggerName::fromValue($name);
51+
}
52+
53+
/**
54+
* @return iterable<string, mixed[]>
55+
* @psalm-return iterable<string, array{mixed, non-empty-string}>
56+
*/
57+
public static function providerForTestInvalidNames(): iterable
58+
{
59+
yield 'null' => [null, 'The trigger name must not be empty.'];
60+
yield 'integer' => [1, 'The trigger name must not be empty.'];
61+
yield 'array' => [['trigger_name'], 'The trigger name must not be empty.'];
62+
yield 'empty string' => ['', 'The trigger name must not be empty.'];
63+
yield 'too long name' => [str_repeat('a', 65), 'The trigger name cannot be longer than 64 characters.'];
64+
yield 'trailing space' => ['a ', 'The trigger name cannot end with a space character.'];
65+
}
66+
}

test/classes/Triggers/TriggerTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public function testTryFromArrayWithValidValues(array $trigger): void
2626
{
2727
$actual = Trigger::tryFromArray($trigger);
2828
$this->assertNotNull($actual);
29-
$this->assertSame('trigger_name', $actual->name);
29+
$this->assertSame('trigger_name', $actual->name->getName());
3030
$this->assertSame(Timing::Before, $actual->timing);
3131
$this->assertSame(Event::Update, $actual->event);
3232
$this->assertSame('test_table', $actual->table->getName());

0 commit comments

Comments
 (0)