Skip to content

Commit 5ad2b1b

Browse files
committed
Improve Date public API usage
1 parent e8c8724 commit 5ad2b1b

File tree

5 files changed

+61
-58
lines changed

5 files changed

+61
-58
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ All Notable changes to `bakame/http-strucured-fields` will be documented in this
1111
- `InnerList::fromAssociative` to improve InnerList public API;
1212
- `Item` implements the `ValueAccess` interface;
1313
- `Item::toPair` to complement `Item::fromPair`;
14+
- `Item::fromDate` to improve and complete the Item Date public API;
1415
- `Value` internal class to improve Item public API;
1516
- `Token::toString` to return the string representation of the token.
1617
- Adding support for `MapKey` object to access container members.

README.md

Lines changed: 23 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ composer require bakame/http-structured-fields
2727
### Parsing and Serializing Structured Fields
2828

2929
Once the library is installed parsing the header value is done via the normalized `fromHttpValue` named
30-
constructor attached to all library's value objects as shown below:
30+
constructor attached to library's structured fields representation as shown below:
3131

3232
```php
3333

@@ -41,7 +41,7 @@ use Bakame\Http\StructuredFields\Item;
4141
// via any given framework or package or super global.
4242
// We are using a PSR-7 Request object in this example
4343

44-
$headerLine = $request->getHeaderLine('foo'); // 'foo: bar;baz=42' the raw header line
44+
$headerLine = $request->getHeaderLine('foo'); // 'foo: bar;baz=42' the raw header line is a structured field item
4545
$field = Item::fromHttpValue($headerLine);
4646
$field->value(); // returns Token::fromString('bar); the found token value
4747
$field->parameter('baz'); // returns 42; the value of the parameter or null if the parameter is not defined.
@@ -102,8 +102,8 @@ The table below summarizes the item value type.
102102
| Date | class `DateTimeImmutable` | `Type::Date` |
103103

104104
As shown in the table, the RFC define two (2) specific data types that can not be represented by
105-
PHP default type system, for them, we define two classes `Token` and `ByteSequence` to help
106-
representing them in our code.
105+
PHP default type system, for them, we have defined two classes `Token` and `ByteSequence` to help
106+
with represention.
107107

108108
```php
109109
use Bakame\Http\StructuredFields\Token;
@@ -130,14 +130,17 @@ $byte->encoded(); // returns 'SGVsbG8gd29ybGQh'
130130

131131
$token->equals($byte); // will return false;
132132
$byte->equals(ByteSequence::fromEncoded('SGVsbG8gd29ybGQh')); // will return true
133+
134+
$token->type(); // returns Type::Token enum
135+
$byte->type(); // returns Type::ByteSequence
133136
```
134137

135138
**Both classes DO NOT expose the `Stringable` interface to distinguish them
136139
from a string or a string like object**
137140

138141
#### Item
139142

140-
The defined types are all attached to the `Item` object where there values and type
143+
The defined types are all attached to the `Item` object where there values and types
141144
are accessible using the following methods:
142145

143146
```php
@@ -148,7 +151,7 @@ use Bakame\Http\StructuredFields\Type;
148151
// the Item::value() can return one of those type
149152
$item = Item::from(CarbonImmutable::parse('today'));
150153
$item->type(); // return Type::Date;
151-
$item->value() // return CarbonImmutable::parse('today') (because it extends DateTimeImmutable)
154+
$item->value() // return a CarbonImmutable instance because it extends DateTimeImmutable
152155
// you can also do
153156
Type::Date->equals($item); // returns true
154157
```
@@ -189,7 +192,7 @@ $container->pair(int $offset): array{0:string, 1:StructuredField};
189192
$container->toPairs(): iterable<array{0:string, 1:StructuredField}>;
190193
```
191194

192-
#### Accessing the paramters values
195+
#### Accessing the parameters values
193196

