Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions UPGRADE-2.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,19 @@ The context is now also passed on to nested objects. In 1.x, `$event->getPayload
still serialized the user data in the server context. `FbqGenerator` was not affected, since it asks the user data and
the custom data directly.

## Stricter types on `User`, `Fb` and `Fbp`

- **`Fbp::$randomNumber` is private.** It was the only public, mutable property on the otherwise immutable cookie value
objects. Use `getRandomNumber()` and `withRandomNumber()`.
- **`User::$fbc` and `User::$fbp` are natively typed**, as `Fbc|string|null` and `Fbp|string|null`. They were untyped, so
anything could be assigned. Assigning something else now throws a `\TypeError`.
- **`Fb::withCreationTime()` takes `int|\DateTimeInterface` natively.** Passing anything else throws a `\TypeError`. It
used to throw an `InvalidArgumentException`.
- `withSubdomainIndex()`, `withCreationTime()` and `withAppendix()` declare `static` as their return type. They already
returned the concrete class; this only matters if you extend `Fb` yourself and override them.

A `\TypeError` is PHP's own error for a programming mistake and does not implement `ExceptionInterface`.

## `FbqGenerator::generateTrack()` no longer throws a `\JsonException`

When the custom data cannot be encoded as JSON, it now logs an error and returns an empty string, which is what
Expand Down
6 changes: 2 additions & 4 deletions src/Event/Parameters.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,17 +50,15 @@
*
* @return list<string>
*/
protected static function getHashedFields(): array

Check warning on line 53 in src/Event/Parameters.php

View workflow job for this annotation

GitHub Actions / Mutation tests (8.3, highest)

Escaped Mutant for Mutator "ProtectedVisibility": @@ @@ * * @return list<string> */ - protected static function getHashedFields(): array + private static function getHashedFields(): array { return []; }
{
return [];
}

/**
* @param mixed $data
*
* @return array<array-key, mixed>|string|float|int|bool|null
*/
private static function normalize($data, PayloadContext $context, ?string $field = null)
private static function normalize(mixed $data, PayloadContext $context, ?string $field = null): array|string|float|int|bool|null
{
if (null === $data) {
return null;
Expand All @@ -75,7 +73,7 @@
}

if (is_string($data)) {
Assert::notNull($field);

Check warning on line 76 in src/Event/Parameters.php

View workflow job for this annotation

GitHub Actions / Mutation tests (8.3, highest)

Escaped Mutant for Mutator "MethodCallRemoval": @@ @@ $data = (string) $data; } if (is_string($data)) { - Assert::notNull($field); + if (in_array($field, static::getNormalizedFields(), true)) { try { $data = Normalizer::normalize($field, $data);
if (in_array($field, static::getNormalizedFields(), true)) {
try {
$data = Normalizer::normalize($field, $data);
Expand All @@ -95,7 +93,7 @@
return $data;
}

Assert::isArray($data);

Check warning on line 96 in src/Event/Parameters.php

View workflow job for this annotation

GitHub Actions / Mutation tests (8.3, highest)

Escaped Mutant for Mutator "MethodCallRemoval": @@ @@ if (is_int($data) || is_float($data) || is_bool($data)) { return $data; } - Assert::isArray($data); + /** @var mixed $datum */ foreach ($data as $key => &$datum) { if ($datum instanceof self) {

/** @var mixed $datum */
foreach ($data as $key => &$datum) {
Expand All @@ -121,7 +119,7 @@
*/
private static function filterEmptyValues(array $data): array
{
return array_filter($data, static function ($value): bool {
return array_filter($data, static function (mixed $value): bool {
return !(null === $value || '' === $value || [] === $value);
});
}
Expand Down
6 changes: 2 additions & 4 deletions src/Event/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,9 @@ final class User extends Parameters

public ?string $clientUserAgent = null;

/** @var string|Fbc|null */
public $fbc;
public Fbc|string|null $fbc = null;

/** @var string|Fbp|null */
public $fbp;
public Fbp|string|null $fbp = null;

public ?string $subscriptionId = null;

Expand Down
18 changes: 3 additions & 15 deletions src/ValueObject/Fb.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@

public function __construct()
{
$this->creationTime = (int) ceil(microtime(true) * 1000);

Check warning on line 48 in src/ValueObject/Fb.php

View workflow job for this annotation

GitHub Actions / Mutation tests (8.3, highest)

Escaped Mutant for Mutator "RoundingFamily": @@ @@ private ?string $appendix = null; public function __construct() { - $this->creationTime = (int) ceil(microtime(true) * 1000); + $this->creationTime = (int) round(microtime(true) * 1000); } /** * @throws InvalidArgumentException if the $value is not the correct format

Check warning on line 48 in src/ValueObject/Fb.php

View workflow job for this annotation

GitHub Actions / Mutation tests (8.3, highest)

Escaped Mutant for Mutator "RoundingFamily": @@ @@ private ?string $appendix = null; public function __construct() { - $this->creationTime = (int) ceil(microtime(true) * 1000); + $this->creationTime = (int) floor(microtime(true) * 1000); } /** * @throws InvalidArgumentException if the $value is not the correct format
}

/**
Expand All @@ -60,10 +60,7 @@
return $this->subdomainIndex;
}

/**
* @return static
*/
public function withSubdomainIndex(int $subdomainIndex): self
public function withSubdomainIndex(int $subdomainIndex): static
{
Assert::greaterThanEq($subdomainIndex, 0);

Expand All @@ -78,20 +75,14 @@
return $this->creationTime;
}

/**
* @param int|\DateTimeInterface $creationTime
*
* @return static
*/
public function withCreationTime($creationTime): self
public function withCreationTime(int|\DateTimeInterface $creationTime): static
{
if ($creationTime instanceof \DateTimeInterface) {
$creationTime = (int) $creationTime->format('Uv');
}

Assert::integer($creationTime);
Assert::greaterThanEq($creationTime, 1_075_590_000_000); // Facebooks founding date xD
Assert::lessThanEq($creationTime, (time() + 1) * 1000);

Check warning on line 85 in src/ValueObject/Fb.php

View workflow job for this annotation

GitHub Actions / Mutation tests (8.3, highest)

Escaped Mutant for Mutator "IncrementInteger": @@ @@ } Assert::greaterThanEq($creationTime, 1075590000000); // Facebooks founding date xD - Assert::lessThanEq($creationTime, (time() + 1) * 1000); + Assert::lessThanEq($creationTime, (time() + 2) * 1000); $obj = clone $this; $obj->creationTime = $creationTime; return $obj;

$obj = clone $this;
$obj->creationTime = $creationTime;
Expand All @@ -102,7 +93,7 @@
public function getCreationTimeAsDateTime(): \DateTimeImmutable
{
$dateTime = \DateTimeImmutable::createFromFormat('U.v', (string) ($this->creationTime / 1000));
Assert::notFalse($dateTime);

Check warning on line 96 in src/ValueObject/Fb.php

View workflow job for this annotation

GitHub Actions / Mutation tests (8.3, highest)

Escaped Mutant for Mutator "MethodCallRemoval": @@ @@ public function getCreationTimeAsDateTime(): \DateTimeImmutable { $dateTime = \DateTimeImmutable::createFromFormat('U.v', (string) ($this->creationTime / 1000)); - Assert::notFalse($dateTime); + return $dateTime; } public function getAppendix(): ?string

return $dateTime;
}
Expand All @@ -112,10 +103,7 @@
return $this->appendix;
}

/**
* @return static
*/
public function withAppendix(?string $appendix): self
public function withAppendix(?string $appendix): static
{
if (null !== $appendix) {
Assert::regex($appendix, self::REGEXP_APPENDIX);
Expand Down
2 changes: 1 addition & 1 deletion src/ValueObject/Fbp.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
*/
final class Fbp extends Fb
{
public int $randomNumber;
private int $randomNumber;

public function __construct()
{
Expand Down
21 changes: 21 additions & 0 deletions tests/Event/UserTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
namespace Setono\MetaConversionsApi\Event;

use PHPUnit\Framework\TestCase;
use Setono\MetaConversionsApi\ValueObject\Fbc;
use Setono\MetaConversionsApi\ValueObject\Fbp;

/**
* @covers \Setono\MetaConversionsApi\Event\User
Expand All @@ -23,4 +25,23 @@ public function it_normalizes(): void
'em' => ['55e79200c1635b37ad31a378c39feb12f120f116625093a19bc32fff15041149'],
], $user->getPayload());
}

/**
* @test
*/
public function it_accepts_the_cookies_as_value_objects_and_as_strings(): void
{
$user = new User();
self::assertNull($user->fbc);
self::assertNull($user->fbp);
self::assertSame([], $user->getPayload());

$user->fbc = Fbc::fromString('fb.1.1657051589577.ClickId');
$user->fbp = Fbp::fromString('fb.1.1656874832584.1088522659');
self::assertSame(['fbc' => 'fb.1.1657051589577.ClickId', 'fbp' => 'fb.1.1656874832584.1088522659'], $user->getPayload());

$user->fbc = 'fb.1.1657051589577.OtherClickId';
$user->fbp = 'fb.1.1656874832584.1234567890';
self::assertSame(['fbc' => 'fb.1.1657051589577.OtherClickId', 'fbp' => 'fb.1.1656874832584.1234567890'], $user->getPayload());
}
}
10 changes: 0 additions & 10 deletions tests/ValueObject/FbTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -124,16 +124,6 @@ public static function creationTimesOutOfRange(): \Generator
yield 'in the future' => [(time() + 60) * 1000];
}

/**
* @test
*/
public function it_rejects_a_creation_time_that_is_neither_an_integer_nor_a_datetime(): void
{
$this->expectException(InvalidArgumentException::class);

(new Fbp())->withCreationTime('1656874832584'); // @phpstan-ignore argument.type
}

/**
* @test
*/
Expand Down
Loading