Skip to content

Commit 9f39429

Browse files
committed
Implementing ParameterAccess::toPair new method
1 parent 2561d73 commit 9f39429

11 files changed

+164
-36
lines changed

CHANGELOG.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@ All Notable changes to `bakame/http-strucured-fields` will be documented in this
77
### Added
88

99
- `InnerList::fromPair` to improve InnerList public API;
10+
- `InnerList::toPair` to improve InnerList public API;
1011
- `InnerList::fromAssociative` to improve InnerList public API;
11-
- `Value` class to improve Item public API;
1212
- `Item` implements the `ValueAccess` interface;
13-
- `Item::fromValue` named constructor to instantiate a new `Item` from a `Value` object;
14-
- Adding support for `MapKey` object.
13+
- `Item::toPair` to complement `Item::fromPair`;
14+
- `Value` internal class to improve Item public API;
15+
- Adding support for `MapKey` object to access container members.
1516

1617
### Fixed
1718

README.md

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ Per the RFC, items can have different types that are translated to PHP using:
9191

9292
The table below summarizes the item value type.
9393

94-
| HTTP DataType | Package Data Type | Package Enum Type |
94+
| RFC Type | PHP Type | Package Enum Type |
9595
|---------------|--------------------------------|----------------------|
9696
| Integer | `int` | `Type::Integer` |
9797
| Decimal | `float` | `Type::Decimal` |
@@ -144,7 +144,7 @@ are accessible using the following methods:
144144
use Bakame\Http\StructuredFields\Item;
145145
use Bakame\Http\StructuredFields\Type;
146146

147-
//@type DataType ByteSequence|Token|DateTimeImmutable|Stringable|string|int|float|bool
147+
//@type SfItemInput ByteSequence|Token|DateTimeImmutable|Stringable|string|int|float|bool
148148
// the Item::value() can return one of those type
149149
$item = Item::from(CarbonImmutable::parse('today'));
150150
$item->type(); // return Type::Date;
@@ -260,18 +260,20 @@ The `Item::from` method expects an associative iterable to represents the parame
260260

261261
```php
262262
use Bakame\Http\StructuredFields\Item;
263-
use Bakame\Http\StructuredFields\ValueAccess;
264263

265-
//@type DataType Value|ByteSequence|Token|DateTimeInterface|Stringable|string|int|float|bool
264+
//@type SfItemInput ByteSequence|Token|DateTimeInterface|Stringable|string|int|float|bool
266265

267-
Item::from(DataType $value, iterable<string, Value> $associativeParameters = []): self;
268-
Item::fromPair(array{0:DataType, 1:iterable<array{0:string, 1:DataType}>} $pair): self;
266+
Item::from(SfItemInput $value, iterable<string, SfItemInput> $associativeParameters = []): self;
267+
Item::fromPair(array{0:SfItemInput, 1:iterable<array{0:string, 1:SfItemInput}>} $pair): self;
269268
Item::fromDecodedByteSequence(string $value): self;
270269
Item::fromEncodedByteSequence(string $value): self;
271270
Item::fromToken(string $value): self;
272271
Item::fromTimestamp(int $value): self;
273272
Item::fromDateFormat(string $format, string $datetime): self;
274-
Item::fromDateString(string $datetime, DateTimeZone|string|null $timezone): self;
273+
Item::fromDecimal(int|float $value): self;
274+
Item::fromInteger(int|float $value): self;
275+
Item::true(): self;
276+
Item::false(): self;
275277
```
276278

277279
It is possible to update a `Item` object using the following modifying method:
@@ -281,7 +283,7 @@ use Bakame\Http\StructuredFields\Item;
281283
use Bakame\Http\StructuredFields\ValueAccess;
282284
use Bakame\Http\StructuredFields\Parameters;
283285

284-
Item::withValue(Value|DataType $value): static
286+
Item::withValue(SfItemInput $value): static
285287
```
286288

287289
And just like with the `InnerList` instance the `Item` object provides additional modifying methods
@@ -420,10 +422,9 @@ using one of those two additional named constructors:
420422

421423
```php
422424
use Bakame\Http\StructuredFields\InnerList;
423-
use Bakame\Http\StructuredFields\ValueAccess;
424425

