Skip to content

Commit 3959179

Browse files
committed
Improve Item::fromPair and documentation
1 parent 7c1221f commit 3959179

File tree

4 files changed

+66
-32
lines changed

4 files changed

+66
-32
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ All Notable changes to `bakame/http-strucured-fields` will be documented in this
66

77
### Added
88

9-
- `Item::fromPair` named constructor to create a new instance from a pair expressed as an array list with two values.
9+
- `Item::fromPair` named constructor to create a new instance from a pair expressed as an array list with two values.
1010
- `Parameters::sanitize` ensure the container always contains only Bare Items.
1111
- `autoload.php` script to allow non composer application to load the package
1212

README.md

Lines changed: 50 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ System Requirements
3737
Installation
3838
------------
3939

40-
Using composer:
40+
Use composer:
4141

4242
```
4343
composer require bakame/http-structured-fields
@@ -60,13 +60,13 @@ echo $list->get(-1)->value; //returns '/member/*/comments'
6060
Parsing and Serializing Structured Fields
6161
------------
6262

63-
an HTTP field can be defined as:
63+
an HTTP field value can be:
6464

6565
- a Dictionary,
6666
- a List,
6767
- an Item.
6868

69-
For each of those top-level types, the package provides a dedicated value object to parse the textual
69+
For each of these top-level types, the package provides a dedicated value object to parse the textual
7070
representation of the field and to serialize the value object back to the textual representation.
7171

7272
- Parsing is done via a common named constructor `fromHttpValue` which expects the Header or Trailer string value.
@@ -90,17 +90,18 @@ Building Structured Fields
9090

9191
### Items
9292

93-
#### Bare Items
93+
#### Definitions
9494

95-
Items can have different types [defined in the RFC][3]. They are translated to PHP native type
96-
when possible otherwise two additional classes
95+
Items can have different types [defined in the RFC][3].
9796

98-
- `Bakame\Http\StructuredFields\Token` and
99-
- `Bakame\Http\StructuredFields\ByteSequence`
97+
They are translated to PHP using:
10098

101-
are used to represent non-native types as shown in the table below:
99+
- native type where possible
100+
- specific classes defined in the package namespace to represent non-native type
102101

103-
| HTTP DataType | Returned value | validation method |
102+
The table below summarize the item value type.
103+
104+
| HTTP DataType | Package Data Type | validation method |
104105
|---------------|----------------------|------------------------|
105106
| Integer | `int` | `Item::isInteger` |
106107
| Decimal | `float` | `Item::isDecimal` |
@@ -109,12 +110,29 @@ are used to represent non-native types as shown in the table below:
109110
| Token | class `Token` | `Item::isToken` |
110111
| Byte Sequence | class `ByteSequence` | `Item::isByteSequence` |
111112

112-
#### Items with parameters
113+
Items can be associated with an ordered maps of key-value pairs also known as parameters, where the
114+
keys are strings and the value are bare items. Their public API is covered in subsequent paragraphs.
115+
116+
**An item without any parameter associated to it is said to be a bare item.**
117+
118+
#### Token Data type
119+
120+
The Token data type is a special string as defined in the RFC. To distinguish it from a normal string, the `Bakame\Http\StructuredFields\Token` class is used.
121+
122+
To instantiate the class you are required to use the `Token::fromString` named constructor.
123+
The class also exposes the complementat=ry public methods `Token::toString` as well as the `Token::toHttpValue` to enable its textual representation.
113124

114-
Item can be associated with that an ordered maps of key-value pairs called `Parameters`, where the
115-
keys are strings and the value are bare items. Their public API will be cover in subsequent paragraphs.
116125

117-
#### Usage
126+
#### Byte Sequence Data type
127+
128+
The Byte Sequence data type is a special string as defined in the RFC to represent base64 encoded data. To distinguish it from a normal string,
129+
the `Bakame\Http\StructuredFields\ByteSequence` class is used.
130+
131+
To instantiate the class you are required to use the `ByteSequence::fromDecoded` or `ByteSequence::fromEncoded` named constructors.
132+
The class also exposes the complementat=ry public methods `ByteSequence::decoded`, `ByteSequence::encoded` as well as
133+
the `ByteSequence::toHttpValue` to enable its textual representation.
134+
135+
#### Usages
118136

119137
Instantiation via type recognition is done using the `Item::from` named constructor.
120138

@@ -124,27 +142,33 @@ Instantiation via type recognition is done using the `Item::from` named construc
124142
```php
125143
use Bakame\Http\StructuredFields;
126144

127-
$item = StructuredFields\Item::from("hello world", ["a" => 1]);
145+
$item = StructuredFields\Item::from("hello world", ["a" => true]);
128146
$item->value; //returns "hello world"
129147
$item->isString(); //return true
130148
$item->isToken(); //return false
131-
$item->parameters->value("a"); //returns 1
149+
$item->parameters->value("a"); //returns true
132150
```
133151

134152
Conversely, the `Item::fromPair` is an alternative to the `Item::from`
135153
which expects a tuple composed by an array as a list where:
136154

137155
- The first member on index `0` represents one of the six (6) item type value;
138-
- The second optional member, on index `1`, MUST be an iterable construct where its index represents the parameter key and its value an item or a item type value;
156+
- The second optional member, on index `1`, MUST be an iterable construct containing tuples of key-value pairs;
139157

140158
```php
141159
use Bakame\Http\StructuredFields;
142160

