2 - Add InstanceConfig value object and InstanceType enum
This commit is contained in:
parent
7a2db5a14d
commit
bdd2b0f2e5
4 changed files with 199 additions and 3 deletions
65
packages/Lvl0/FediDiscover/src/Config/InstanceConfig.php
Normal file
65
packages/Lvl0/FediDiscover/src/Config/InstanceConfig.php
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lvl0\FediDiscover\Config;
|
||||
|
||||
use InvalidArgumentException;
|
||||
|
||||
final readonly class InstanceConfig
|
||||
{
|
||||
/**
|
||||
* @param array<string, mixed> $extras
|
||||
*/
|
||||
public function __construct(
|
||||
public InstanceType $type,
|
||||
public string $url,
|
||||
public bool $enabled,
|
||||
public int $intervalSeconds,
|
||||
public array $extras
|
||||
) {}
|
||||
|
||||
/**
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public static function fromArray(array $array): self
|
||||
{
|
||||
foreach (['type', 'url', 'enabled', 'interval_seconds'] as $key) {
|
||||
if (! array_key_exists($key, $array)) {
|
||||
throw new InvalidArgumentException("Missing required key: {$key}");
|
||||
}
|
||||
}
|
||||
|
||||
if ($array['interval_seconds'] <= 0) {
|
||||
throw new InvalidArgumentException('Interval seconds needs to be larger than zero');
|
||||
}
|
||||
|
||||
$type = InstanceType::tryFrom($array['type']);
|
||||
if ($type === null) {
|
||||
throw new InvalidArgumentException('Invalid type: ' . $array['type']);
|
||||
}
|
||||
|
||||
if (filter_var($array['url'], FILTER_VALIDATE_URL) === false) {
|
||||
throw new InvalidArgumentException('Invalid URL: ' . $array['url']);
|
||||
}
|
||||
|
||||
return new self(
|
||||
type: $type,
|
||||
url: $array['url'],
|
||||
enabled: $array['enabled'],
|
||||
intervalSeconds: $array['interval_seconds'],
|
||||
extras: $array['extras'] ?? []
|
||||
);
|
||||
}
|
||||
|
||||
public function toArray(): array
|
||||
{
|
||||
return [
|
||||
'type' => $this->type->value,
|
||||
'url' => $this->url,
|
||||
'enabled' => $this->enabled,
|
||||
'interval_seconds' => $this->intervalSeconds,
|
||||
'extras' => $this->extras,
|
||||
];
|
||||
}
|
||||
}
|
||||
10
packages/Lvl0/FediDiscover/src/Config/InstanceType.php
Normal file
10
packages/Lvl0/FediDiscover/src/Config/InstanceType.php
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lvl0\FediDiscover\Config;
|
||||
|
||||
enum InstanceType: string
|
||||
{
|
||||
case Mastodon = 'mastodon';
|
||||
}
|
||||
121
packages/Lvl0/FediDiscover/tests/Unit/InstanceConfigTest.php
Normal file
121
packages/Lvl0/FediDiscover/tests/Unit/InstanceConfigTest.php
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Lvl0\FediDiscover\Tests\Unit;
|
||||
|
||||
use Lvl0\FediDiscover\Config\InstanceConfig;
|
||||
use Lvl0\FediDiscover\Config\InstanceType;
|
||||
use PHPUnit\Framework\Attributes\DataProvider;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class InstanceConfigTest extends TestCase
|
||||
{
|
||||
public function test_from_array_returns_instance_config_with_correct_field_values(): void
|
||||
{
|
||||
$config = InstanceConfig::fromArray([
|
||||
'type' => 'mastodon',
|
||||
'url' => 'https://mastodon.social',
|
||||
'enabled' => true,
|
||||
'interval_seconds' => 600,
|
||||
'extras' => ['token' => 'abc123'],
|
||||
]);
|
||||
|
||||
$this->assertSame(InstanceType::Mastodon, $config->type);
|
||||
$this->assertSame('https://mastodon.social', $config->url);
|
||||
$this->assertTrue($config->enabled);
|
||||
$this->assertSame(600, $config->intervalSeconds);
|
||||
$this->assertSame(['token' => 'abc123'], $config->extras);
|
||||
}
|
||||
|
||||
public function test_from_array_rejects_non_positive_interval_seconds(): void
|
||||
{
|
||||
$this->expectException(\InvalidArgumentException::class);
|
||||
|
||||
InstanceConfig::fromArray([
|
||||
'type' => 'mastodon',
|
||||
'url' => 'https://mastodon.social',
|
||||
'enabled' => true,
|
||||
'interval_seconds' => 0,
|
||||
'extras' => [],
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_extras_defaults_to_empty_array_when_omitted(): void
|
||||
{
|
||||
$config = InstanceConfig::fromArray([
|
||||
'type' => 'mastodon',
|
||||
'url' => 'https://mastodon.social',
|
||||
'enabled' => true,
|
||||
'interval_seconds' => 600,
|
||||
]);
|
||||
|
||||
$this->assertSame([], $config->extras);
|
||||
}
|
||||
|
||||
#[DataProvider('requiredKeyProvider')]
|
||||
public function test_from_array_throws_when_required_key_is_missing(string $missingKey): void
|
||||
{
|
||||
$input = [
|
||||
'type' => 'mastodon',
|
||||
'url' => 'https://mastodon.social',
|
||||
'enabled' => true,
|
||||
'interval_seconds' => 600,
|
||||
];
|
||||
|
||||
unset($input[$missingKey]);
|
||||
|
||||
$this->expectException(\InvalidArgumentException::class);
|
||||
$this->expectExceptionMessageMatches('/' . preg_quote($missingKey, '/') . '/');
|
||||
|
||||
InstanceConfig::fromArray($input);
|
||||
}
|
||||
|
||||
public static function requiredKeyProvider(): array
|
||||
{
|
||||
return [
|
||||
'type missing' => ['type'],
|
||||
'url missing' => ['url'],
|
||||
'enabled missing' => ['enabled'],
|
||||
'interval_seconds missing' => ['interval_seconds'],
|
||||
];
|
||||
}
|
||||
|
||||
public function test_from_array_throws_invalid_argument_exception_for_unknown_type_string(): void
|
||||
{
|
||||
$this->expectException(\InvalidArgumentException::class);
|
||||
$this->expectExceptionMessageMatches('/pleroma/');
|
||||
|
||||
InstanceConfig::fromArray([
|
||||
'type' => 'pleroma',
|
||||
'url' => 'https://pleroma.example.com',
|
||||
'enabled' => true,
|
||||
'interval_seconds' => 600,
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_from_array_rejects_malformed_url(): void
|
||||
{
|
||||
$this->expectException(\InvalidArgumentException::class);
|
||||
|
||||
InstanceConfig::fromArray([
|
||||
'type' => 'mastodon',
|
||||
'url' => 'not a url',
|
||||
'enabled' => true,
|
||||
'interval_seconds' => 600,
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_to_array_produces_array_that_round_trips_through_from_array(): void
|
||||
{
|
||||
$original = [
|
||||
'type' => 'mastodon',
|
||||
'url' => 'https://mastodon.social',
|
||||
'enabled' => true,
|
||||
'interval_seconds' => 600,
|
||||
'extras' => ['token' => 'abc123'],
|
||||
];
|
||||
|
||||
$this->assertSame($original, InstanceConfig::fromArray($original)->toArray());
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue