Skip to content

Commit 0326653

Browse files
committed
Add parser public API
1 parent de42d88 commit 0326653

17 files changed

Lines changed: 348 additions & 43 deletions

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,18 @@ All Notable changes to `bakame/http-strucured-fields` will be documented in this
1616
- `ParameterAccess::replaceParamater`
1717
- `ParameterAccess::withoutParametersByKeys`
1818
- `ParameterAccess::withoutParametersByIndices`
19+
- `ItemParser` interface to return an array representation of a Structured Field as an item.
20+
- `ParametersParser` interface to return an array representation of a Structured Field parameter container.
21+
- `DictionaryParser` interface to return an array representation of a Structured Field dictionary container.
22+
- `ListParser` interface to return an array representation of a Structured Field list container.
23+
- `InnerListParser` interface to return an array representation of a Structured Field inner list container.
24+
- `ValueParser` interface to return a PHP type of a Structured Field Value string representation.
25+
- `Parser` is now part of the public API
26+
- `Item::fromHttpValue` now has an optional second parameter to shift the parser implementation used
27+
- `Parameters::fromHttpValue` now has an optional second parameter to shift the parser implementation used
28+
- `Dictionary::fromHttpValue` now has an optional second parameter to shift the parser implementation used
29+
- `OuterList::fromHttpValue` now has an optional second parameter to shift the parser implementation used
30+
- `InnerList::fromHttpValue` now has an optional second parameter to shift the parser implementation used
1931

2032
### Fixed
2133

README.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,56 @@ All five (5) structured data type as defined in the RFC are provided inside the
113113
- `OuterList` (named `List` in the RFC but renamed in the package because `list` is a reserved word in PHP.)
114114
- `InnerList`
115115

116+
#### Advance usage
117+
118+
In order to allow:
119+
120+
- clearer decoupling betwen parsing and objet building
121+
- different parsers implementations
122+
- improve the package usage in testing.
123+
124+
Starting with version `1.1` the internal parser has been made public. The class exposes
125+
the following method each belonging to a different contract or interface.
126+
127+
```php
128+
Parser::parseValue(Stringable|string $httpValue): ByteSequence|Token|DateTimeImmutable|string|int|float|bool;
129+
Parser::parseItem(Stringable|string $httpValue): array;
130+
Parser::parseParameters(Stringable|string $httpValue): array;
131+
Parser::parseInnerList(Stringable|string $httpValue): array;
132+
Parser::parseList(Stringable|string $httpValue): array;
133+
Parser::parseDictionary(Stringable|string $httpValue): array;
134+
```
135+
136+
While the provided default `Parser` class implements all these methods
137+
you are free to only implement the methods you need.
138+
139+
```php
140+
use Bakame\Http\StructuredFields\Parser;
141+
142+
$parser = new Parser();
143+
$parser->parseValue('text/csv'); //returns Token::fromString('text/csv')
144+
$parser->parseItem('@1234567890;file=24');
145+
//returns an array
146+
// [
147+
// new DateTimeImmutable('@1234567890'),
148+
// ['file' => 24],
149+
// ]
150+
```
151+
152+
Each `fromHttpValue` method signature has been updated to take a second optional argument
153+
that represents the parser interface to use in order to allow parsing of the HTTP string
154+
representation value.
155+
156+
By default, if no parser is provided, the package will default to use the package `Parser` class,
157+
158+
```php
159+
Item::fromHttpValue(Stringable|string $httpValue, ItemParser $parser = new Parser()): Item;
160+
InnerList::fromHttpValue(Stringable|string $httpValue, InnerListParser $parser = new Parser()): InnerList;
161+
Dictionary::fromHttpValue(Stringable|string $httpValue, DictionaryParser $parser = new Parser()): Dictionary;
162+
OuterList::fromHttpValue(Stringable|string $httpValue, ListParser $parser = new Parser()): OuterList;
163+
Parameters::fromHttpValue(Stringable|string $httpValue, ParametersParser $parser = new Parser()): Parameters;
164+
```
165+
116166
### Accessing Structured Fields Values
117167

118168
#### RFC Value type

src/Dictionary.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,17 +108,17 @@ public static function fromPairs(iterable $pairs): self
108108
*
109109
* @throws SyntaxError If the string is not a valid
110110
*/
111-
public static function fromHttpValue(Stringable|string $httpValue): self
111+
public static function fromHttpValue(Stringable|string $httpValue, DictionaryParser $parser = new Parser()): self
112112
{
113113
$converter = fn (array $member): InnerList|Item => match (true) {
114114
is_array($member[0]) => InnerList::fromAssociative(
115115
array_map(fn (array $item) => Item::fromAssociative(...$item), $member[0]),
116116
$member[1]
117117
),
118-
default => Item::fromAssociative($member[0], $member[1]),
118+
default => Item::fromAssociative(...$member),
119119
};
120120

121-
return new self(array_map($converter, Parser::parseDictionary($httpValue)));
121+
return new self(array_map($converter, $parser->parseDictionary($httpValue)));
122122
}
123123

