Skip to content

Commit 07df1e7

Browse files
committed
feat: changes support values to be optional
1 parent 02d3433 commit 07df1e7

File tree

2 files changed

+132
-13
lines changed

2 files changed

+132
-13
lines changed

src/Providers/Models/DTO/SupportedOption.php

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
*
1717
* @phpstan-type SupportedOptionArrayShape array{
1818
* name: string,
19-
* supportedValues: array<int, mixed>
19+
* supportedValues?: array<int, mixed>
2020
* }
2121
*
2222
* @extends AbstractDataValueObject<SupportedOptionArrayShape>
@@ -32,19 +32,19 @@ class SupportedOption extends AbstractDataValueObject
3232
protected string $name;
3333

3434
/**
35-
* @var mixed[] The supported values for this option.
35+
* @var mixed[]|null The supported values for this option.
3636
*/
37-
protected array $supportedValues;
37+
protected ?array $supportedValues;
3838

3939
/**
4040
* Constructor.
4141
*
4242
* @since n.e.x.t
4343
*
4444
* @param string $name The option name.
45-
* @param mixed[] $supportedValues The supported values for this option.
45+
* @param mixed[]|null $supportedValues The supported values for this option, or null if any value is supported.
4646
*/
47-
public function __construct(string $name, array $supportedValues)
47+
public function __construct(string $name, ?array $supportedValues = null)
4848
{
4949
$this->name = $name;
5050
$this->supportedValues = $supportedValues;
@@ -72,6 +72,11 @@ public function getName(): string
7272
*/
7373
public function isSupportedValue($value): bool
7474
{
75+
// If supportedValues is null, any value is supported
76+
if ($this->supportedValues === null) {
77+
return true;
78+
}
79+
7580
return in_array($value, $this->supportedValues, true);
7681
}
7782

@@ -80,9 +85,9 @@ public function isSupportedValue($value): bool
8085
*
8186
* @since n.e.x.t
8287
*
83-
* @return mixed[] The supported values.
88+
* @return mixed[]|null The supported values, or null if any value is supported.
8489
*/
85-
public function getSupportedValues(): array
90+
public function getSupportedValues(): ?array
8691
{
8792
return $this->supportedValues;
8893
}
@@ -116,7 +121,7 @@ public static function getJsonSchema(): array
116121
'description' => 'The supported values for this option.',
117122
],
118123
],
119-
'required' => [self::KEY_NAME, self::KEY_SUPPORTED_VALUES],
124+
'required' => [self::KEY_NAME],
120125
];
121126
}
122127

@@ -129,10 +134,15 @@ public static function getJsonSchema(): array
129134
*/
130135
public function toArray(): array
131136
{
132-
return [
137+
$data = [
133138
self::KEY_NAME => $this->name,
134-
self::KEY_SUPPORTED_VALUES => array_values($this->supportedValues),
135139
];
140+
141+
if ($this->supportedValues !== null) {
142+
$data[self::KEY_SUPPORTED_VALUES] = array_values($this->supportedValues);
143+
}
144+
145+
return $data;
136146
}
137147

138148
/**
@@ -142,11 +152,11 @@ public function toArray(): array
142152
*/
143153
public static function fromArray(array $array): self
144154
{
145-
static::validateFromArrayData($array, [self::KEY_NAME, self::KEY_SUPPORTED_VALUES]);
155+
static::validateFromArrayData($array, [self::KEY_NAME]);
146156

147157
return new self(
148158
$array[self::KEY_NAME],
149-
$array[self::KEY_SUPPORTED_VALUES]
159+
$array[self::KEY_SUPPORTED_VALUES] ?? null
150160
);
151161
}
152162
}

tests/unit/Providers/Models/DTO/SupportedOptionTest.php

Lines changed: 110 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ public function testGetJsonSchema(): void
176176

177177
// Check required fields
178178
$this->assertArrayHasKey('required', $schema);
179-
$this->assertEquals([SupportedOption::KEY_NAME, SupportedOption::KEY_SUPPORTED_VALUES], $schema['required']);
179+
$this->assertEquals([SupportedOption::KEY_NAME], $schema['required']);
180180
}
181181

