Skip to content

Commit d436163

Browse files
committed
Improve named constructors for List containers
1 parent 677fbdf commit d436163

File tree

8 files changed

+104
-63
lines changed

8 files changed

+104
-63
lines changed

CHANGELOG.md

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,14 @@ All Notable changes to `bakame/http-strucured-fields` will be documented in this
88

99
- `Item::fromTimestamp`, `Item::fromDateFormat` to improve item instantiation with dates.
1010
- `ParameterAccess::parameter` to ease parameter members value access.
11-
- **[BC Break]** `ParameterAccess::withoutAllParameters` is renamed `ParameterAccess::withoutAnyParameters`.
11+
- `InnerList::fromAssociativeParameters`
12+
- `InnerList::fromPairParameters`
13+
- **[BC Break]** `ParameterAccess::withoutAllParameters` is renamed `ParameterAccess::withoutAnyParameter`.
1214
- **[BC Break]** `OrderedList` is renamed `OuterList`.
1315
- **[BC Break]** `MemberContainer::remove` methods get added to the interface.
1416
- **[BC Break]** `MemberContainer::keys` method added to the interface.
17+
- **[BC Break]** `InnerList::from` is renamed `InnerList::fromMembers`.
18+
- **[BC Break]** `OuterList::from` is renamed `OuterList::fromMembers`.
1519

1620
### Fixed
1721

@@ -31,9 +35,11 @@ All Notable changes to `bakame/http-strucured-fields` will be documented in this
3135
- **[BC Break]** `OrderedList` is removed, use `OuterList` instead.
3236
- **[BC Break]** `ParameterAccess::withoutAllParameters` is removed, use `ParameterAccess::withoutAnyParameters` instead.
3337
- **[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.
36-
38+
- **[BC Break]** remove `InnerList::fromList`, use `InnerList::from` instead.
39+
- **[BC Break]** remove `OuterList::fromList`, use `OuterList::from` instead.
40+
- **[BC Break]** remove `InnerList::from` use `InnerList::fromMembers`.
41+
- **[BC Break]** remove `OuterList::from` use `OuterList::fromMembers`.
42+
-
3743
## [0.7.0] - 2023-02-06
3844

3945
### Added

README.md

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,11 @@ $newResponse = $response->headers->set('foo', $bar);
100100
The library provides all five (5) structured defined in the RFC inside the `Bakame\Http\StructuredFields`
101101
namespace.
102102

103-
- `Item`;
104-
- `Dictionary` and `Parameters` as 2 Ordered map Containers;
105-
- `OuterList` and `InnerList` as 2 list Containers ;
103+
- `Item`
104+
- `Parameters`
105+
- `Dictionary`
106+
- `OuterList`
107+
- `InnerList`
106108

107109
They all implement the `StructuredField` interface and expose a `fromHttpValue` named constructor:
108110

@@ -178,7 +180,7 @@ Conversely, changes can be applied to `OuterList` and `InnerList` with adapted m
178180
use Bakame\Http\StructuredFields\InnerList;
179181
use Bakame\Http\StructuredFields\Item;
180182

181-
$list = InnerList::from()
183+
$list = InnerList::fromMembers()
182184
->unshift('42')
183185
->push(42)
184186
->insert(1, 42.0)
@@ -206,7 +208,7 @@ $field->addParameter($key, $value): static;
206208
$field->appendParameter($key, $value): static;
207209
$field->prependParameter($key, $value): static;
208210
$field->withoutParameters(...$keys): static;
209-
$field->withoutAllParameters($): static;
211+
$field->withoutAnyParameter(): static;
210212
$field->withParameters(Parameters $parameters): static;
211213
```
212214

@@ -291,7 +293,7 @@ so they all expect an associative iterable to represents the parameters.
291293
use Bakame\Http\StructuredFields\Item;
292294
use Bakame\Http\StructuredFields\Value;
293295

294-
//@type DataType ByteSequence|Token|DateTimeInterface|Stringable|string|int|float|bool
296+
//@type DataType Value|ByteSequence|Token|DateTimeInterface|Stringable|string|int|float|bool
295297

296298
Item::from(DataType $value, iterable<string, Value> $associativeParameters = []): self;
297299
Item::fromPair(array{0:DataType, 1:iterable<array{0:string, 1:DataType}>} $pair): self;
@@ -305,16 +307,29 @@ Item::fromDateString(string $datetime, DateTimeZone|string|null $timezone): self
305307

306308
### Accessing members of Structured Fields Containers.
307309

308-
`Item` are accessible using three (3) methods:
310+
`Item` properties are accessible using the following methods:
309311

310312
```php
311313
use Bakame\Http\StructuredFields\Item;
312314

313315
$item = Item::from(CarbonImmutable::parse('today'));
314316
$item->type(); // return Type::Date;
315317
$item->value() // return CarbonImmutable::parse('today') (because it extends DateTimeImmutable)
316-
$item->parameters(); // returns a Parameters container
317-
$item->parameter('z'); // returns the Bare Item value or null if the key does not exists
318+
```
319+
320+
You can attach, read and update the associated `Parameters` instance using the
321+
following:
322+
323+
```php
324+
use Bakame\Http\StructuredFields\Parameters;
325+
326+
$item->parameter($key): mixed|null;
327+
$item->addParameter($key, $value): static;
328+
$item->appendParameter($key, $value): static;
329+
$item->prependParameter($key, $value): static;
330+
$item->withoutParameters(...$keys): static;
331+
$item->withoutAnyParameter(): static;
332+
$item->withParameters(Parameters $parameters): static;
318333
```
319334

320335
All containers implement PHP `IteratorAggregate`, `Countable` and `ArrayAccess` interfaces for easy usage in your codebase.
@@ -326,7 +341,7 @@ $container->has(string|int ...$offsets): bool;
326341
$container->get(string|int $offset): bool;
327342
$container->remove(string|int ...$offsets): bool;
328343
$container->hasMembers(): bool;
329-
$container->hasNotMembers(): bool;
344+
$container->hasNoMembers(): bool;
330345
```
331346

332347
To avoid invalid states, the modifying methods from PHP `ArrayAccess` will throw a `ForbiddenOperation` if you try to

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::from(...$member),
51+
is_iterable($member) => InnerList::fromMembers(...$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::from(...$value[0])->withParameters(Parameters::fromAssociative($value[1])) : $value;
110+
yield $key => is_array($value) ? InnerList::fromMembers(...$value[0])->withParameters(Parameters::fromAssociative($value[1])) : $value;
111111
}
112112
})(Parser::parseDictionary($httpValue)));
113113
}

