Merge pull request #17448 from mauriciofauth/identifier-name-exceptions

Add exceptions for invalid identifier names
This commit is contained in:
Maurício Meneghini Fauth 2022-03-19 18:00:26 -03:00 committed by GitHub
commit f09b7d8601
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 206 additions and 117 deletions

View File

@ -6,14 +6,14 @@ namespace PhpMyAdmin;
use PhpMyAdmin\ConfigStorage\Relation;
use PhpMyAdmin\Dbal\DatabaseName;
use PhpMyAdmin\Dbal\InvalidDatabaseName;
use PhpMyAdmin\Dbal\InvalidTableName;
use PhpMyAdmin\Dbal\TableName;
use PhpMyAdmin\Http\Factory\ServerRequestFactory;
use PhpMyAdmin\Http\ServerRequest;
use PhpMyAdmin\Plugins\AuthenticationPlugin;
use PhpMyAdmin\SqlParser\Lexer;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Webmozart\Assert\Assert;
use Webmozart\Assert\InvalidArgumentException;
use function __;
use function array_pop;
@ -517,14 +517,13 @@ final class Common
try {
$GLOBALS['db'] = DatabaseName::fromValue($request->getParam('db'))->getName();
} catch (InvalidArgumentException $exception) {
} catch (InvalidDatabaseName $exception) {
$GLOBALS['db'] = '';
}
try {
Assert::stringNotEmpty($GLOBALS['db']);
$GLOBALS['table'] = TableName::fromValue($request->getParam('table'))->getName();
} catch (InvalidArgumentException $exception) {
} catch (InvalidTableName $exception) {
$GLOBALS['table'] = '';
}

View File

@ -23,10 +23,10 @@ use PhpMyAdmin\ConfigStorage\Features\TrackingFeature;
use PhpMyAdmin\ConfigStorage\Features\UiPreferencesFeature;
use PhpMyAdmin\ConfigStorage\Features\UserPreferencesFeature;
use PhpMyAdmin\Dbal\DatabaseName;
use PhpMyAdmin\Dbal\InvalidDatabaseName;
use PhpMyAdmin\Dbal\InvalidTableName;
use PhpMyAdmin\Dbal\TableName;
use PhpMyAdmin\Version;
use Webmozart\Assert\Assert;
use Webmozart\Assert\InvalidArgumentException;
use function is_string;
@ -138,9 +138,8 @@ final class RelationParameters
}
try {
Assert::keyExists($params, 'db');
$db = DatabaseName::fromValue($params['db']);
} catch (InvalidArgumentException $exception) {
$db = DatabaseName::fromValue($params['db'] ?? null);
} catch (InvalidDatabaseName $exception) {
return new self($user, null);
}
@ -465,7 +464,7 @@ final class RelationParameters
{
try {
return TableName::fromValue($tableName);
} catch (InvalidArgumentException $exception) {
} catch (InvalidTableName $exception) {
return null;
}
}

View File

@ -6,6 +6,7 @@ namespace PhpMyAdmin\Controllers\Table;
use PhpMyAdmin\Controllers\AbstractController;
use PhpMyAdmin\Dbal\DatabaseName;
use PhpMyAdmin\Dbal\InvalidIdentifierName;
use PhpMyAdmin\Dbal\TableName;
use PhpMyAdmin\DbTableExists;
use PhpMyAdmin\Http\ServerRequest;
@ -18,20 +19,17 @@ final class DropColumnConfirmationController extends AbstractController
{
public function __invoke(ServerRequest $request): void
{
$fields = $request->getParsedBodyParam('selected_fld');
try {
$db = DatabaseName::fromValue($request->getParsedBodyParam('db'));
$table = TableName::fromValue($request->getParsedBodyParam('table'));
} catch (InvalidArgumentException $exception) {
Assert::allStringNotEmpty($fields);
} catch (InvalidIdentifierName $exception) {
$this->response->setHttpResponseCode(400);
$this->response->setRequestStatus(false);
$this->response->addJSON('message', __('Table not found.'));
$this->response->addJSON('message', $exception->getMessage());
return;
}
$fields = $request->getParsedBodyParam('selected_fld');
try {
Assert::allStringNotEmpty($fields);
} catch (InvalidArgumentException $exception) {
$this->response->setHttpResponseCode(400);
$this->response->setRequestStatus(false);

View File

@ -7,6 +7,7 @@ namespace PhpMyAdmin\Controllers\Table\Maintenance;
use PhpMyAdmin\Config;
use PhpMyAdmin\Controllers\AbstractController;
use PhpMyAdmin\Dbal\DatabaseName;
use PhpMyAdmin\Dbal\InvalidIdentifierName;
use PhpMyAdmin\Dbal\TableName;
use PhpMyAdmin\Html\Generator;
use PhpMyAdmin\Http\ServerRequest;
@ -60,7 +61,7 @@ final class AnalyzeController extends AbstractController
foreach ($selectedTablesParam as $table) {
$selectedTables[] = TableName::fromValue($table);
}
} catch (InvalidArgumentException $exception) {
} catch (InvalidIdentifierName $exception) {
$message = Message::error($exception->getMessage());
$this->response->setRequestStatus(false);
$this->response->addJSON('message', $message->getDisplay());

View File

@ -7,6 +7,7 @@ namespace PhpMyAdmin\Controllers\Table\Maintenance;
use PhpMyAdmin\Config;
use PhpMyAdmin\Controllers\AbstractController;
use PhpMyAdmin\Dbal\DatabaseName;
use PhpMyAdmin\Dbal\InvalidIdentifierName;
use PhpMyAdmin\Dbal\TableName;
use PhpMyAdmin\Html\Generator;
use PhpMyAdmin\Http\ServerRequest;
@ -60,7 +61,7 @@ final class CheckController extends AbstractController
foreach ($selectedTablesParam as $table) {
$selectedTables[] = TableName::fromValue($table);
}
} catch (InvalidArgumentException $exception) {
} catch (InvalidIdentifierName $exception) {
$message = Message::error($exception->getMessage());
$this->response->setRequestStatus(false);
$this->response->addJSON('message', $message->getDisplay());

View File

@ -7,6 +7,7 @@ namespace PhpMyAdmin\Controllers\Table\Maintenance;
use PhpMyAdmin\Config;
use PhpMyAdmin\Controllers\AbstractController;
use PhpMyAdmin\Dbal\DatabaseName;
use PhpMyAdmin\Dbal\InvalidIdentifierName;
use PhpMyAdmin\Dbal\TableName;
use PhpMyAdmin\Html\Generator;
use PhpMyAdmin\Http\ServerRequest;
@ -60,7 +61,7 @@ final class ChecksumController extends AbstractController
foreach ($selectedTablesParam as $table) {
$selectedTables[] = TableName::fromValue($table);
}
} catch (InvalidArgumentException $exception) {
} catch (InvalidIdentifierName $exception) {
$message = Message::error($exception->getMessage());
$this->response->setRequestStatus(false);
$this->response->addJSON('message', $message->getDisplay());

View File

@ -7,6 +7,7 @@ namespace PhpMyAdmin\Controllers\Table\Maintenance;
use PhpMyAdmin\Config;
use PhpMyAdmin\Controllers\AbstractController;
use PhpMyAdmin\Dbal\DatabaseName;
use PhpMyAdmin\Dbal\InvalidIdentifierName;
use PhpMyAdmin\Dbal\TableName;
use PhpMyAdmin\Html\Generator;
use PhpMyAdmin\Http\ServerRequest;
@ -60,7 +61,7 @@ final class OptimizeController extends AbstractController
foreach ($selectedTablesParam as $table) {
$selectedTables[] = TableName::fromValue($table);
}
} catch (InvalidArgumentException $exception) {
} catch (InvalidIdentifierName $exception) {
$message = Message::error($exception->getMessage());
$this->response->setRequestStatus(false);
$this->response->addJSON('message', $message->getDisplay());

View File

@ -7,6 +7,7 @@ namespace PhpMyAdmin\Controllers\Table\Maintenance;
use PhpMyAdmin\Config;
use PhpMyAdmin\Controllers\AbstractController;
use PhpMyAdmin\Dbal\DatabaseName;
use PhpMyAdmin\Dbal\InvalidIdentifierName;
use PhpMyAdmin\Dbal\TableName;
use PhpMyAdmin\Html\Generator;
use PhpMyAdmin\Http\ServerRequest;
@ -60,7 +61,7 @@ final class RepairController extends AbstractController
foreach ($selectedTablesParam as $table) {
$selectedTables[] = TableName::fromValue($table);
}
} catch (InvalidArgumentException $exception) {
} catch (InvalidIdentifierName $exception) {
$message = Message::error($exception->getMessage());
$this->response->setRequestStatus(false);
$this->response->addJSON('message', $message->getDisplay());

View File

@ -6,6 +6,7 @@ namespace PhpMyAdmin\Controllers\Table\Partition;
use PhpMyAdmin\Controllers\AbstractController;
use PhpMyAdmin\Dbal\DatabaseName;
use PhpMyAdmin\Dbal\InvalidIdentifierName;
use PhpMyAdmin\Dbal\TableName;
use PhpMyAdmin\Html\Generator;
use PhpMyAdmin\Http\ServerRequest;
@ -40,7 +41,7 @@ final class AnalyzeController extends AbstractController
Assert::stringNotEmpty($partitionName);
$database = DatabaseName::fromValue($request->getParam('db'));
$table = TableName::fromValue($request->getParam('table'));
} catch (InvalidArgumentException $exception) {
} catch (InvalidIdentifierName | InvalidArgumentException $exception) {
$message = Message::error($exception->getMessage());
$this->response->addHTML($message->getDisplay());

View File

@ -6,6 +6,7 @@ namespace PhpMyAdmin\Controllers\Table\Partition;
use PhpMyAdmin\Controllers\AbstractController;
use PhpMyAdmin\Dbal\DatabaseName;
use PhpMyAdmin\Dbal\InvalidIdentifierName;
use PhpMyAdmin\Dbal\TableName;
use PhpMyAdmin\Html\Generator;
use PhpMyAdmin\Http\ServerRequest;
@ -40,7 +41,7 @@ final class CheckController extends AbstractController
Assert::stringNotEmpty($partitionName);
$database = DatabaseName::fromValue($request->getParam('db'));
$table = TableName::fromValue($request->getParam('table'));
} catch (InvalidArgumentException $exception) {
} catch (InvalidIdentifierName | InvalidArgumentException $exception) {
$message = Message::error($exception->getMessage());
$this->response->addHTML($message->getDisplay());

View File

@ -6,6 +6,7 @@ namespace PhpMyAdmin\Controllers\Table\Partition;
use PhpMyAdmin\Controllers\AbstractController;
use PhpMyAdmin\Dbal\DatabaseName;
use PhpMyAdmin\Dbal\InvalidIdentifierName;
use PhpMyAdmin\Dbal\TableName;
use PhpMyAdmin\Html\Generator;
use PhpMyAdmin\Http\ServerRequest;
@ -40,7 +41,7 @@ final class DropController extends AbstractController
Assert::stringNotEmpty($partitionName);
$database = DatabaseName::fromValue($request->getParam('db'));
$table = TableName::fromValue($request->getParam('table'));
} catch (InvalidArgumentException $exception) {
} catch (InvalidIdentifierName | InvalidArgumentException $exception) {
$message = Message::error($exception->getMessage());
$this->response->addHTML($message->getDisplay());

View File

@ -6,6 +6,7 @@ namespace PhpMyAdmin\Controllers\Table\Partition;
use PhpMyAdmin\Controllers\AbstractController;
use PhpMyAdmin\Dbal\DatabaseName;
use PhpMyAdmin\Dbal\InvalidIdentifierName;
use PhpMyAdmin\Dbal\TableName;
use PhpMyAdmin\Html\Generator;
use PhpMyAdmin\Http\ServerRequest;
@ -40,7 +41,7 @@ final class OptimizeController extends AbstractController
Assert::stringNotEmpty($partitionName);
$database = DatabaseName::fromValue($request->getParam('db'));
$table = TableName::fromValue($request->getParam('table'));
} catch (InvalidArgumentException $exception) {
} catch (InvalidIdentifierName | InvalidArgumentException $exception) {
$message = Message::error($exception->getMessage());
$this->response->addHTML($message->getDisplay());

View File

@ -6,6 +6,7 @@ namespace PhpMyAdmin\Controllers\Table\Partition;
use PhpMyAdmin\Controllers\AbstractController;
use PhpMyAdmin\Dbal\DatabaseName;
use PhpMyAdmin\Dbal\InvalidIdentifierName;
use PhpMyAdmin\Dbal\TableName;
use PhpMyAdmin\Html\Generator;
use PhpMyAdmin\Http\ServerRequest;
@ -40,7 +41,7 @@ final class RebuildController extends AbstractController
Assert::stringNotEmpty($partitionName);
$database = DatabaseName::fromValue($request->getParam('db'));
$table = TableName::fromValue($request->getParam('table'));
} catch (InvalidArgumentException $exception) {
} catch (InvalidIdentifierName | InvalidArgumentException $exception) {
$message = Message::error($exception->getMessage());
$this->response->addHTML($message->getDisplay());

View File

@ -6,6 +6,7 @@ namespace PhpMyAdmin\Controllers\Table\Partition;
use PhpMyAdmin\Controllers\AbstractController;
use PhpMyAdmin\Dbal\DatabaseName;
use PhpMyAdmin\Dbal\InvalidIdentifierName;
use PhpMyAdmin\Dbal\TableName;
use PhpMyAdmin\Html\Generator;
use PhpMyAdmin\Http\ServerRequest;
@ -40,7 +41,7 @@ final class RepairController extends AbstractController
Assert::stringNotEmpty($partitionName);
$database = DatabaseName::fromValue($request->getParam('db'));
$table = TableName::fromValue($request->getParam('table'));
} catch (InvalidArgumentException $exception) {
} catch (InvalidIdentifierName | InvalidArgumentException $exception) {
$message = Message::error($exception->getMessage());
$this->response->addHTML($message->getDisplay());

View File

@ -6,6 +6,7 @@ namespace PhpMyAdmin\Controllers\Table\Partition;
use PhpMyAdmin\Controllers\AbstractController;
use PhpMyAdmin\Dbal\DatabaseName;
use PhpMyAdmin\Dbal\InvalidIdentifierName;
use PhpMyAdmin\Dbal\TableName;
use PhpMyAdmin\Html\Generator;
use PhpMyAdmin\Http\ServerRequest;
@ -40,7 +41,7 @@ final class TruncateController extends AbstractController
Assert::stringNotEmpty($partitionName);
$database = DatabaseName::fromValue($request->getParam('db'));
$table = TableName::fromValue($request->getParam('table'));
} catch (InvalidArgumentException $exception) {
} catch (InvalidIdentifierName | InvalidArgumentException $exception) {
$message = Message::error($exception->getMessage());
$this->response->addHTML($message->getDisplay());

View File

@ -9,6 +9,7 @@ use PhpMyAdmin\Controllers\AbstractController;
use PhpMyAdmin\Core;
use PhpMyAdmin\DatabaseInterface;
use PhpMyAdmin\Dbal\DatabaseName;
use PhpMyAdmin\Dbal\InvalidIdentifierName;
use PhpMyAdmin\Dbal\TableName;
use PhpMyAdmin\DbTableExists;
use PhpMyAdmin\Http\ServerRequest;
@ -17,7 +18,6 @@ use PhpMyAdmin\ResponseRenderer;
use PhpMyAdmin\Template;
use PhpMyAdmin\Transformations;
use PhpMyAdmin\Util;
use Webmozart\Assert\InvalidArgumentException;
use function __;
use function htmlspecialchars;
@ -65,7 +65,7 @@ class WrapperController extends AbstractController
try {
$db = DatabaseName::fromValue($request->getParam('db'));
$table = TableName::fromValue($request->getParam('table'));
} catch (InvalidArgumentException $exception) {
} catch (InvalidIdentifierName $exception) {
return;
}

View File

@ -28,20 +28,35 @@ final class DatabaseName implements Stringable
/**
* @param mixed $name
*
* @throws InvalidArgumentException
* @throws InvalidDatabaseName
*/
private function __construct($name)
{
Assert::stringNotEmpty($name);
Assert::maxLength($name, self::MAX_LENGTH);
Assert::notEndsWith($name, ' ');
try {
Assert::stringNotEmpty($name);
} catch (InvalidArgumentException $exception) {
throw InvalidDatabaseName::fromEmptyName();
}
try {
Assert::maxLength($name, self::MAX_LENGTH);
} catch (InvalidArgumentException $exception) {
throw InvalidDatabaseName::fromLongName(self::MAX_LENGTH);
}
try {
Assert::notEndsWith($name, ' ');
} catch (InvalidArgumentException $exception) {
throw InvalidDatabaseName::fromNameWithTrailingSpace();
}
$this->name = $name;
}
/**
* @param mixed $name
*
* @throws InvalidArgumentException
* @throws InvalidDatabaseName
*/
public static function fromValue($name): self
{

View File

@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
namespace PhpMyAdmin\Dbal;
use function __;
use function sprintf;
class InvalidDatabaseName extends InvalidIdentifierName
{
public static function fromEmptyName(): self
{
return new self(__('The database name must be a non-empty string.'));
}
/**
* @psalm-param positive-int $length
*/
public static function fromLongName(int $length): self
{
return new self(sprintf(__('The database name cannot be longer than %d characters.'), $length));
}
public static function fromNameWithTrailingSpace(): self
{
return new self(__('The database name cannot end with a space character.'));
}
}

View File

@ -0,0 +1,11 @@
<?php
declare(strict_types=1);
namespace PhpMyAdmin\Dbal;
use InvalidArgumentException;
class InvalidIdentifierName extends InvalidArgumentException
{
}

View File

@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
namespace PhpMyAdmin\Dbal;
use function __;
use function sprintf;
class InvalidTableName extends InvalidIdentifierName
{
public static function fromEmptyName(): self
{
return new self(__('The table name must be a non-empty string.'));
}
/**
* @psalm-param positive-int $length
*/
public static function fromLongName(int $length): self
{
return new self(sprintf(__('The table name cannot be longer than %d characters.'), $length));
}
public static function fromNameWithTrailingSpace(): self
{
return new self(__('The table name cannot end with a space character.'));
}
}

View File

@ -28,20 +28,35 @@ final class TableName implements Stringable
/**
* @param mixed $name
*
* @throws InvalidArgumentException
* @throws InvalidTableName
*/
private function __construct($name)
{
Assert::stringNotEmpty($name);
Assert::maxLength($name, self::MAX_LENGTH);
Assert::notEndsWith($name, ' ');
try {
Assert::stringNotEmpty($name);
} catch (InvalidArgumentException $exception) {
throw InvalidTableName::fromEmptyName();
}
try {
Assert::maxLength($name, self::MAX_LENGTH);
} catch (InvalidArgumentException $exception) {
throw InvalidTableName::fromLongName(self::MAX_LENGTH);
}
try {
Assert::notEndsWith($name, ' ');
} catch (InvalidArgumentException $exception) {
throw InvalidTableName::fromNameWithTrailingSpace();
}
$this->name = $name;
}
/**
* @param mixed $name
*
* @throws InvalidArgumentException
* @throws InvalidTableName
*/
public static function fromValue($name): self
{

View File

@ -75,7 +75,7 @@ class DropColumnConfirmationControllerTest extends AbstractTestCase
$this->assertSame(400, $response->getHttpResponseCode());
$this->assertFalse($response->hasSuccessState());
$this->assertSame(['message' => 'Table not found.'], $response->getJSONResult());
$this->assertSame(['message' => 'The database name must be a non-empty string.'], $response->getJSONResult());
$this->assertSame('', $response->getHTMLResult());
}
}

View File

@ -5,69 +5,60 @@ declare(strict_types=1);
namespace PhpMyAdmin\Tests\Dbal;
use PhpMyAdmin\Dbal\DatabaseName;
use PhpMyAdmin\Dbal\InvalidDatabaseName;
use PHPUnit\Framework\TestCase;
use Webmozart\Assert\InvalidArgumentException;
use function str_repeat;
/**
* @covers \PhpMyAdmin\Dbal\DatabaseName
* @covers \PhpMyAdmin\Dbal\InvalidDatabaseName
*/
class DatabaseNameTest extends TestCase
{
public function testEmptyName(): void
/**
* @dataProvider providerForTestValidNames
*/
public function testValidName(string $validName): void
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Expected a different value than "".');
DatabaseName::fromValue('');
$name = DatabaseName::fromValue($validName);
$this->assertEquals($validName, $name->getName());
$this->assertEquals($validName, (string) $name);
}
public function testNameWithTrailingWhitespace(): void
/**
* @return iterable<int, string[]>
*/
public function providerForTestValidNames(): iterable
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Expected a value not to end with " ". Got: "a "');
DatabaseName::fromValue('a ');
}
public function testLongName(): void
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage(
'Expected a value to contain at most 64 characters. Got: '
. '"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"'
);
DatabaseName::fromValue(str_repeat('a', 65));
}
public function testValidName(): void
{
$name = DatabaseName::fromValue('name');
$this->assertEquals('name', $name->getName());
$this->assertEquals('name', (string) $name);
yield ['name'];
yield ['0'];
yield [str_repeat('a', 64)];
}
/**
* @param mixed $name
*
* @dataProvider providerForTestInvalidMixedNames
* @dataProvider providerForTestInvalidNames
*/
public function testInvalidMixedNames($name, string $exceptionMessage): void
public function testInvalidNames($name, string $exceptionMessage): void
{
$this->expectException(InvalidArgumentException::class);
$this->expectException(InvalidDatabaseName::class);
$this->expectExceptionMessage($exceptionMessage);
DatabaseName::fromValue($name);
}
/**
* @return mixed[][]
* @psalm-return non-empty-list<array{mixed, string}>
* @return iterable<string, mixed[]>
* @psalm-return iterable<string, array{mixed, non-empty-string}>
*/
public function providerForTestInvalidMixedNames(): array
public function providerForTestInvalidNames(): iterable
{
return [
[null, 'Expected a string. Got: NULL'],
[1, 'Expected a string. Got: integer'],
[['db'], 'Expected a string. Got: array'],
];
yield 'null' => [null, 'The database name must be a non-empty string.'];
yield 'integer' => [1, 'The database name must be a non-empty string.'];
yield 'array' => [['database'], 'The database name must be a non-empty string.'];
yield 'empty string' => ['', 'The database name must be a non-empty string.'];
yield 'too long name' => [str_repeat('a', 65), 'The database name cannot be longer than 64 characters.'];
yield 'trailing space' => ['a ', 'The database name cannot end with a space character.'];
}
}

