Skip to content

Commit

Permalink
Update http structured fields package
Browse files Browse the repository at this point in the history
  • Loading branch information
nyamsprod committed Dec 25, 2023
1 parent eb5bfa8 commit 8f13d4f
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 39 deletions.
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ All Notable changes to `bakame/http-strucured-fields` will be documented in this
- `Token::tryFromString`
- `OuterList::fromPairs`
- `DataType` is now part of the public API
- `Type::fromVariable`
- `Type::tryFromVariable`
- the `Type` enum is now a baked string Enum.

### Fixed

Expand All @@ -19,7 +22,8 @@ All Notable changes to `bakame/http-strucured-fields` will be documented in this

### Deprecated

- None
- `Type::fromValue` use `Type::fromVariable` instead
- `Type::tryFromValue` use `Type::tryFromVariable` instead

### Removed

Expand Down
34 changes: 16 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ use Bakame\Http\StructuredFields\DataType;
use Bakame\Http\StructuredFields\Token;

//1 - parsing an Accept Header
$headerValue = 'text/html, application/xhtml+xml, application/xml;q=0.9, image/webp, */*;q=0.8';
$field = DataType::List->parse($headerValue);
$fieldValue = 'text/html, application/xhtml+xml, application/xml;q=0.9, image/webp, */*;q=0.8';
$field = DataType::List->parse($fieldValue);
$field[2]->value()->toString(); // returns 'application/xml'
$field[2]->parameter('q'); // returns (float) 0.9
$field[0]->value()->toString(); // returns 'text/html'
Expand Down Expand Up @@ -69,11 +69,11 @@ header. Content validation is out of scope for this library.
> [!NOTE]
> New in version 1.2.0
The `DataType` enum serves as a factory class to quickly parse and build a structured field.
The enum list all available data type according to the RFC. To parse a header you need to
give the `parse` method a string or a stringable object. On success, it will return a
`Bakame\Http\StruncturedFields\StruncturedField` implementing object otherwise an
exception will be thrown.
The `DataType` enum list all available data type according to the RFC. It is also a
Factory to enable parsing and building such data types. To parse a header you need
to give the `parse` method a string or a stringable object. On success, it will
return a `Bakame\Http\StruncturedFields\StruncturedField` implementing object
otherwise an exception will be thrown.

```php
$headerLine = 'bar;baz=42'; //the raw header line is a structured field item
Expand Down Expand Up @@ -103,14 +103,12 @@ echo DataType::List->build([
// display "dumela lefatshe";a=?0, ("a" "b" @1703319068);a
```

The data type can be given as a string or using the `DataType` enum.

#### Using specific named constructor

The package provides specific classes for each data type. if you do not wish to
use the `DataType` factoring, parsing the header value is done via the
`fromHttpValue` named constructor. The method is attached to each library's
structured fields representation as shown below:
To complement the factory and to allow for more fine-grained manipulations, the package
provides specific classes for each data type. if you do not wish to use the `DataType`
factoring, parsing the header value is done via the `fromHttpValue` named constructor.
The method is attached to each library's structured fields representation as shown below:

```php
declare(strict_types=1);
Expand Down Expand Up @@ -230,18 +228,18 @@ The table below summarizes the item value type.
| Date | class `DateTimeImmutable` | `Type::Date` |
| DisplayString | class `DisplayString` | `Type::DisplayString` |

The Enum `Type` which list all available types can be use to determine the RFC type
corresponding to a PHP structure using the `Type::fromValue` static method.
The Enum `Type` which list all available types can be used to determine the RFC type
corresponding to a PHP structure using the `Type::fromVariable` static method.
The method will throw if the structure is not recognized Alternatively it is possible
to use the `Type::tryFromValue` which will instead return `null` on unindentified type.
On success both methods returns the corresponding enum `Type`.

```php
use Bakame\Http\StructuredFields\Type;