src/InnerList.php

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
final class InnerList implements MemberList, ParameterAccess
2525
{
2626
/** @var list<Value> */
27-
private array $members;
27+
private readonly array $members;
2828

2929
/**
3030
* @param iterable<Value|DataType> $members
@@ -37,11 +37,31 @@ private function __construct(private readonly Parameters $parameters, iterable $
3737
/**
3838
* Returns a new instance.
3939
*/
40-
public static function from(Value|Token|ByteSequence|DateTimeInterface|Stringable|string|int|float|bool ...$members): static
40+
public static function fromMembers(Value|Token|ByteSequence|DateTimeInterface|Stringable|string|int|float|bool ...$members): static
4141
{
4242
return new self(Parameters::create(), $members);
4343
}
4444

45+
/**
46+
* Returns a new instance with an iter.
47+
*
48+
* @param iterable<string,Value|DataType> $parameters
49+
*/
50+
public static function fromAssociativeParameters(iterable $parameters, Value|Token|ByteSequence|DateTimeInterface|Stringable|string|int|float|bool ...$members): static
51+
{
52+
return new self(Parameters::fromAssociative($parameters), $members);
53+
}
54+
55+
/**
56+
* Returns a new instance.
57+
*
58+
* @param MemberOrderedMap<string, Value>|iterable<array{0:string, 1:Value|DataType}> $parameters
59+
*/
60+
public static function fromPairParameters(iterable $parameters, Value|Token|ByteSequence|DateTimeInterface|Stringable|string|int|float|bool ...$members): static
61+
{
62+
return new self(Parameters::fromPairs($parameters), $members);
63+
}
64+
4565
private static function filterMember(StructuredField|Token|ByteSequence|DateTimeInterface|Stringable|string|int|float|bool $member): Value
4666
{
4767
return match (true) {
@@ -60,7 +80,7 @@ public static function fromHttpValue(Stringable|string $httpValue): self
6080
{
6181
[$members, $parameters] = [...Parser::parseInnerList($httpValue)];
6282

63-
return self::from(...$members)
83+
return self::fromMembers(...$members)
6484
->withParameters(Parameters::fromAssociative($parameters));
6585
}
6686

src/InnerListTest.php

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ 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::from(...$arrayParams)
19+
$instance = InnerList::fromMembers(...$arrayParams)
2020
->withParameters(Parameters::fromAssociative(['test' => Item::from(42)]));
2121

2222
self::assertSame($stringItem, $instance->get(0));
@@ -31,7 +31,7 @@ public function it_can_add_or_remove_members(): void
3131
{
3232
$stringItem = Item::from('helloWorld');
3333
$booleanItem = Item::from(true);
34-
$instance = InnerList::from($stringItem, $booleanItem);
34+
$instance = InnerList::fromMembers($stringItem, $booleanItem);
3535

3636
self::assertCount(2, $instance);
3737
self::assertTrue($instance->has(1));
@@ -61,7 +61,7 @@ public function it_can_add_or_remove_members(): void
6161
#[Test]
6262
public function it_can_unshift_insert_and_replace(): void
6363
{
64-
$container = InnerList::from()
64+
$container = InnerList::fromMembers()
6565
->unshift('42')
6666
->push(42)
6767
->insert(1, 42.0)
@@ -76,7 +76,7 @@ public function it_can_unshift_insert_and_replace(): void
7676
#[Test]
7777
public function it_returns_the_same_object_if_nothing_is_changed(): void
7878
{
79-
$container = InnerList::from(42, 'forty-two');
79+
$container = InnerList::fromMembers(42, 'forty-two');
8080

8181
$sameContainer = $container
8282
->unshift()
@@ -91,21 +91,21 @@ public function it_fails_to_replace_invalid_index(): void
9191
{
9292
$this->expectException(InvalidOffset::class);
9393

94-
InnerList::from()->replace(0, ByteSequence::fromDecoded('Hello World'));
94+
InnerList::fromMembers()->replace(0, ByteSequence::fromDecoded('Hello World'));
9595
}
9696

9797
#[Test]
9898
public function it_fails_to_insert_at_an_invalid_index(): void
9999
{
100100
$this->expectException(InvalidOffset::class);
101101

102-
InnerList::from()->insert(3, ByteSequence::fromDecoded('Hello World'));
102+
InnerList::fromMembers()->insert(3, ByteSequence::fromDecoded('Hello World'));
103103
}
104104

105105
#[Test]
106106
public function it_fails_to_return_an_member_with_invalid_index(): void
107107
{
108-
$instance = InnerList::from();
108+
$instance = InnerList::fromMembers();
109109

110110
self::assertFalse($instance->has(3));
111111

@@ -117,7 +117,7 @@ public function it_fails_to_return_an_member_with_invalid_index(): void
117117
#[Test]
118118
public function it_can_access_its_parameter_values(): void
119119
{
120-
$instance = InnerList::from(false)->addParameter('foo', 'bar');
120+
$instance = InnerList::fromAssociativeParameters(['foo' => 'bar'], false);
121121

122122
self::assertSame('bar', $instance->parameters()->get('foo')->value());
123123
self::assertSame('bar', $instance->parameter('foo'));
@@ -128,7 +128,7 @@ public function it_fails_to_access_unknown_parameter_values(): void
128128
{
129129
$this->expectException(StructuredFieldError::class);
130130

131-
InnerList::from(false)->parameters()->get('bar')->value();
131+
InnerList::fromMembers(false)->parameters()->get('bar')->value();
132132
}
133133

134134
#[Test]
@@ -159,29 +159,29 @@ public function it_fails_to_insert_unknown_index_via_the_array_access_interface(
159159
{
160160
$this->expectException(StructuredFieldError::class);
161161

162-
InnerList::from()->insert(0, Item::from(42.0));
162+
InnerList::fromMembers()->insert(0, Item::from(42.0));
163163
}
164164

165165
#[Test]
166166
public function it_returns_the_same_object_if_no_member_is_removed(): void
167167
{
168-
self::assertCount(0, InnerList::from()->remove(0));
168+
self::assertCount(0, InnerList::fromMembers()->remove(0));
169169
}
170170

171171
#[Test]
172172
public function it_fails_to_fetch_an_value_using_an_integer(): void
173173
{
174174
$this->expectException(InvalidOffset::class);
175175

176-
InnerList::from()->get('zero');
176+
InnerList::fromMembers()->get('zero');
177177
}
178178

179179
#[Test]
180180
public function it_can_access_the_item_value(): void
181181
{
182182
$token = Token::fromString('token');
183183
$input = ['foobar', 0, false, $token];
184-
$structuredField = InnerList::from(...$input);
184+
$structuredField = InnerList::fromMembers(...$input);
185185

186186
self::assertFalse($structuredField->get(2)->value());
187187
self::assertEquals($token, $structuredField->get(-1)->value());
@@ -190,7 +190,7 @@ public function it_can_access_the_item_value(): void
190190
#[Test]
191191
public function it_can_create_via_with_parameters_method_a_new_object(): void
192192
{
193-
$instance1 = InnerList::from(Token::fromString('babayaga'), 'a', true)->addParameter('a', true);
193+
$instance1 = InnerList::fromPairParameters([['a', true]], Token::fromString('babayaga'), 'a', true);
194194
$instance2 = $instance1->withParameters(Parameters::fromAssociative(['a' => true]));
195195
$instance3 = $instance1->withParameters(Parameters::fromAssociative(['a' => false]));
196196

@@ -202,7 +202,7 @@ public function it_can_create_via_with_parameters_method_a_new_object(): void
202202
#[Test]
203203
public function it_can_create_via_parameters_access_methods_a_new_object(): void
204204
{
205-
$instance1 = InnerList::from(Token::fromString('babayaga'), 'a', true)->withParameters(Parameters::fromAssociative(['a' => true]));
205+
$instance1 = InnerList::fromMembers(Token::fromString('babayaga'), 'a', true)->withParameters(Parameters::fromAssociative(['a' => true]));
206206
$instance2 = $instance1->appendParameter('a', true);
207207
$instance7 = $instance1->addParameter('a', true);
208208
$instance3 = $instance1->prependParameter('a', false);
@@ -224,7 +224,7 @@ public function it_can_create_via_parameters_access_methods_a_new_object(): void
224224
#[Test]
225225
public function it_implements_the_array_access_interface(): void
226226
{
227-
$structuredField = InnerList::from('foobar', 'foobar', 'zero', 0);
227+
$structuredField = InnerList::fromMembers('foobar', 'foobar', 'zero', 0);
228228

229229
self::assertInstanceOf(Item::class, $structuredField->get(0));
230230
self::assertInstanceOf(Item::class, $structuredField[0]);
@@ -237,22 +237,22 @@ public function it_forbids_removing_members_using_the_array_access_interface():
237237
{
238238
$this->expectException(LogicException::class);
239239

240-
unset(InnerList::from('foobar', 'foobar', 'zero', 0)[0]);
240+
unset(InnerList::fromMembers('foobar', 'foobar', 'zero', 0)[0]);
241241
}
242242

243243
#[Test]
244244
public function it_forbids_adding_members_using_the_array_access_interface(): void
245245
{
246246
$this->expectException(LogicException::class);
247247

248-
InnerList::from('foobar', 'foobar', 'zero', 0)[0] = Item::from(false);
248+
InnerList::fromMembers('foobar', 'foobar', 'zero', 0)[0] = Item::from(false);
249249
}
250250

251251

252252
#[Test]
253253
public function it_can_returns_the_container_member_keys(): void
254254
{
255-
$instance = InnerList::from();
255+
$instance = InnerList::fromMembers();
256256

257257
self::assertSame([], $instance->keys());
258258

@@ -261,7 +261,7 @@ public function it_can_returns_the_container_member_keys(): void
261261

262262
self::assertSame([0, 1], $newInstance->keys());
263263

264-
$container = InnerList::from()
264+
$container = InnerList::fromMembers()
265265
->unshift('42')
266266
->push(42)
267267
->insert(1, 42.0)

src/OuterList.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
final class OuterList implements MemberList
2626
{
2727
/** @var list<Value|(MemberList<int, Value>&ParameterAccess)> */
28-
private array $members;
28+
private readonly array $members;
2929

3030
/**
3131
* @param Value|(MemberList<int, Value>&ParameterAccess) ...$members
@@ -38,7 +38,7 @@ private function __construct(MemberList|Value ...$members)
3838
/**
3939
* @param StructuredField|iterable<Value|DataType>|DataType ...$members
4040
*/
41-
public static function from(iterable|StructuredField|Token|ByteSequence|DateTimeInterface|Stringable|string|int|float|bool ...$members): self
41+
public static function fromMembers(iterable|StructuredField|Token|ByteSequence|DateTimeInterface|Stringable|string|int|float|bool ...$members): self
4242
{
4343
return new self(...array_map(self::filterMember(...), $members));
4444
}
@@ -53,7 +53,7 @@ private static function filterMember(iterable|StructuredField|Token|ByteSequence
5353
return match (true) {
5454
($member instanceof MemberList && $member instanceof ParameterAccess),
5555
$member instanceof Value => $member,
56-
is_iterable($member) => InnerList::from(...$member),
56+
is_iterable($member) => InnerList::fromMembers(...$member),
5757
default => Item::from($member),
5858
};
5959
}
@@ -65,8 +65,8 @@ private static function filterMember(iterable|StructuredField|Token|ByteSequence
6565
*/
6666
public static function fromHttpValue(Stringable|string $httpValue): self
6767
{
68-
return self::from(...array_map(
69-
fn (mixed $value) => is_array($value) ? InnerList::from(...$value[0])->withParameters(Parameters::fromAssociative($value[1])) : $value,
68+
return self::fromMembers(...array_map(
69+
fn (mixed $value) => is_array($value) ? InnerList::fromMembers(...$value[0])->withParameters(Parameters::fromAssociative($value[1])) : $value,
7070
Parser::parseList($httpValue)
7171
));
7272
}

0 commit comments

Comments
 (0)