Skip to content

Commit ef0a241

Browse files
committed
Improve Container list implementation
1 parent 95bd28b commit ef0a241

File tree

4 files changed

+67
-38
lines changed

4 files changed

+67
-38
lines changed

CHANGELOG.md

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

99
- `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.
11+
- `InnerList::sanitize` ensure the list is without gaps.
12+
- `OrderedLost::sanitize` ensure the list is without gaps.
1113
- `autoload.php` script to allow non composer application to load the package
1214
- `OrderedList` and `InnerList` now implements the PHP `ArrayAccess` interface.
1315

@@ -23,7 +25,8 @@ All Notable changes to `bakame/http-strucured-fields` will be documented in this
2325

2426
### Removed
2527

26-
- None
28+
- **[BC Break]** `InnerList` no longer re-index its content replaced by `InnerList::sanitize` to force re-indexation.
29+
- **[BC Break]** `OrdererList` no longer re-index its content replaced by `InnerList::sanitize` to force re-indexation.
2730

2831
## [0.4.0] - 2022-03-27
2932

README.md

Lines changed: 38 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,7 @@ Building Structured Fields
9191

9292
#### Definitions
9393

94-
Items can have different types [defined in the RFC][3].
95-
96-
They are translated to PHP using:
94+
Items can have different types that are translated to PHP using:
9795

9896
- native type where possible
9997
- specific classes defined in the package namespace to represent non-native type
@@ -109,28 +107,24 @@ The table below summarize the item value type.
109107
| Token | class `Token` | `Item::isToken` |
110108
| Byte Sequence | class `ByteSequence` | `Item::isByteSequence` |
111109

112-
Items can be associated with an ordered maps of key-value pairs also known as parameters, where the
113-
keys are strings and the value are bare items. Their public API is covered in subsequent paragraphs.
114-
115-
**An item without any parameter associated to it is said to be a bare item.**
116-
117-
#### Token type
110+
##### Token
118111

119112
```php
120113
use Bakame\Http\StructuredFields;
121114

122-
$token = StructuredFields\Token::fromString('bar')]));
115+
$token = StructuredFields\Token::fromString('bar');
123116

124117
echo $token->toString(); //displays 'bar'
125118
echo $dictionary->toHttpValue(); //displays 'bar'
126119
```
127120

128-
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+
The Token data type is a special string as defined in the RFC. To distinguish it from a normal string,
122+
the `Bakame\Http\StructuredFields\Token` class is used.
129123

130124
To instantiate the class you are required to use the `Token::fromString` named constructor.
131125
The class also exposes the complementary public methods `Token::toString` as well as the `Token::toHttpValue` to enable its textual representation.
132126

133-
#### Byte Sequence type
127+
##### Byte Sequence
134128

135129
```php
136130
use Bakame\Http\StructuredFields;
@@ -144,15 +138,20 @@ echo $sequenceFromDecoded->toHttpValue(); //displays ':SGVsbG8gV29ybGQ=:'
144138
echo $sequenceFromEncoded->toHttpValue(); //displays ':SGVsbG8gV29ybGQ=:'
145139
```
146140

147-
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,
148-
the `Bakame\Http\StructuredFields\ByteSequence` class is used.
141+
The Byte Sequence data type is a special string as defined in the RFC to represent base64 encoded data.
142+
To distinguish it from a normal string, the `Bakame\Http\StructuredFields\ByteSequence` class is used.
149143

150-
To instantiate the class you are required to use the `ByteSequence::fromDecoded` or `ByteSequence::fromEncoded` named constructors.
151-
The class also exposes the complementary public methods `ByteSequence::decoded`, `ByteSequence::encoded` as well as
152-
the `ByteSequence::toHttpValue` to enable its textual representation.
144+
To instantiate the class you are required to use the `ByteSequence::fromDecoded` or `ByteSequence::fromEncoded`
145+
named constructors. The class also exposes the complementary public methods `ByteSequence::decoded`,
146+
`ByteSequence::encoded` as well as the `ByteSequence::toHttpValue` to enable its textual representation.
153147

154148
#### Usages
155149

150+
Items can be associated with an ordered maps of key-value pairs also known as parameters, where the
151+
keys are strings and the value are bare items. Their public API is covered in subsequent paragraphs.
152+
153+
**An item without any parameter associated to it is said to be a bare item.**
154+
156155
```php
157156
use Bakame\Http\StructuredFields;
158157

@@ -166,7 +165,8 @@ $item->parameters->value("a"); //returns true
166165
Instantiation via type recognition is done using the `Item::from` named constructor.
167166

168167
- The first argument represents one of the six (6) item type value;
169-
- The second argument, which is optional, MUST be an iterable construct where its index represents the parameter key and its value an item or a item type value;
168+
- The second argument, which is optional, MUST be an iterable construct
169+
where its index represents the parameter key and its value an item or an item type value;
170170

171171
```php
172172
use Bakame\Http\StructuredFields;
@@ -184,11 +184,12 @@ $item->parameters->value("a")->decoded(); //returns 'Hello World'
184184
echo $item->toHttpValue(); //returns "hello world";a=:SGVsbG8gV29ybGQ=:
185185
```
186186

187-
Conversely, the `Item::fromPair` is an alternative to the `Item::from`
188-
which expects a tuple composed by an array as a list where:
187+
`Item::fromPair` is an alternative to the `Item::from` named constructor, it expects
188+
a tuple composed by an array as a list where:
189189

190190
- The first member on index `0` represents one of the six (6) item type value;
191-
- The second optional member, on index `1`, MUST be an iterable construct containing tuples of key-value pairs;
191+
- The second optional member, on index `1`, **MUST** be an iterable construct containing
192+
tuples of key-value pairs;
192193

