Skip to content

Commit b880d4a

Browse files
committed
Simplify Public API
1 parent 4d1399b commit b880d4a

File tree

10 files changed

+193
-159
lines changed

10 files changed

+193
-159
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ All Notable changes to `bakame/http-strucured-fields` will be documented in this
3131
- **[BC Break]** `OrderedList` is removed, use `OuterList` instead.
3232
- **[BC Break]** `ParameterAccess::withoutAllParameters` is removed, use `ParameterAccess::withoutAnyParameters` instead.
3333
- **[BC Break]** remove the `$parameters` argument from all `Item` named constuctore except from `Item::from`.
34+
- **[BC Break]** remove the `InnerList::fromList`, use `InnerList::from` instead.
35+
- **[BC Break]** remove the `OuterList::fromList`, use `OuterList::from` instead.
3436

3537
## [0.7.0] - 2023-02-06
3638

README.md

Lines changed: 56 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@
77
[![Total Downloads](https://img.shields.io/packagist/dt/bakame/http-structured-fields.svg?style=flat-square)](https://packagist.org/packages/bakame/http-structured-fields)
88
[![Sponsor development of this project](https://img.shields.io/badge/sponsor%20this%20package-%E2%9D%A4-ff69b4.svg?style=flat-square)](https://github.com/sponsors/nyamsprod)
99

10-
The package uses value objects to parse, serialize, build and update [HTTP Structured Fields][1] in PHP.
10+
`bakame/http-structured-fields` is a framework-agnostic PHP library that allows you to parse, serialize and build HTTP Structured Fields in PHP according to the [RFC][1].
1111

1212
HTTP Structured fields are intended for use for new HTTP fields that wish to use a common syntax that is
13-
more restrictive than traditional HTTP field values or could be used to [retrofit current fields][2] to
13+
more restrictive than traditional HTTP field values or could be used to retrofit current fields value to
1414
have them compliant with the new syntax.
1515

1616
```php
@@ -52,45 +52,65 @@ echo $list[-1]->value(); // returns '/member/*/comments'
5252

5353
### Parsing and Serializing Structured Fields
5454

55-
To parse the string representation of an HTTP field you must use the `fromHttpValue`
56-
named constructor provided to all the immutable value objects:
55+
Once the library is installed parsing the header value is done via one of the package value object via its `fromHttpValue`
56+
named constructor as shown below:
5757

5858
```php
59-
use Bakame\Http\StructuredFields\Dictionary;
6059

61-
$dictionary = Dictionary::fromHttpValue("a=?0, b, c=?1; foo=bar");
60+
declare(strict_types=1);
61+
62+
namespace MyApp;
63+
64+
require 'vendor/autoload.php';
65+
66+
use Bakame\Http\StructuredFields\Item;
67+
68+
//the HTTP request object is given by your application
69+
// or any given framework or package.
70+
//We use a PSR-7 Request object in this example
71+
72+
$headerLine = $request->getHeaderLine('foo');
73+
$field = Item::fromHttpValue($headerLine);
74+
$field->value(); // returns the found token value
75+
$field->parameter('baz'); // returns the value of the parameter or null if the parameter is not defined.
6276
```
6377

64-
`fromHttpValue` returns an instance of the `Bakame\Http\StructuredFields\StructuredField` interface.
78+
The `fromHttpValue` method returns an instance of the `Bakame\Http\StructuredFields\StructuredField` interface.
6579
The interface provides a way to serialize the value object into a normalized RFC compliant HTTP field
6680
string value using the `toHttpValue` method.
6781

6882
To ease integration with current PHP frameworks and packages working with HTTP headers and trailers,
69-
each value object also exposes the `Stringable` interface method `__toString`,
70-
an alias of the `toHttpValue` method.
83+
each value object also exposes the `Stringable` interface method `__toString` as an alias
84+
of the `toHttpValue` method.
7185

7286
````php
73-
use Bakame\Http\StructuredFields\OuterList;
87+
use Bakame\Http\StructuredFields\Item;
7488

75-
$list = OuterList::fromHttpValue('("foo"; a=1;b=2);lvl=5, ("bar" "baz");lvl=1');
76-
echo $list->toHttpValue(); // '("foo";a=1;b=2);lvl=5, ("bar" "baz");lvl=1'
77-
echo $list; // '("foo";a=1;b=2);lvl=5, ("bar" "baz");lvl=1'
89+
$bar = Item::fromToken('bar')->addParameter('baz', Item::from(42));
90+
echo $bar->toHttpValue(); // return 'bar;baz=42'
91+
92+
//the HTTP response object is given by your application
93+
// or any given framework or package.
94+
//We use Symfony Response object in this example
95+
$newResponse = $response->headers->set('foo', $bar->toHttpValue());
96+
//or
97+
$newResponse = $response->headers->set('foo', $bar);
7898
````
7999

80-
The library provides currently five (5) immutable value objects define inside the `Bakame\Http\StructuredFields`
81-
namespace
100+
The library provides all five (5) structured defined in the RFC inside the `Bakame\Http\StructuredFields`
101+
namespace.
82102

83103
- `Item`;
84-
- `Dictionary` and `Parameters` as 2 Ordered Map Containers;
85-
- `OuterList` and `InnerList` as 2 List Containers ;
104+
- `Dictionary` and `Parameters` as 2 Ordered map Containers;
105+
- `OuterList` and `InnerList` as 2 list Containers ;
86106

87-
they all implement the `StructuredField` interface and expose a `fromHttpValue` named constructor:
107+
They all implement the `StructuredField` interface and expose a `fromHttpValue` named constructor:
88108

89109
### Building and Updating Structured Fields Values
90110

91111
Every value object can be used as a builder to create an HTTP field value.
92112

93-
For instance, `Dictionary` and `Parameters` can be build with an associative iterable as shown below
113+
The `Dictionary` and `Parameters` instances can be build with an associative iterable structure as shown below
94114

95115
```php
96116
use Bakame\Http\StructuredFields\Dictionary;
@@ -105,7 +125,7 @@ echo $value->toHttpValue(); //"b=?0, a=bar;baz=42, c=@1671800423"
105125
echo $value; //"b=?0, a=bar;baz=42, c=@1671800423"
106126
```
107127

108-
Or with an iterable structure of pairs as described in the RFC:
128+
Or with an iterable structure of pairs as per defined in the RFC:
109129

110130
```php
111131
use Bakame\Http\StructuredFields\Parameters;
@@ -120,7 +140,7 @@ echo $value->toHttpValue(); //;b=?0;a=bar;c=@1671800423
120140
echo $value; //;b=?0;a=bar;c=@1671800423
121141
```
122142

123-
If builder methods are preferred, the same result can be achieved with the following steps:
143+
If the preference is to use the builder pattern, the same result can be achieved with the following steps:
124144

125145
```php
126146
use Bakame\Http\StructuredFields\Dictionary;
@@ -129,7 +149,7 @@ use Bakame\Http\StructuredFields\Token;
129149

130150
$bar = Item::fromToken('bar')
131151
->addParameter('baz', Item::from(42));
132-
$dictBuilder = Dictionary::create()
152+
$value = Dictionary::create()
133153
->add('a', $bar)
134154
->prepend('b', Item::from(false))
135155
->append('c', Item::from(new DateTimeImmutable('2022-12-23 13:00:23')))
@@ -200,28 +220,28 @@ Items can have different types that are translated to PHP using:
200220

201221
The table below summarizes the item value type.
202222

203-
| HTTP DataType | Package Data Type | Package Enum Type |
204-
|---------------|--------------------------------------------------------|----------------------|
205-
| Integer | `int` | `Type::Integer` |
206-
| Decimal | `float` | `Type::Decimal` |
207-
| String | `string` or `Stringable` class | `Tyoe::String` |
208-
| Boolean | `bool` | `Type::Boolean` |
209-
| Token | class `Token` | `Type::Token` |
210-
| Byte Sequence | class `ByteSequence` | `Type::ByteSequence` |
211-
| Date | class `DateTimeImmutable` or `DateTimeInterface` class | `Type::Date` |
223+
| HTTP DataType | Package Data Type | Package Enum Type |
224+
|---------------|--------------------------------|----------------------|
225+
| Integer | `int` | `Type::Integer` |
226+
| Decimal | `float` | `Type::Decimal` |
227+
| String | `string` or `Stringable` class | `Tyoe::String` |
228+
| Boolean | `bool` | `Type::Boolean` |
229+
| Token | class `Token` | `Type::Token` |
230+
| Byte Sequence | class `ByteSequence` | `Type::ByteSequence` |
231+
| Date | class `DateTimeImmutable` | `Type::Date` |
212232

213233
```php
214234
use Bakame\Http\StructuredFields\ByteSequence;
215235
use Bakame\Http\StructuredFields\Item;
216236

217237
$item = Item::fromPair([
218238
"hello world", [
219-
["a", ByteSequence::fromDecoded("Hello World")],
239+
["a", Item::from(ByteSequence::fromDecoded("Hello World"))],
220240
]
221241
]);
222242
$item->value(); // returns "hello world"
223243
$item->type(); // returns Type::String
224-
$item->parameters("a"); // returns StructuredFields\ByteSequence::fromDecoded('Hello World');
244+
$item->parameters("a"); // returns ByteSequence::fromDecoded('Hello World');
225245
echo $item->toHttpValue(); // returns "hello world";a=:SGVsbG8gV29ybGQ=:
226246
```
227247

@@ -276,10 +296,10 @@ Item::fromPair(array{0:mixed, 1:iterable<array{0:string, 1:Value}>} $pair): self
276296
Item::fromDecodedByteSequence(string $value): self;
277297
Item::fromEncodedByteSequence(string $value): self;
278298
Item::fromToken(string $value): self;
279-
Item::fromDate(DateTimeInterface $value): self;
299+
Item::fromDate(DateTimeInterface $datetime): self;
280300
Item::fromTimestamp(int $value): self;
281-
Item::fromDateFormat(string $dateFormat, string $dateString): self;
282-
Item::fromDateFormat(string $dateString, DateTimeZone|string|null $timezone): self;
301+
Item::fromDateFormat(string $format, string $datetime): self;
302+
Item::fromDateString(string $datetime, DateTimeZone|string|null $timezone): self;
283303
```
284304

285305
### Accessing members of Structured Fields Containers.

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
"require-dev": {
3131
"friendsofphp/php-cs-fixer": "^v3.14.3",
3232
"httpwg/structured-field-tests": "*@dev",
33-
"phpstan/phpstan": "^1.10.4",
33+
"phpstan/phpstan": "^1.10.5",
3434
"phpstan/phpstan-strict-rules": "^1.5.0",
3535
"phpstan/phpstan-phpunit": "^1.3.10",
3636
"phpstan/phpstan-deprecation-rules": "^1.1.2",

src/Dictionary.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ private static function filterMember(iterable|StructuredField|Token|ByteSequence
4848
return match (true) {
4949
($member instanceof MemberList && $member instanceof ParameterAccess),
5050
$member instanceof Value => $member,
51-
is_iterable($member) => InnerList::fromList($member),
51+
is_iterable($member) => InnerList::from(...$member),
5252
default => Item::from($member),
5353
};
5454
}
@@ -107,7 +107,7 @@ public static function fromHttpValue(Stringable|string $httpValue): self
107107
{
108108
return new self((function (iterable $pairs) {
109109
foreach ($pairs as $key => $value) {
110-
yield $key => is_array($value) ? InnerList::fromList(...$value) : $value;
110+
yield $key => is_array($value) ? InnerList::from(...$value[0])->withParameters(Parameters::fromAssociative($value[1])) : $value;
111111
}
112112
})(Parser::parseDictionary($httpValue)));
113113
}

src/InnerList.php

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,6 @@ public static function from(Value|Token|ByteSequence|DateTimeInterface|Stringabl
4242
return new self(Parameters::create(), $members);
4343
}
4444

45-
/**
46-
* @param iterable<Value|DataType> $members
47-
* @param iterable<string, Value|DataType> $parameters
48-
*/
49-
public static function fromList(iterable $members = [], iterable $parameters = []): self
50-
{
51-
return new self(Parameters::fromAssociative($parameters), $members);
52-
}
53-
5445
private static function filterMember(StructuredField|Token|ByteSequence|DateTimeInterface|Stringable|string|int|float|bool $member): Value
5546
{
5647
return match (true) {
@@ -67,7 +58,10 @@ private static function filterMember(StructuredField|Token|ByteSequence|DateTime
6758
*/
6859
public static function fromHttpValue(Stringable|string $httpValue): self
6960
{
70-
return self::fromList(...Parser::parseInnerList($httpValue));
61+
[$members, $parameters] = [...Parser::parseInnerList($httpValue)];
62+
63+
return self::from(...$members)
64+
->withParameters(Parameters::fromAssociative($parameters));
7165
}
7266

7367
public function parameters(): Parameters

src/InnerListTest.php

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ public function it_can_be_instantiated_with_an_collection_of_item(): void
1616
$stringItem = Item::from('helloWorld');
1717
$booleanItem = Item::from(true);
1818
$arrayParams = [$stringItem, $booleanItem];
19-
$instance = InnerList::fromList($arrayParams, Parameters::fromAssociative(['test' => Item::from(42)]));
19+
$instance = InnerList::from(...$arrayParams)
20+
->withParameters(Parameters::fromAssociative(['test' => Item::from(42)]));
2021

2122
self::assertSame($stringItem, $instance->get(0));
2223
self::assertTrue($instance->hasMembers());
@@ -30,7 +31,7 @@ public function it_can_add_or_remove_members(): void
3031
{
3132
$stringItem = Item::from('helloWorld');
3233
$booleanItem = Item::from(true);
33-
$instance = InnerList::fromList([$stringItem, $booleanItem]);
34+
$instance = InnerList::from($stringItem, $booleanItem);
3435

3536
self::assertCount(2, $instance);
3637
self::assertTrue($instance->has(1));
@@ -116,17 +117,18 @@ public function it_fails_to_return_an_member_with_invalid_index(): void
116117
#[Test]
117118
public function it_can_access_its_parameter_values(): void
118119
{
119-
$instance = InnerList::fromList([false], ['foo' => 'bar']);
120+
$instance = InnerList::from(false)->addParameter('foo', 'bar');
120121

121122
self::assertSame('bar', $instance->parameters()->get('foo')->value());
123+
self::assertSame('bar', $instance->parameter('foo'));
122124
}
123125

124126
#[Test]
125127
public function it_fails_to_access_unknown_parameter_values(): void
126128
{
127129
$this->expectException(StructuredFieldError::class);
128130

129-
InnerList::fromList([false], ['foo' => 'bar'])->parameters()->get('bar')->value();
131+
InnerList::from(false)->parameters()->get('bar')->value();
130132
}
131133

132134
#[Test]
@@ -179,7 +181,7 @@ public function it_can_access_the_item_value(): void
179181
{
180182
$token = Token::fromString('token');
181183
$input = ['foobar', 0, false, $token];
182-
$structuredField = InnerList::fromList($input);
184+
$structuredField = InnerList::from(...$input);
183185

184186
self::assertFalse($structuredField->get(2)->value());
185187
self::assertEquals($token, $structuredField->get(-1)->value());
@@ -188,7 +190,7 @@ public function it_can_access_the_item_value(): void
188190
#[Test]
189191
public function it_can_create_via_with_parameters_method_a_new_object(): void
190192
{
191-
$instance1 = InnerList::fromList([Token::fromString('babayaga'), 'a', true], ['a' => true]);
193+
$instance1 = InnerList::from(Token::fromString('babayaga'), 'a', true)->addParameter('a', true);
192194
$instance2 = $instance1->withParameters(Parameters::fromAssociative(['a' => true]));
193195
$instance3 = $instance1->withParameters(Parameters::fromAssociative(['a' => false]));
194196

@@ -200,7 +202,7 @@ public function it_can_create_via_with_parameters_method_a_new_object(): void
200202
#[Test]
201203
public function it_can_create_via_parameters_access_methods_a_new_object(): void
202204
{
203-
$instance1 = InnerList::fromList([Token::fromString('babayaga'), 'a', true], ['a' => true]);
205+
$instance1 = InnerList::from(Token::fromString('babayaga'), 'a', true)->withParameters(Parameters::fromAssociative(['a' => true]));
204206
$instance2 = $instance1->appendParameter('a', true);
205207
$instance7 = $instance1->addParameter('a', true);
206208
$instance3 = $instance1->prependParameter('a', false);

0 commit comments

Comments
 (0)