echo Type::fromValue(42); // returns Type::Integer
echo Type::fromValue(42.0)->name; // returns 'Decimal'
echo Type::fromValue(new SplTempFileObject()); // throws InvalidArgument
echo Type::fromVariable(42)->value; // returns 'integer'
echo Type::fromVariable(42.0)->name; // returns 'Decimal'
echo Type::fromVariable(new SplTempFileObject()); // throws InvalidArgument
echo Type::tryFromValue(new SplTempFileObject()); // returns null
```

Expand Down
52 changes: 37 additions & 15 deletions src/Type.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,29 +31,51 @@ public function equals(mixed $other): bool
/**
* @throws InvalidArgument if the value can not be resolved into a supported HTTP structured field data type
*/
public static function fromValue(mixed $value): self
public static function fromVariable(mixed $value): self
{
return self::tryFromValue($value) ?? throw new InvalidArgument((is_object($value) ? 'An instance of "'.$value::class.'"' : 'A value of type "'.gettype($value).'"').' can not be used as an HTTP structured field data type.');
return self::tryFromVariable($value) ?? throw new InvalidArgument((is_object($value) ? 'An instance of "'.$value::class.'"' : 'A value of type "'.gettype($value).'"').' can not be used as an HTTP structured field data type.');
}

public static function tryFromValue(mixed $value): self|null
public static function tryFromVariable(mixed $variable): self|null
{
return match (true) {
$value instanceof ValueAccess,
$value instanceof Token,
$value instanceof DisplayString,
$value instanceof ByteSequence => $value->type(),
$value instanceof DateTimeInterface => Type::Date,
is_int($value) => Type::Integer,
is_float($value) => Type::Decimal,
is_bool($value) => Type::Boolean,
is_string($value) => match (true) {
null !== Token::tryFromString($value) => Type::Token,
null !== ByteSequence::tryFromEncoded($value) => Type::ByteSequence,
1 === preg_match('/[^\x20-\x7f]/', $value) => Type::DisplayString,
$variable instanceof ValueAccess,
$variable instanceof Token,
$variable instanceof DisplayString,
$variable instanceof ByteSequence => $variable->type(),
$variable instanceof DateTimeInterface => Type::Date,
is_int($variable) => Type::Integer,
is_float($variable) => Type::Decimal,
is_bool($variable) => Type::Boolean,
is_string($variable) => match (true) {
null !== Token::tryFromString($variable) => Type::Token,
null !== ByteSequence::tryFromEncoded($variable) => Type::ByteSequence,
1 === preg_match('/[^\x20-\x7f]/', $variable) => Type::DisplayString,
default => Type::String,
},
default => null,
};
}

/**
* @deprecated since version 1.2.0 will be removed in the next major release.
* @see Type::fromVariable()
* @codeCoverageIgnore
*
* @throws InvalidArgument if the value can not be resolved into a supported HTTP structured field data type
*/
public static function fromValue(mixed $value): self
{
return self::fromVariable($value);
}

/**
* @deprecated since version 1.2.0 will be removed in the next major release.
* @see Type::tryFromVariable()
* @codeCoverageIgnore
*/
public static function tryFromValue(mixed $value): self|null
{
return self::tryFromVariable($value);
}
}
2 changes: 1 addition & 1 deletion src/Value.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public function __construct(ValueAccess|Token|ByteSequence|DisplayString|DateTim
is_float($value) => self::filterDecimal($value),
default => self::filterString($value),
};
$this->type = Type::fromValue($value);
$this->type = Type::fromVariable($value);
}

/**
Expand Down
8 changes: 4 additions & 4 deletions tests/TypeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ final class TypeTest extends TestCase
#[Test]
public function it_will_return_null_if_the_type_is_no_supported(): void
{
self::assertNull(Type::tryFromValue([]));
self::assertNull(Type::tryFromVariable([]));
}

#[Test]
public function it_will_return_true_if_the_type_is_valid_but_its_value_is_invalid(): void
{
self::assertTrue(Type::Integer->equals(Type::tryFromValue(1_000_000_000_000_000)));
self::assertTrue(Type::Integer->equals(Type::tryFromVariable(1_000_000_000_000_000)));
}

#[Test]
Expand All @@ -35,8 +35,8 @@ public function it_can_tell_the_item_type_from_a_value_instance(): void
#[DataProvider('itemTypeProvider')]
public function it_can_tell_the_item_type(mixed $value, Type $expectedType): void
{
self::assertTrue($expectedType->equals(Type::fromValue($value)));
self::assertTrue($expectedType->equals(Type::tryFromValue($value)));
self::assertTrue($expectedType->equals(Type::fromVariable($value)));
self::assertTrue($expectedType->equals(Type::tryFromVariable($value)));
}

/**
Expand Down

0 comments on commit 8f13d4f

Please sign in to comment.