182182
/**
@@ -408,5 +408,114 @@ public function testImplementsCorrectInterfaces(): void
408408
$option
409409
);
410410
}
411+
412+
/**
413+
* Tests with null supportedValues (any value is supported).
414+
*
415+
* @return void
416+
*/
417+
public function testWithNullSupportedValues(): void
418+
{
419+
$option = new SupportedOption('any_value_option');
420+
421+
$this->assertEquals('any_value_option', $option->getName());
422+
$this->assertNull($option->getSupportedValues());
423+
424+
// Any value should be supported when supportedValues is null
425+
$this->assertTrue($option->isSupportedValue('string'));
426+
$this->assertTrue($option->isSupportedValue(123));
427+
$this->assertTrue($option->isSupportedValue(45.67));
428+
$this->assertTrue($option->isSupportedValue(true));
429+
$this->assertTrue($option->isSupportedValue(false));
430+
$this->assertTrue($option->isSupportedValue(null));
431+
$this->assertTrue($option->isSupportedValue(['array']));
432+
$this->assertTrue($option->isSupportedValue(['key' => 'value']));
433+
$this->assertTrue($option->isSupportedValue(new \stdClass()));
434+
}
435+
436+
/**
437+
* Tests toArray with null supportedValues.
438+
*
439+
* @return void
440+
*/
441+
public function testToArrayWithNullSupportedValues(): void
442+
{
443+
$option = new SupportedOption('flexible_option');
444+
$array = $option->toArray();
445+
446+
$this->assertIsArray($array);
447+
$this->assertEquals('flexible_option', $array[SupportedOption::KEY_NAME]);
448+
$this->assertArrayNotHasKey(SupportedOption::KEY_SUPPORTED_VALUES, $array);
449+
$this->assertCount(1, $array);
450+
}
451+
452+
/**
453+
* Tests fromArray with missing supportedValues.
454+
*
455+
* @return void
456+
*/
457+
public function testFromArrayWithMissingSupportedValues(): void
458+
{
459+
$data = [
460+
SupportedOption::KEY_NAME => 'open_option'
461+
];
462+
463+
$option = SupportedOption::fromArray($data);
464+
465+
$this->assertInstanceOf(SupportedOption::class, $option);
466+
$this->assertEquals('open_option', $option->getName());
467+
$this->assertNull($option->getSupportedValues());
468+
$this->assertTrue($option->isSupportedValue('anything'));
469+
}
470+
471+
/**
472+
* Tests round-trip with null supportedValues.
473+
*
474+
* @return void
475+
*/
476+
public function testRoundTripWithNullSupportedValues(): void
477+
{
478+
$original = new SupportedOption('unrestricted');
479+
480+
$array = $original->toArray();
481+
$restored = SupportedOption::fromArray($array);
482+
483+
$this->assertEquals($original->getName(), $restored->getName());
484+
$this->assertEquals($original->getSupportedValues(), $restored->getSupportedValues());
485+
$this->assertNull($restored->getSupportedValues());
486+
}
487+
488+
/**
489+
* Tests JSON serialization with null supportedValues.
490+
*
491+
* @return void
492+
*/
493+
public function testJsonSerializationWithNullSupportedValues(): void
494+
{
495+
$option = new SupportedOption('json_option');
496+
497+
$json = json_encode($option);
498+
$decoded = json_decode($json, true);
499+
500+
$this->assertIsString($json);
501+
$this->assertIsArray($decoded);
502+
$this->assertEquals('json_option', $decoded[SupportedOption::KEY_NAME]);
503+
$this->assertArrayNotHasKey(SupportedOption::KEY_SUPPORTED_VALUES, $decoded);
504+
}
505+
506+
/**
507+
* Tests JSON schema reflects optional supportedValues.
508+
*
509+
* @return void
510+
*/
511+
public function testJsonSchemaReflectsOptionalSupportedValues(): void
512+
{
513+
$schema = SupportedOption::getJsonSchema();
514+
515+
// Check that supportedValues is not in required fields
516+
$this->assertArrayHasKey('required', $schema);
517+
$this->assertEquals([SupportedOption::KEY_NAME], $schema['required']);
518+
$this->assertNotContains(SupportedOption::KEY_SUPPORTED_VALUES, $schema['required']);
519+
}
411520
}
412521

0 commit comments

Comments
 (0)