124124
public function toHttpValue(): string

src/DictionaryParser.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Bakame\Http\StructuredFields;
6+
7+
use Stringable;
8+
9+
/**
10+
* @phpstan-import-type SfType from StructuredField
11+
*/
12+
interface DictionaryParser
13+
{
14+
/**
15+
* Returns an ordered map represented as a PHP associative array from an HTTP textual representation.
16+
*
17+
* @see https://www.rfc-editor.org/rfc/rfc8941.html#section-4.2.2
18+
*
19+
* @return array<string, array{0:SfType|array<array{0:SfType, 1:array<string, SfType>}>, 1:array<string, SfType>}>
20+
*/
21+
public function parseDictionary(Stringable|string $httpValue): array;
22+
}

src/InnerList.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,12 @@ private static function filterMember(mixed $member): object
5959
*
6060
* @see https://www.rfc-editor.org/rfc/rfc8941.html#section-3.1
6161
*/
62-
public static function fromHttpValue(Stringable|string $httpValue): self
62+
public static function fromHttpValue(Stringable|string $httpValue, InnerListParser $parser = new Parser()): self
6363
{
64-
[$membersList, $parameters] = Parser::parseInnerList($httpValue);
64+
[$members, $parameters] = $parser->parseInnerList($httpValue);
6565

6666
return new self(
67-
array_map(fn (array $member): Item => Item::fromAssociative(...$member), $membersList),
67+
array_map(fn (array $member): Item => Item::fromAssociative(...$member), $members),
6868
Parameters::fromAssociative($parameters)
6969
);
7070
}

src/InnerListParser.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Bakame\Http\StructuredFields;
6+
7+
use Stringable;
8+
9+
/**
10+
* @phpstan-import-type SfType from StructuredField
11+
*/
12+
interface InnerListParser
13+
{
14+
/**
15+
* Returns an inner list represented as a PHP list array from an HTTP textual representation.
16+
*
17+
* @see https://www.rfc-editor.org/rfc/rfc8941.html#section-4.2.1.2
18+
*
19+
* @return array{0:array<array{0:SfType, 1:array<string, SfType>}>, 1:array<string, SfType>}
20+
*/
21+
public function parseInnerList(Stringable|string $httpValue): array;
22+
}

src/Item.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ private function __construct(
3232
*
3333
* @throws SyntaxError If the HTTP value can not be parsed
3434
*/
35-
public static function fromHttpValue(Stringable|string $httpValue): self
35+
public static function fromHttpValue(Stringable|string $httpValue, ItemParser $parser = new Parser()): self
3636
{
37-
return self::fromAssociative(...Parser::parseItem($httpValue));
37+
return self::fromAssociative(...$parser->parseItem($httpValue));
3838
}
3939

4040
/**

src/ItemParser.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Bakame\Http\StructuredFields;
6+
7+
use Stringable;
8+
9+
/**
10+
* @phpstan-import-type SfType from StructuredField
11+
*/
12+
interface ItemParser
13+
{
14+
/**
15+
* Returns an Item represented as a PHP list array from an HTTP textual representation.
16+
*
17+
* @see https://www.rfc-editor.org/rfc/rfc8941.html#name-parsing-an-item
18+
*
19+
* @return array{0:SfType, 1:array<string, SfType>}
20+
*/
21+
public function parseItem(Stringable|string $httpValue): array;
22+
}

src/ListParser.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Bakame\Http\StructuredFields;
6+
7+
use Stringable;
8+
9+
/**
10+
* @phpstan-import-type SfType from StructuredField
11+
*/
12+
interface ListParser
13+
{
14+
/**
15+
* Returns an ordered list represented as a PHP list array from an HTTP textual representation.
16+
*
17+
* @see https://www.rfc-editor.org/rfc/rfc8941.html#section-4.2.1
18+
*
19+
* @return array<array{0:SfType|array<array{0:SfType, 1:array<string, SfType>}>, 1:array<string, SfType>}>
20+
*/
21+
public function parseList(Stringable|string $httpValue): array;
22+
}

src/OuterList.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,17 +60,17 @@ private static function filterMember(mixed $member): object
6060
*
6161
* @see https://www.rfc-editor.org/rfc/rfc8941.html#section-3.1
6262
*/
63-
public static function fromHttpValue(Stringable|string $httpValue): self
63+
public static function fromHttpValue(Stringable|string $httpValue, ListParser $parser = new Parser()): self
6464
{
6565
$converter = fn (array $member): InnerList|Item => match (true) {
6666
is_array($member[0]) => InnerList::fromAssociative(
6767
array_map(fn (array $item) => Item::fromAssociative(...$item), $member[0]),
6868
$member[1]
6969
),
70-
default => Item::fromAssociative($member[0], $member[1]),
70+
default => Item::fromAssociative(...$member),
7171
};
7272

73-
return new self(...array_map($converter, Parser::parseList($httpValue)));
73+
return new self(...array_map($converter, $parser->parseList($httpValue)));
7474
}
7575

7676
/**

0 commit comments

Comments
 (0)