193194
Once instantiated, accessing `Item` properties is done via two (2) readonly properties:
194195

@@ -238,8 +239,7 @@ At any given time it is possible with each of these objects to:
238239
**Of note:**
239240

240241
- All setter methods are chainable
241-
- For setter methods, Item types are inferred using `Item::from` if a `Item` object is not submitted.
242-
- Because all containers can be access by their indexes, some changes may re-index them as to not expose missing indexes.
242+
- For setter methods, Item types are inferred using `Item::from` if a `Item` object is not provided.
243243

244244
#### Ordered Maps
245245

@@ -271,7 +271,7 @@ key to its members
271271
- `Parameters` can only contain `Item` instances
272272
- `Dictionary` instance can contain `Item` and/or `InnerList` instances.
273273

274-
Both classes exposes the following:
274+
Both classes expose the following:
275275

276276
named constructors:
277277

@@ -283,9 +283,9 @@ getter methods:
283283
- `toPairs` returns an iterator to iterate over the container pairs;
284284
- `keys` to list all existing keys of the ordered maps as an array list;
285285
- `has` tell whether a specific element is associated to a given `key`;
286-
- `hasPair` tell whether a `key-value` association exists at a given `index` (negative indexes are supported);
286+
- `hasPair` tell whether a `key-value` association exists at a given `index`;
287287
- `get` returns the element associated to a specific `key`;
288-
- `pair` returns the key-pair association present at a specific `index` (negative indexes are supported);
288+
- `pair` returns the key-pair association present at a specific `index`;
289289

290290
setter methods:
291291

@@ -298,9 +298,9 @@ setter methods:
298298

299299
The `Parameters` instance exposes the following additional methods:
300300

301-
- `Parameters::values()` to list all existing Bare Items value as an array list;
302-
- `Parameters::value(string $key)` to return the value of the Bare Item associated to the `$key` or `null` if the key is unknown or invalid;
303-
- `Parameters::sanitize()` to return an instance where all Items present in the container are Bare Items. Any non Bared Item instance will see its parameters getting clear up.
301+
- `Parameters::values` to list all existing Bare Items value as an array list;
302+
- `Parameters::value` to return the value of the Bare Item associated to the `$key` or `null` if the key is unknown or invalid;
303+
- `Parameters::sanitize` to return an instance where all Items present in the container are Bare Items. Any non Bared Item instance will see its parameters getting clear up.
304304

305305
```php
306306
use Bakame\Http\StructuredFields;
@@ -320,6 +320,8 @@ $parameters->toHttpValue(); // returns ;b="false";foo="foo"
320320
$parameters->value('unknown'); // returns null
321321
```
322322

323+
**Both classes support negative indexes.**
324+
323325
#### Lists
324326

325327
```php
@@ -347,7 +349,7 @@ The main distinction between `OrderedList` and `InnerList` are:
347349
- `InnerList` members must be `Items`;
348350
- `InnerList` can have a `Parameters` instance attached to it;
349351

350-
Both classes exposes the following:
352+
Both classes expose the following:
351353

352354
named constructors:
353355

@@ -366,6 +368,7 @@ setter methods
366368
- `insert` to add elements at a given position in the list;
367369
- `replace` to replace an element at a given position in the list;
368370
- `remove` to remove elements based on their position;
371+
- `sanitize` force re-indexation of the list if needed to remove key "gaps".
369372

370373
Additionally, both classes implements PHP `ArrayAccess` interface as syntactic sugar methods
371374
around the `get`, `has`, `push`, `remove` and `replace` methods.
@@ -377,14 +380,14 @@ $innerList = StructuredFields\InnerList::fromList([42, 42.0, "42"], ["a" => true
377380
isset($innerList[2]); //return true
378381
isset($innerList[42]); //return false
379382
$innerList[] = StructuredFields\Token::fromString('forty-two');
380-
unset($innerList[0]);
381-
unset($innerList[1]); //<-- we use `1` instead of 2 because of re-indexation !!!
383+
unset($innerList[0], $innerList[2]);
382384
echo $innerList->toHttpValue(); //returns '(42.0 forty-two);a'
383385
```
384386

385-
**if you try to set a key which does not exist an exception will be thrown as both
386-
classes must remain valid lists with no empty keys.
387-
Be aware that re-indexation behaviour may affect your logic**
387+
**if you try to set a key which does not exist an exception will be
388+
thrown as both classes must remain valid lists with no empty
389+
keys. Be aware that re-indexation behaviour may affect
390+
your logic**
388391

389392
```php
390393
use Bakame\Http\StructuredFields;

src/InnerList.php

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,18 @@ public function remove(int ...$indexes): self
187187
unset($this->members[$offset]);
188188
}
189189

190-
if ([] !== $offsets) {
190+
return $this;
191+
}
192+
193+
/**
194+
* Ensure the container always contains list.
195+
*
196+
* If gaps are present in the list their are removed
197+
* and the list gets re-indexed.
198+
*/
199+
public function sanitize(): self
200+
{
201+
if (!array_is_list($this->members)) {
191202
$this->members = array_values($this->members);
192203
}
193204

src/OrderedList.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,19 @@ public function remove(int ...$indexes): self
197197
unset($this->members[$offset]);
198198
}
199199

200-
if ([] !== $offsets) {
200+
return $this;
201+
}
202+
203+
204+
/**
205+
* Ensure the container always contains list.
206+
*
207+
* If gaps are present in the list their are removed
208+
* and the list gets re-indexed.
209+
*/
210+
public function sanitize(): self
211+
{
212+
if (!array_is_list($this->members)) {
201213
$this->members = array_values($this->members);
202214
}
203215

0 commit comments

Comments
 (0)