194197
You can also read the associated `Parameters` instance attached to an `InnerList` or a `Item` instances
195198
using the following methods:
@@ -205,35 +208,10 @@ $innerList->parameters(): Parameters;
205208

206209
Every value object can be used as a builder to create an HTTP field value.
207210

208-
The `Item` value object exposes lots of named constructors.
211+
#### Items value
209212

210-
```php
211-
use Bakame\Http\StructuredFields\ByteSequence;
212-
use Bakame\Http\StructuredFields\Item;
213-
214-
$item = Item::from("hello world", [
215-
"a" => Item::fromDecodedByteSequence("Hello World")
216-
]);
217-
$item->value(); // returns "hello world"
218-
$item->type(); // returns Type::String
219-
$item->parameter("a"); // returns ByteSequence::fromDecoded('Hello World');
220-
echo $item->toHttpValue(); // returns "hello world";a=:SGVsbG8gV29ybGQ=:
221-
```
222-
223-
**Of note: to instantiate a decimal number type a float MUST be used as the first argument of `Item::from`.**
224-
225-
```php
226-
use Bakame\Http\StructuredFields\Item;
227-
228-
$decimal = Item::from(42.0);
229-
$decimal->type(); //Type::Decimal
230-
231-
$integer = Item::fromPair([42]);
232-
$integer->type(); //return Type::Integer
233-
```
234-
235-
Here's the complete list of named constructors attached to the `Item` object.
236-
The `Item::from` method expects an associative iterable to represents the parameters.
213+
The `Item` value object exposes lots of named constructors to construct
214+
bare items (ie: item without parameters attached to them).
237215

238216
```php
239217
use Bakame\Http\StructuredFields\Item;
@@ -243,22 +221,24 @@ Item::fromEncodedByteSequence(string $value): self;
243221
Item::fromToken(string $value): self;
244222
Item::fromTimestamp(int $value): self;
245223
Item::fromDateFormat(string $format, string $datetime): self;
224+
Item::fromDateString(string $datetime, DateTimeZone|string|null $timezone = null): self;
225+
Item::fromDate(DateTimeInterface $datetime): self;
246226
Item::fromDecimal(int|float $value): self;
247227
Item::fromInteger(int|float $value): self;
248228
Item::true(): self;
249229
Item::false(): self;
250230
```
251231

252-
It is possible to update a `Item` object using the following modifying method:
232+
To update an `Item` object value, the `Item::withValue` method should be use:
253233

254234
```php
255235
use Bakame\Http\StructuredFields\Item;
256-
use Bakame\Http\StructuredFields\ValueAccess;
257-
use Bakame\Http\StructuredFields\Parameters;
258236

259237
Item::withValue(SfItemInput $value): static
260238
```
261239

240+
### Dictionaries
241+
262242
The `Dictionary` and `Parameters` instances can be build with an associative iterable structure as shown below
263243

264244
```php
@@ -337,6 +317,7 @@ $list = InnerList::from(
337317
echo $list->toHttpValue(); //'(:SGVsbG8gV29ybGQ=: 42.0 42)'
338318
echo $list; //'(:SGVsbG8gV29ybGQ=: 42.0 42)'
339319
```
320+
340321
Once again, builder methods exist on both classes to ease container construction.
341322

342323
```php
@@ -363,26 +344,10 @@ $list->replace($key, $member): static;
363344
$list->remove(...$key): static;
364345
```
365346

366-
# Adding and updating parameters
367-
368-
Apart from the `Item::from` named constructor, you can initialize a new Item instance using pairs
369-
as defined in the RFC:
370-
371-
```php
372-
use Bakame\Http\StructuredFields\ByteSequence;
373-
use Bakame\Http\StructuredFields\Item;
374-
375-
$item = Item::fromPair(["hello world", [
376-
["a", Item::from(ByteSequence::fromDecoded("Hello World"))],
377-
]]);
378-
$item->value(); // returns "hello world"
379-
$item->type(); // returns Type::String
380-
$item->parameter("a"); // returns ByteSequence::fromDecoded('Hello World');
381-
echo $item->toHttpValue(); // returns "hello world";a=:SGVsbG8gV29ybGQ=:
382-
```
347+
#### Adding and updating parameters
383348

