Skip to content

Commit 7bb9ee1

Browse files
committed
Improve builder specification
1 parent d9c9f2c commit 7bb9ee1

File tree

5 files changed

+114
-1
lines changed

5 files changed

+114
-1
lines changed

src/InnerList.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
*
2828
* @phpstan-import-type SfItem from StructuredField
2929
* @phpstan-import-type SfItemInput from StructuredField
30+
* @phpstan-type SfInnerListPair array{0:iterable<SfItemInput>,b1:MemberOrderedMap<string, SfItem>|iterable<array{0:string, 1:SfItemInput}>}
3031
*
3132
* @implements MemberList<int, SfItem>
3233
*/

src/Item.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
*
1818
* @phpstan-import-type SfItem from StructuredField
1919
* @phpstan-import-type SfItemInput from StructuredField
20+
* @phpstan-type SfItemPair array{0:ByteSequence|Token|DisplayString|DisplayString|DateTimeInterface|string|int|float|bool, 1:MemberOrderedMap<string, SfItem>|iterable<array{0:string, 1:SfItemInput}>}
2021
*/
2122
final class Item implements ParameterAccess, ValueAccess
2223
{

src/OuterList.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
*
2727
* @phpstan-import-type SfMember from StructuredField
2828
* @phpstan-import-type SfMemberInput from StructuredField
29+
* @phpstan-import-type SfInnerListPair from InnerList
30+
* @phpstan-import-type SfItemPair from Item
2931
*
3032
* @implements MemberList<int, SfMember>
3133
*/
@@ -76,6 +78,19 @@ public static function fromHttpValue(Stringable|string $httpValue, ListParser $p
7678
return new self(...array_map($converter, $parser->parseList($httpValue)));
7779
}
7880

81+
/**
82+
* @param iterable<SfInnerListPair|SfItemPair> $pairs
83+
*/
84+
public static function fromPairs(iterable $pairs): self
85+
{
86+
$members = [];
87+
foreach ($pairs as [$member, $parameters]) {
88+
$members[] = is_iterable($member) ? InnerList::fromPair([$member, $parameters]) : Item::fromPair([$member, $parameters]);
89+
}
90+
91+
return self::new(...$members);
92+
}
93+
7994
/**
8095
* @param SfMember|SfMemberInput ...$members
8196
*/

src/functions.php

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
* Parse a header conform to the HTTP Structured Field RFCs.
1515
*
1616
* @param 'dictionary'|'parameters'|'list'|'innerlist'|'item' $type
17+
*
1718
* @throws OutOfRangeException If the value is unknown or undefined
1819
*/
1920
function http_parse_structured_field(string $type, string $httpValue): StructuredField
@@ -24,7 +25,37 @@ function http_parse_structured_field(string $type, string $httpValue): Structure
2425
'list' => OuterList::fromHttpValue($httpValue),
2526
'innerlist' => InnerList::fromHttpValue($httpValue),
2627
'item' => Item::fromHttpValue($httpValue), /* @phpstan-ignore-line */
27-
default => throw new ValueError('The submitted type "'.$type.'" is unknown or not supported,'), /* @phpstan-ignore-line */
28+
default => throw new OutOfBoundsException('The submitted type "'.$type.'" is unknown or not supported,'), /* @phpstan-ignore-line */
29+
};
30+
}
31+
}
32+
33+
if (!function_exists('http_build_structured_field')) {
34+
/**
35+
* Build an HTTP Structured Field Text representation fron an iterable PHP structure.
36+
*
37+
* @param 'dictionary'|'parameters'|'list'|'innerlist'|'item' $type
38+
* @param iterable $data the iterable data used to generate the structured field
39+
*
40+
* @throws OutOfBoundsException If the type is unknown or unsupported
41+
*
42+
* @see Dictionary::fromPairs()
43+
* @see Parameters::fromPairs()
44+
* @see OuterList::fromPairs()
45+
* @see InnerList::fromPair()
46+
* @see Item::fromPair()
47+
*/
48+
function http_build_structured_field(string $type, iterable $data): string /* @phptan-ignore-line */
49+
{
50+
$data = [...$data];
51+
52+
return match ($type) {
53+
'dictionary' => Dictionary::fromPairs($data)->toHttpValue(),
54+
'parameters' => Parameters::fromPairs($data)->toHttpValue(),
55+
'list' => OuterList::fromPairs($data)->toHttpValue(),
56+
'innerlist' => InnerList::fromPair($data)->toHttpValue(), /* @phpstan-ignore-line */
57+
'item' => Item::fromPair($data)->toHttpValue(), /* @phpstan-ignore-line */
58+
default => throw new OutOfBoundsException('The submitted type "'.$type.'" is unknown or not supported,'), /* @phpstan-ignore-line */
2859
};
2960
}
3061
}

tests/FunctionsTest.php

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Bakame\Http\StructuredFields;
6+
7+
use PHPUnit\Framework\Attributes\Test;
8+
use PHPUnit\Framework\TestCase;
9+
10+
final class FunctionsTest extends TestCase
11+
{
12+
#[Test]
13+
public function ti_will_generate_the_structured_field_text_represenation_for_an_innerlist(): void
14+
{
15+
self::assertSame(
16+
http_build_structured_field('innerlist', [['a', 'b', 'c'], [['a', true]]]),
17+
InnerList::fromPair([['a', 'b', 'c'], [['a', true]]])->toHttpValue()
18+
);
19+
}
20+
21+
#[Test]
22+
public function ti_will_generate_the_structured_field_text_represenation_for_an_item(): void
23+
{
24+
self::assertSame(
25+
http_build_structured_field('item', ['coucoulesamis', [['a', false]]]),
26+
Item::fromPair(['coucoulesamis', [['a', false]]])->toHttpValue()
27+
);
28+
}
29+
30+
#[Test]
31+
public function ti_will_generate_the_structured_field_text_represenation_for_parameters(): void
32+
{
33+
$data = [['a', false], ['b', true]];
34+
35+
self::assertSame(
36+
http_build_structured_field('parameters', $data),
37+
Parameters::fromPairs($data)->toHttpValue()
38+
);
39+
}
40+
41+
#[Test]
42+
public function ti_will_generate_the_structured_field_text_represenation_for_dictionary(): void
43+
{
44+
$data = [['a', false], ['b', Item::fromDateString('+30 minutes')]];
45+
46+
self::assertSame(
47+
http_build_structured_field('dictionary', $data),
48+
Dictionary::fromPairs($data)->toHttpValue()
49+
);
50+
}
51+
52+
#[Test]
53+
public function ti_will_generate_the_structured_field_text_represenation_for_list(): void
54+
{
55+
$data = [
56+
['coucoulesamis', [['a', false]]],
57+
[['a', 'b', Item::fromDateString('+30 minutes')], [['a', true]]],
58+
];
59+
60+
self::assertSame(
61+
http_build_structured_field('list', $data),
62+
OuterList::fromPairs($data)->toHttpValue() /* @phpstan-ignore-line */
63+
);
64+
}
65+
}

0 commit comments

Comments
 (0)