View File

@ -4,70 +4,61 @@ declare(strict_types=1);
namespace PhpMyAdmin\Tests\Dbal;
use PhpMyAdmin\Dbal\InvalidTableName;
use PhpMyAdmin\Dbal\TableName;
use PHPUnit\Framework\TestCase;
use Webmozart\Assert\InvalidArgumentException;
use function str_repeat;
/**
* @covers \PhpMyAdmin\Dbal\TableName
* @covers \PhpMyAdmin\Dbal\InvalidTableName
*/
class TableNameTest extends TestCase
{
public function testEmptyName(): void
/**
* @dataProvider providerForTestValidNames
*/
public function testValidName(string $validName): void
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Expected a different value than "".');
TableName::fromValue('');
$name = TableName::fromValue($validName);
$this->assertEquals($validName, $name->getName());
$this->assertEquals($validName, (string) $name);
}
public function testNameWithTrailingWhitespace(): void
/**
* @return iterable<int, string[]>
*/
public function providerForTestValidNames(): iterable
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Expected a value not to end with " ". Got: "a "');
TableName::fromValue('a ');
}
public function testLongName(): void
{
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage(
'Expected a value to contain at most 64 characters. Got: '
. '"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"'
);
TableName::fromValue(str_repeat('a', 65));
}
public function testValidName(): void
{
$name = TableName::fromValue('name');
$this->assertEquals('name', $name->getName());
$this->assertEquals('name', (string) $name);
yield ['name'];
yield ['0'];
yield [str_repeat('a', 64)];
}
/**
* @param mixed $name
*
* @dataProvider providerForTestInvalidMixedNames
* @dataProvider providerForTestInvalidNames
*/
public function testInvalidMixedNames($name, string $exceptionMessage): void
public function testInvalidNames($name, string $exceptionMessage): void
{
$this->expectException(InvalidArgumentException::class);
$this->expectException(InvalidTableName::class);
$this->expectExceptionMessage($exceptionMessage);
TableName::fromValue($name);
}
/**
* @return mixed[][]
* @psalm-return non-empty-list<array{mixed, string}>
* @return iterable<string, mixed[]>
* @psalm-return iterable<string, array{mixed, non-empty-string}>
*/
public function providerForTestInvalidMixedNames(): array
public function providerForTestInvalidNames(): iterable
{
return [
[null, 'Expected a string. Got: NULL'],
[1, 'Expected a string. Got: integer'],
[['table'], 'Expected a string. Got: array'],
];
yield 'null' => [null, 'The table name must be a non-empty string.'];
yield 'integer' => [1, 'The table name must be a non-empty string.'];
yield 'array' => [['table'], 'The table name must be a non-empty string.'];
yield 'empty string' => ['', 'The table name must be a non-empty string.'];
yield 'too long name' => [str_repeat('a', 65), 'The table name cannot be longer than 64 characters.'];
yield 'trailing space' => ['a ', 'The table name cannot end with a space character.'];
}
}