384-
It is also possible to instantiate an `InnerList` instance with included parameters
385-
using one of those two additional named constructors:
349+
It is also possible to instantiate an `InnerList` or an `Item` instance with included parameters
350+
using one of these named constructors:
386351

387352
```php
388353
use Bakame\Http\StructuredFields\InnerList;
@@ -408,7 +373,7 @@ InnerList::toPair(): array{0:list<Item>, 1:Parameters}>};
408373
Item::toPair(): array{0:mixed, 1:Parameters}>};
409374
```
410375

411-
The `InnerList` and `Item` object provide additional modifying methods to help deal with parameters.
376+
The `InnerList` and `Item` object provide additional modifying methods to help deal with parameters.
412377
You can attach and update the associated `Parameters` instance using the following methods:
413378

414379
```php

src/Item.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,16 @@ public static function fromDateString(string $datetime, DateTimeZone|string|null
141141
return self::fromValue(Value::fromDateString($datetime, $timezone));
142142
}
143143

144+
/**
145+
* Returns a new instance from a DateTineInterface implementing object.
146+
*
147+
* @throws SyntaxError if the format is invalid
148+
*/
149+
public static function fromDate(DateTimeInterface $datetime): self
150+
{
151+
return self::fromValue(Value::fromDate($datetime));
152+
}
153+
144154
/**
145155
* Returns a new bare instance from value.
146156
*/

src/ItemTest.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ public function it_instantiates_a_date(): void
133133
$item = Item::fromHttpValue('@1583349795');
134134
self::assertEquals($item, Item::from(new DateTimeImmutable('2020-03-04 19:23:15')));
135135
self::assertEquals($item, Item::from(new DateTime('2020-03-04 19:23:15')));
136+
self::assertEquals($item, Item::fromDate(new DateTime('2020-03-04 19:23:15')));
136137
self::assertEquals($item, Item::fromTimestamp(1583349795));
137138
self::assertEquals($item, Item::fromDateFormat(DateTimeInterface::RFC822, 'Wed, 04 Mar 20 19:23:15 +0000'));
138139
self::assertTrue($item ->value() < Item::fromDateString('-1 year')->value());
@@ -147,6 +148,22 @@ public function it_fails_to_instantiate_an_invalid_date_format(): void
147148
Item::fromHttpValue('@112345.678');
148149
}
149150

151+
#[Test]
152+
public function it_fails_to_instantiate_an_out_of_range_date_object_in_the_future(): void
153+
{
154+
$this->expectException(SyntaxError::class);
155+
156+
Item::fromDate((new DateTimeImmutable())->setTimestamp(1_000_000_000_000_000));
157+
}
158+
159+
#[Test]
160+
public function it_fails_to_instantiate_an_out_of_range_date_object_in_the_past(): void
161+
{
162+
$this->expectException(SyntaxError::class);
163+
164+
Item::fromDate((new DateTime())->setTimestamp(-1_000_000_000_000_000));
165+
}
166+
150167
#[Test]
151168
public function it_fails_to_instantiate_an_out_of_range_timestamp_in_the_future(): void
152169
{

src/Value.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,16 @@ public static function fromDateString(string $datetime, DateTimeZone|string|null
162162
return new self($value);
163163
}
164164

165+
/**
166+
* Returns a new instance from a DatetimeInterface implementing object.
167+
*
168+
* @throws SyntaxError if the format is invalid
169+
*/
170+
public static function fromDate(DateTimeInterface $datetime): self
171+
{
172+
return new self($datetime);
173+
}
174+
165175
public static function fromDecimal(int|float $value): self
166176
{
167177
return new self((float) $value);

0 commit comments

Comments
 (0)