143-
$item = StructuredFields\Item::fromPair(["hello world", ["a" => 1]]);
161+
$item = StructuredFields\Item::fromPair([
162+
"hello world",
163+
[
164+
["a", StructuredFields\ByteSequence::fromDecoded("Hello World")]
165+
]
166+
]);
144167
$item->value; //returns "hello world"
145168
$item->isString(); //return true
146-
$item->isToken(); //return false
147-
$item->parameters->value("a"); //returns 1
169+
$item->parameters->get("a")->isByteSequence(); //returns true
170+
$item->parameters->value("a")->decoded(); //returns 'Hello World'
171+
echo $item->toHttpValue(); //returns "hello world";a=:SGVsbG8gV29ybGQ=:
148172
```
149173

150174
Once instantiated, accessing `Item` properties is done via two (2) readonly properties:
@@ -168,8 +192,7 @@ $item->isInteger(); //return true
168192

169193
### Containers
170194

171-
Apart from the `Item` structure, the package exposes different containers
172-
with different requirements via the following value objects:
195+
The package exposes different ordered maps and lists with different requirements via the following value objects:
173196

174197
- `Dictionary`,
175198
- `Parameters`,
@@ -204,14 +227,14 @@ $parameters->clear()->isEmpty(); // returns true
204227
The `Parameters` and the `Dictionary` classes allow associating a string
205228
key to its members
206229

207-
- `Parameters` can only contains `Item` instances
230+
- `Parameters` can only contain `Item` instances
208231
- `Dictionary` instance can contain `Item` and/or `InnerList` instances.
209232

210233
Both classes exposes the following:
211234

212235
getter methods:
213236

214-
- `fromAssociative` a named constructor to instantiate the container with an associative array;
237+
- `fromAssociative` a named constructor to instantiate the container with an iterable construct of associative value;
215238
- `fromPairs` a named constructor to instantiate the container with a list of key-value pairs;
216239
- `toPairs` returns an iterator to iterate over the container pairs;
217240
- `keys` to list all existing keys of the ordered maps as an array list;
@@ -266,7 +289,7 @@ $parameters->get('b'); // returns Item::from(true)
266289
iterator_to_array($parameters->toPairs(), true); // returns [['b', Item::from(true)], ['foo', Item::from('bar')]]
267290
iterator_to_array($parameters, true); // returns ['b' => Item::from(true), 'foo' => Item::from('bar')]
268291
$parameters->mergeAssociative(
269-
StructuredFields\Parameters::fromAssociative(['b' => true, 'foo' => 'foo']),
292+
StructuredFields\Parameters::fromPairs([['b', true], ['foo', 'foo']]),
270293
['b' => 'false']
271294
);
272295
$parameters->toHttpValue(); // returns ;b="false";foo="foo"
@@ -277,7 +300,7 @@ $parameters->value('unknown'); // returns null
277300

278301
The `OrderedList` and the `InnerList` classes are list of members that act as containers
279302

280-
The main distinction between `InnerList` and `OrderedList` are:
303+
The main distinction between `OrderedList` and `InnerList` are:
281304

282305
- `OrderedList` members must be `InnerList` or `Items`;
283306
- `InnerList` members must be `Items`;
@@ -317,7 +340,7 @@ $orderedList = StructuredFields\OrderedList::from(
317340
echo $orderedList->toHttpValue(); //returns '"42";foo="bar", (42.0 forty-two);a'
318341
```
319342

320-
A `Parameters` instance can be associated to an `InnerList` using the same API described for the `Item` value object.
343+
A `Parameters` instance can be associated to an `InnerList` using the same API as for the `Item` value object.
321344

322345
```php
323346
use Bakame\Http\StructuredFields;

src/Item.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public static function __set_state(array $properties): self
3838
/**
3939
* @param array{
4040
* 0:Token|ByteSequence|int|float|string|bool,
41-
* 1?:iterable<string,Item|ByteSequence|Token|bool|int|float|string>
41+
* 1?:Parameters|iterable<array{0:string, 1:Item|ByteSequence|Token|bool|int|float|string}>
4242
* } $pair
4343
*/
4444
public static function fromPair(array $pair): self
@@ -52,7 +52,7 @@ public static function fromPair(array $pair): self
5252
throw new SyntaxError('The pair first value should be the item value and the optional second value the item parameters.');
5353
}
5454

55-
return self::from(...$pair);
55+
return self::from($pair[0], Parameters::fromPairs($pair[1]));
5656
}
5757

5858
/**

src/ItemTest.php

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ public function it_can_exchange_parameters(): void
262262
/**
263263
* @test
264264
*/
265-
public function it_can_create_an_item_from_a_array_pair(): void
265+
public function it_can_create_an_item_from_a_array_of_pairs(): void
266266
{
267267
$instance1 = Item::from(Token::fromString('babayaga'));
268268
$instance2 = Item::fromPair([Token::fromString('babayaga')]);
@@ -277,7 +277,7 @@ public function it_can_create_an_item_from_a_array_pair(): void
277277
* @dataProvider invalidPairProvider
278278
* @param array<mixed> $pair
279279
*/
280-
public function it_fails_to_create_an_item_from_a_array_pair(array $pair): void
280+
public function it_fails_to_create_an_item_from_an_array_of_pairs(array $pair): void
281281
{
282282
$this->expectException(SyntaxError::class);
283283

@@ -293,4 +293,15 @@ public function invalidPairProvider(): iterable
293293
yield 'empty extra filled pair' => ['pair' => [1, [2], 3]];
294294
yield 'associative array' => ['pair' => ['value' => 'bar', 'parameters' => ['foo' => 'bar']]];
295295
}
296+
297+
/**
298+
* @test
299+
*/
300+
public function it_can_create_an_item_from_a_array_of_pairs_and_parameters(): void
301+
{
302+
$instance1 = Item::from(Token::fromString('babayaga'), ['a' => true]);
303+
$instance2 = Item::fromPair([Token::fromString('babayaga'), [['a', true]]]);
304+
305+
self::assertEquals($instance2, $instance1);
306+
}
296307
}

0 commit comments

Comments
 (0)