Skip to content

Commit

Permalink
[#17] Add StrategyWasAdded event
Browse files Browse the repository at this point in the history
  • Loading branch information
kpicaza committed Nov 4, 2021
1 parent 205ba73 commit 3b996c4
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 28 deletions.
85 changes: 85 additions & 0 deletions src/Write/Event/StrategyWasAdded.php
@@ -0,0 +1,85 @@
<?php

declare(strict_types=1);

namespace Pheature\Core\Toggle\Write\Event;

use Pheature\Core\Toggle\Write\FeatureId;
use DatetimeImmutable;
use Pheature\Core\Toggle\Write\Payload;
use Pheature\Core\Toggle\Write\Segment;
use Pheature\Core\Toggle\Write\SegmentId;
use Pheature\Core\Toggle\Write\SegmentType;
use Pheature\Core\Toggle\Write\StrategyId;
use Pheature\Core\Toggle\Write\StrategyType;

/**
* @phpstan-import-type WriteSegment from Segment
*/
final class StrategyWasAdded
{
private string $featureId;
private DatetimeImmutable $occurredAt;
private string $strategyId;
private string $strategyType;
/** @var WriteSegment[] */
private array $segments;

/** @param WriteSegment[] $segments */
public function __construct(
string $featureId,
string $strategyId,
string $strategyType,
array $segments,
DatetimeImmutable $occurredAt
) {
$this->featureId = $featureId;
$this->strategyId = $strategyId;
$this->strategyType = $strategyType;
$this->segments = $segments;
$this->occurredAt = $occurredAt;
}

/** @param WriteSegment[] $segments */
public static function occur(string $featureId, string $strategyId, string $strategyType, array $segments): self
{
return new self($featureId, $strategyId, $strategyType, $segments, new DatetimeImmutable());
}

public function featureId(): FeatureId
{
return FeatureId::fromString($this->featureId);
}

public function strategyId(): StrategyId
{
return StrategyId::fromString($this->strategyId);
}

public function strategyType(): StrategyType
{
return StrategyType::fromString($this->strategyType);
}

public function occurredAt(): DatetimeImmutable
{
return $this->occurredAt;
}

/**
* @return Segment[]
*/
public function segments(): array
{
return array_map(
static function (array $segment): Segment {
return new Segment(
SegmentId::fromString($segment['segment_id']),
SegmentType::fromString($segment['segment_type']),
Payload::fromArray($segment['criteria'])
);
},
$this->segments
);
}
}
7 changes: 7 additions & 0 deletions src/Write/Feature.php
Expand Up @@ -9,6 +9,7 @@
use Pheature\Core\Toggle\Write\Event\FeatureWasCreated;
use JsonSerializable;
use Pheature\Core\Toggle\Write\Event\FeatureWasRemoved;
use Pheature\Core\Toggle\Write\Event\StrategyWasAdded;

use function array_map;
use function array_values;
Expand Down Expand Up @@ -60,6 +61,12 @@ public static function withId(FeatureId $featureId): self
public function setStrategy(Strategy $strategy): void
{
$this->strategies[$strategy->id()->value()] = $strategy;
$this->events[] = StrategyWasAdded::occur(
$this->featureId->value(),
$strategy->id()->value(),
$strategy->type()->value(),
array_map(static fn(Segment $segment) => $segment->jsonSerialize(), $strategy->segments())
);
}

public function removeStrategy(StrategyId $strategyId): void
Expand Down
21 changes: 5 additions & 16 deletions src/Write/Payload.php
Expand Up @@ -8,41 +8,30 @@

final class Payload
{
/**
* @var array<string, mixed>
*/
/** @var array<array-key, mixed> */
private array $criteria;

/**
* @param array<string, mixed> $criteria
*/
/** @param array<array-key, mixed> $criteria */
private function __construct(array $criteria)
{
$this->criteria = $criteria;
}

/**
* @param array<string, mixed> $criteria
* @return static
*/
/** @param array<array-key, mixed> $criteria */
public static function fromArray(array $criteria): self
{
return new self($criteria);
}

public static function fromJsonString(string $jsonPayload): self
{
/**
* @var array<string, mixed> $payload
*/
/** @var array<array-key, mixed> $payload */
$payload = json_decode($jsonPayload, true, 16, JSON_THROW_ON_ERROR);

return self::fromArray($payload);
}

/**
* @return array<string, mixed>
*/
/** @return array<array-key, mixed> */
public function criteria(): array
{
return $this->criteria;
Expand Down
6 changes: 5 additions & 1 deletion src/Write/Segment.php
Expand Up @@ -6,6 +6,10 @@

use JsonSerializable;

/**
* @phpstan-type WriteSegment array{segment_id: string, segment_type: string, criteria: array<array-key, mixed>}
* @psalm-type WriteSegment array{segment_id: string, segment_type: string, criteria: array<array-key, mixed>}
*/
final class Segment implements JsonSerializable
{
private SegmentId $segmentId;
Expand Down Expand Up @@ -35,7 +39,7 @@ public function payload(): Payload
}

/**
* @return array<string, string|array<string, mixed>>
* @return WriteSegment
*/
public function jsonSerialize(): array
{
Expand Down
15 changes: 6 additions & 9 deletions src/Write/Strategy.php
Expand Up @@ -8,6 +8,11 @@

use function array_map;

/**
* @phpstan-import-type WriteSegment from Segment
* @phpstan-type WriteStrategy array{strategy_id: string, strategy_type: string, segments: WriteSegment[]}
* @psalm-type WriteStrategy array{strategy_id: string, strategy_type: string, segments: WriteSegment[]}
*/
final class Strategy implements JsonSerializable
{
private StrategyId $strategyId;
Expand Down Expand Up @@ -49,15 +54,7 @@ public function segments(): array
return $this->segments;
}

/**
* @phpstan-return array<string, mixed>
* @phpstan-ignore-next-line
* @return array{
* strategy_id: string,
* strategy_type: string
* segments: array<array-key, array<string, array<string, mixed>|string>>,
* }
*/
/** @return WriteStrategy */
public function jsonSerialize(): array
{
return [
Expand Down
30 changes: 28 additions & 2 deletions test/Write/FeatureTest.php
Expand Up @@ -7,8 +7,13 @@
use Pheature\Core\Toggle\Write\Event\FeatureWasDisabled;
use Pheature\Core\Toggle\Write\Event\FeatureWasEnabled;
use Pheature\Core\Toggle\Write\Event\FeatureWasRemoved;
use Pheature\Core\Toggle\Write\Event\StrategyWasAdded;
use Pheature\Core\Toggle\Write\Feature;
use Pheature\Core\Toggle\Write\FeatureId;
use Pheature\Core\Toggle\Write\Payload;
use Pheature\Core\Toggle\Write\Segment;
use Pheature\Core\Toggle\Write\SegmentId;
use Pheature\Core\Toggle\Write\SegmentType;
use Pheature\Core\Toggle\Write\Strategy;
use Pheature\Core\Toggle\Write\StrategyId;
use Pheature\Core\Toggle\Write\StrategyType;
Expand All @@ -21,6 +26,8 @@ final class FeatureTest extends TestCase
private const FEATURE_ID = 'some_feature';
private const STRATEGY_ID = 'some_strategy';
private const STRATEGY_TYPE = 'some_strategy_type';
private const SEGMENT_ID = 'some_segment';
private const SEGMENT_TYPE = 'some_segment_type';

public function testItShouldBeCreatedWithId(): void
{
Expand Down Expand Up @@ -86,14 +93,33 @@ public function testItShouldSetAnStrategy(): void
$strategy = new Strategy(
StrategyId::fromString(self::STRATEGY_ID),
StrategyType::fromString(self::STRATEGY_TYPE),
[]
[
new Segment(
SegmentId::fromString(self::SEGMENT_ID),
SegmentType::fromString(self::SEGMENT_TYPE),
Payload::fromArray(['foo' => 'bar'])
)
]
);
$feature = $this->createFeature();
$feature->setStrategy($strategy);
$this->assertCount(1, $feature->strategies());

$events = $feature->release();
$this->assertCount(0, $events);
$this->assertCount(1, $events);
$this->assertEventIsRecorded(StrategyWasAdded::class, $events);

/** @var StrategyWasAdded $strategyWasAdded */
$strategyWasAdded = $events[0];
$this->assertSame(self::FEATURE_ID, $strategyWasAdded->featureId()->value());
$this->assertSame(self::STRATEGY_ID, $strategyWasAdded->strategyId()->value());
$this->assertSame(self::STRATEGY_TYPE, $strategyWasAdded->strategyType()->value());
/** @var Segment $segment */
$segment = $strategyWasAdded->segments()[0];
$this->assertSame(self::SEGMENT_ID, $segment->segmentId()->value());
$this->assertSame(self::SEGMENT_TYPE, $segment->segmentType()->value());
$this->assertSame(['foo' => 'bar'], $segment->payload()->criteria());
$this->assertInstanceOf(DatetimeImmutable::class, $strategyWasAdded->occurredAt());
}

public function testItShouldRemoveAnStrategies(): void
Expand Down

0 comments on commit 3b996c4

Please sign in to comment.