425-
InnerList::fromAssociative(iterable<string, Value|DataType> $parameters, ...$members): self;
426-
InnerList::fromPair(array{0:list<Item>, iterable<array{0:string, 1:Value|DataType}>} $pair): self;
426+
InnerList::fromAssociative(iterable<string, SfItemInput> $parameters, ...$members): self;
427+
InnerList::fromPair(array{0:list<Item>, iterable<array{0:string, 1:SfItemInput}>} $pair): self;
427428
```
428429

429430
## Contributing

src/InnerList.php

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ private static function filterMember(mixed $member): object
5353
/**
5454
* Returns a new instance.
5555
*/
56-
public static function from(StructuredField|Value|Token|ByteSequence|DateTimeInterface|Stringable|string|int|float|bool ...$members): self
56+
public static function from(StructuredField|Token|ByteSequence|DateTimeInterface|Stringable|string|int|float|bool ...$members): self
5757
{
5858
return new self(Parameters::create(), $members);
5959
}
@@ -90,7 +90,7 @@ public static function fromPair(array $pair): self
9090
*/
9191
public static function fromAssociative(
9292
iterable $parameters,
93-
StructuredField|Value|Token|ByteSequence|DateTimeInterface|Stringable|string|int|float|bool ...$members
93+
StructuredField|Token|ByteSequence|DateTimeInterface|Stringable|string|int|float|bool ...$members
9494
): self {
9595
return new self(Parameters::fromAssociative($parameters), $members);
9696
}
@@ -167,6 +167,14 @@ public function __toString(): string
167167
return $this->toHttpValue();
168168
}
169169

170+
/**
171+
* @return array{0:list<SfItem>, 1:MemberOrderedMap<string, SfItem>}
172+
*/
173+
public function toPair(): array
174+
{
175+
return [$this->members, $this->parameters];
176+
}
177+
170178
public function count(): int
171179
{
172180
return count($this->members);

src/InnerListTest.php

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace Bakame\Http\StructuredFields;
66

77
use LogicException;
8+
use PHPUnit\Framework\Attributes\DataProvider;
89
use PHPUnit\Framework\Attributes\Test;
910
use PHPUnit\Framework\TestCase;
1011

@@ -208,6 +209,39 @@ public function it_can_create_via_with_parameters_method_a_new_object(): void
208209
self::assertEquals([...$instance1], [...$instance3]);
209210
}
210211

212+
/**
213+
* @param array<mixed> $pair
214+
*/
215+
#[Test]
216+
#[DataProvider('invalidPairProvider')]
217+
public function it_fails_to_create_an_innerlist_from_an_array_of_pairs(array $pair): void
218+
{
219+
$this->expectException(SyntaxError::class);
220+
221+
InnerList::fromPair($pair); // @phpstan-ignore-line
222+
}
223+
224+
/**
225+
* @return iterable<string, array{pair:array<mixed>}>
226+
*/
227+
public static function invalidPairProvider(): iterable
228+
{
229+
yield 'empty pair' => ['pair' => []];
230+
yield 'empty extra filled pair' => ['pair' => [1, [2], 3]];
231+
yield 'associative array' => ['pair' => ['value' => 'bar', 'parameters' => ['foo' => 'bar']]];
232+
}
233+
234+
#[Test]
235+
public function it_can_create_and_return_an_array_of_pairs(): void
236+
{
237+
$instance = InnerList::fromPair([[42, 'forty-two'], [['foo', 'bar']]]);
238+
$res = $instance->toPair();
239+
240+
self::assertEquals([Item::from(42), Item::from('forty-two')], $res[0]);
241+
self::assertEquals(Parameters::fromAssociative(['foo' => 'bar']), $res[1]);
242+
self::assertEquals($instance, InnerList::fromPair($res));
243+
}
244+
211245
#[Test]
212246
public function it_can_create_via_parameters_access_methods_a_new_object(): void
213247
{

src/Item.php

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,11 @@ private function __construct(
3636
*/
3737
public static function from(mixed $value, iterable $parameters = []): self
3838
{
39-
if (!$value instanceof Value) {
40-
$value = new Value($value);
41-
}
42-
4339
if (!$parameters instanceof Parameters) {
4440
$parameters = Parameters::fromAssociative($parameters);
4541
}
4642

47-
return new self($value, $parameters);
43+
return new self(new Value($value), $parameters);
4844
}
4945

5046
/**
@@ -65,15 +61,11 @@ public static function fromPair(array $pair): self
6561
throw new SyntaxError('The pair first value should be the item value and the optional second value the item parameters.');
6662
}
6763

68-
if (!$pair[0] instanceof Value) {
69-
$pair[0] = new Value($pair[0]);
70-
}
71-
7264
if (!$pair[1] instanceof Parameters) {
7365
$pair[1] = Parameters::fromPairs($pair[1]);
7466
}
7567

76-
return new self($pair[0], $pair[1]);
68+
return new self(new Value($pair[0]), $pair[1]);
7769
}
7870

7971
/**
@@ -152,11 +144,31 @@ public static function fromDateString(string $datetime, DateTimeZone|string|null
152144
/**
153145
* Returns a new bare instance from value.
154146
*/
155-
public static function fromValue(Value $value): self
147+
private static function fromValue(Value $value): self
156148
{
157149
return new self($value, Parameters::create());
158150
}
159151

152+
public static function fromDecimal(int|float $value): self
153+
{
154+
return self::fromValue(Value::fromDecimal($value));
155+
}
156+
157+
public static function fromInteger(int|float $value): self
158+
{
159+
return self::fromValue(Value::fromInteger($value));
160+
}
161+
162+
public static function true(): self
163+
{
164+
return self::fromValue(Value::true());
165+
}
166+
167+
public static function false(): self
168+
{
169+
return self::fromValue(Value::false());
170+
}
171+
160172
public function value(): ByteSequence|Token|DateTimeImmutable|string|int|float|bool
161173
{
162174
return $this->value->value;
@@ -196,6 +208,14 @@ public function toHttpValue(): string
196208
return $this->value->serialize().$this->parameters->toHttpValue();
197209
}
198210

211+
/**
212+
* @return array{0:SfItemInput, 1:MemberOrderedMap<string, SfItem>}
213+
*/
214+
public function toPair(): array
215+
{
216+
return [$this->value->value, $this->parameters];
217+
}
218+
199219
public function withValue(mixed $value): static
200220
{
201221
$value = new Value($value);

src/ItemTest.php

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,32 @@ public function it_fails_to_instantiate_a_date_with_an_invalid_datetime(): void
187187
Item::fromDateString('foobar');
188188
}
189189

190+
#[Test]
191+
public function it_instantiates_a_decimal(): void
192+
{
193+
self::assertSame(42.0, Item::from(42.0)->value());
194+
self::assertSame(42.0, Item::fromDecimal(42)->value());
195+
self::assertSame(42.0, Item::fromDecimal(42.0)->value());
196+
}
197+
198+
#[Test]
199+
public function it_instantiates_a_integer(): void
200+
{
201+
self::assertSame(42, Item::from(42)->value());
202+
self::assertSame(42, Item::fromInteger(42.9)->value());
203+
self::assertSame(42, Item::fromInteger(42.0)->value());
204+
self::assertSame(42, Item::fromInteger(42)->value());
205+
}
206+
207+
#[Test]
208+
public function it_instantiates_a_boolean(): void
209+
{
210+
self::assertTrue(Item::from(true)->value());
211+
self::assertTrue(Item::true()->value());
212+
self::assertFalse(Item::from(false)->value());
213+
self::assertFalse(Item::false()->value());
214+
}
215+
190216
#[Test]
191217
public function it_instantiates_a_binary(): void
192218
{
@@ -315,6 +341,17 @@ public function it_can_create_an_item_from_a_array_of_pairs(): void
315341
self::assertEquals($instance3, $instance1);
316342
}
317343

344+
#[Test]
345+
public function it_can_create_and_return_an_array_of_pairs(): void
346+
{
347+
$instance = Item::fromPair([42, [['foo', 'bar']]]);
348+
$res = $instance->toPair();
349+
350+
self::assertSame(42, $res[0]);
351+
self::assertEquals(Parameters::fromAssociative(['foo' => 'bar']), $res[1]);
352+
self::assertEquals($instance, Item::fromPair($res));
353+
}
354+
318355
#[Test]
319356
#[DataProvider('invalidPairProvider')]
320357
/**

src/OuterList.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ final class OuterList implements MemberList
3232
/**
3333
* @param SfMember|SfMemberInput ...$members
3434
*/
35-
private function __construct(iterable|Value|Token|ByteSequence|DateTimeInterface|Stringable|string|int|float|bool ...$members)
35+
private function __construct(iterable|Token|ByteSequence|DateTimeInterface|Stringable|string|int|float|bool ...$members)
3636
{
3737
$this->members = array_map(self::filterMember(...), array_values([...$members]));
3838
}
@@ -54,7 +54,7 @@ private static function filterMember(mixed $member): object
5454
/**
5555
* @param SfMember|SfMemberInput ...$members
5656
*/
57-
public static function from(iterable|StructuredField|Value|Token|ByteSequence|DateTimeInterface|Stringable|string|int|float|bool ...$members): self
57+
public static function from(iterable|StructuredField|Token|ByteSequence|DateTimeInterface|Stringable|string|int|float|bool ...$members): self
5858
{
5959
return new self(...$members);
6060
}
@@ -182,7 +182,7 @@ public function offsetSet(mixed $offset, mixed $value): void
182182
/**
183183
* Inserts members at the beginning of the list.
184184
*/
185-
public function unshift(StructuredField|Value|Token|ByteSequence|DateTimeInterface|Stringable|string|int|float|bool ...$members): static
185+
public function unshift(StructuredField|Token|ByteSequence|DateTimeInterface|Stringable|string|int|float|bool ...$members): static
186186
{
187187
if ([] === $members) {
188188
return $this;
@@ -202,7 +202,7 @@ private function newInstance(iterable $members): self
202202
/**
203203
* Inserts members at the end of the list.
204204
*/
205-
public function push(StructuredField|Value|Token|ByteSequence|DateTimeInterface|Stringable|string|int|float|bool ...$members): static
205+
public function push(StructuredField|Token|ByteSequence|DateTimeInterface|Stringable|string|int|float|bool ...$members): static
206206
{
207207
if ([] === $members) {
208208
return $this;
@@ -216,7 +216,7 @@ public function push(StructuredField|Value|Token|ByteSequence|DateTimeInterface|
216216
*
217217
* @throws InvalidOffset If the index does not exist
218218
*/
219-
public function insert(int $key, StructuredField|Value|Token|ByteSequence|DateTimeInterface|Stringable|string|int|float|bool ...$members): static
219+
public function insert(int $key, StructuredField|Token|ByteSequence|DateTimeInterface|Stringable|string|int|float|bool ...$members): static
220220
{
221221
$offset = $this->filterIndex($key);
222222

@@ -233,7 +233,7 @@ public function insert(int $key, StructuredField|Value|Token|ByteSequence|DateTi
233233
};
234234
}
235235

236-
public function replace(int $key, StructuredField|Value|Token|ByteSequence|DateTimeInterface|Stringable|string|int|float|bool $member): static
236+
public function replace(int $key, StructuredField|Token|ByteSequence|DateTimeInterface|Stringable|string|int|float|bool $member): static
237237
{
238238
if (null === ($offset = $this->filterIndex($key))) {
239239
throw InvalidOffset::dueToIndexNotFound($key);

src/ParameterAccess.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,15 @@
66

77
/**
88
* @phpstan-import-type SfTypeInput from StructuredField
9+
* @phpstan-import-type SfItem from StructuredField
910
*/
1011
interface ParameterAccess
1112
{
13+
/**
14+
* @return array{0:mixed, 1:MemberOrderedMap<string, SfItem>}
15+
*/
16+
public function toPair(): array;
17+
1218
/**
1319
* Returns a copy of the associated parameter instance.
1420
*/

src/Parameters.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ public function remove(MapKey|string|int ...$keys): static
266266
/**
267267
* @param SfItemInput $member
268268
*/
269-
public function append(MapKey|string $key, StructuredField|Value|Token|ByteSequence|DateTimeInterface|Stringable|string|int|float|bool $member): static
269+
public function append(MapKey|string $key, StructuredField|Token|ByteSequence|DateTimeInterface|Stringable|string|int|float|bool $member): static
270270
{
271271
$key = $key instanceof MapKey ? $key->value : $key;
272272
$members = $this->members;
@@ -283,7 +283,7 @@ public function append(MapKey|string $key, StructuredField|Value|Token|ByteSeque
283283
/**
284284
* @param SfItemInput $member
285285
*/
286-
public function prepend(MapKey|string $key, StructuredField|Value|Token|ByteSequence|DateTimeInterface|Stringable|string|int|float|bool $member): static
286+
public function prepend(MapKey|string $key, StructuredField|Token|ByteSequence|DateTimeInterface|Stringable|string|int|float|bool $member): static
287287
{
288288
$key = $key instanceof MapKey ? $key->value : $key;
289289
$members = $this->members;

src/StructuredField.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
use Stringable;
88

99
/**
10-
* @phpstan-type SfTypeInput Value|ByteSequence|Token|\DateTimeInterface|\Stringable|string|int|float|bool
10+
* @phpstan-type SfTypeInput ByteSequence|Token|\DateTimeInterface|\Stringable|string|int|float|bool
1111
* @phpstan-type SfItem ValueAccess&ParameterAccess
1212
* @phpstan-type SfItemInput SfItem|SfTypeInput
1313
* @phpstan-type SfMember (MemberList<int, SfItem>|ValueAccess)&ParameterAccess

0 commit comments

Comments
 (0)