Skip to content

Commit

Permalink
✨ Add unique key to conditional availability period (#160)
Browse files Browse the repository at this point in the history
- generate key by `now`, `startAt`, `endAt` & `fkConditionalAvailability`
- add database field `key` to `foi_conditional_availability`
- ...
  • Loading branch information
daniel-rose authored Dec 6, 2023
1 parent dc14ea2 commit 4c219e5
Show file tree
Hide file tree
Showing 8 changed files with 187 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
<transfer name="ConditionalAvailabilityPeriod">
<property name="idConditionalAvailabilityPeriod" type="int"/>
<property name="fkConditionalAvailability" type="int"/>
<property name="key" type="string" />
<property name="conditionalAvailability" type="ConditionalAvailability" />
<property name="quantity" type="int" />
<property name="createdAt" type="string" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace FondOfImpala\Zed\ConditionalAvailability\Business;

use FondOfImpala\Zed\ConditionalAvailability\Business\Generator\KeyGenerator;
use FondOfImpala\Zed\ConditionalAvailability\Business\Generator\KeyGeneratorInterface;
use FondOfImpala\Zed\ConditionalAvailability\Business\Model\ConditionalAvailabilityPeriodsPersister;
use FondOfImpala\Zed\ConditionalAvailability\Business\Model\ConditionalAvailabilityPeriodsPersisterInterface;
use FondOfImpala\Zed\ConditionalAvailability\Business\Model\ConditionalAvailabilityPluginExecutor;
Expand Down Expand Up @@ -64,7 +66,10 @@ public function createConditionalAvailabilityWriter(): ConditionalAvailabilityWr
*/
public function createConditionalAvailabilityPeriodsPersister(): ConditionalAvailabilityPeriodsPersisterInterface
{
return new ConditionalAvailabilityPeriodsPersister($this->getEntityManager());
return new ConditionalAvailabilityPeriodsPersister(
$this->createKeyGenerator(),
$this->getEntityManager(),
);
}

/**
Expand All @@ -86,4 +91,12 @@ protected function getConditionalAvailabilityPostSavePlugins(): array
ConditionalAvailabilityDependencyProvider::PLUGINS_CONDITIONAL_AVAILABILITY_POST_SAVE,
);
}

/**
* @return \FondOfImpala\Zed\ConditionalAvailability\Business\Generator\KeyGeneratorInterface
*/
protected function createKeyGenerator(): KeyGeneratorInterface
{
return new KeyGenerator();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

namespace FondOfImpala\Zed\ConditionalAvailability\Business\Generator;

use DateTime;
use Generated\Shared\Transfer\ConditionalAvailabilityPeriodTransfer;

class KeyGenerator implements KeyGeneratorInterface
{
/**
* @param \Generated\Shared\Transfer\ConditionalAvailabilityPeriodTransfer $conditionalAvailabilityPeriod
* @param \DateTime|null $dateTime
*
* @return string
*/
public function generate(
ConditionalAvailabilityPeriodTransfer $conditionalAvailabilityPeriod,
?DateTime $dateTime = null
): string {
$dateTime = $dateTime ?? new DateTime();

$keyParts = [
$conditionalAvailabilityPeriod->getFkConditionalAvailability(),
$conditionalAvailabilityPeriod->getStartAt(),
$conditionalAvailabilityPeriod->getEndAt(),
$dateTime->format('Y-m-d H:i:s.u'),
];

return sha1(implode(':', $keyParts));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace FondOfImpala\Zed\ConditionalAvailability\Business\Generator;

use DateTime;
use Generated\Shared\Transfer\ConditionalAvailabilityPeriodTransfer;

interface KeyGeneratorInterface
{
/**
* @param \Generated\Shared\Transfer\ConditionalAvailabilityPeriodTransfer $conditionalAvailabilityPeriod
* @param \DateTime|null $dateTime
*
* @return string
*/
public function generate(
ConditionalAvailabilityPeriodTransfer $conditionalAvailabilityPeriod,
?DateTime $dateTime = null
): string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,26 @@

namespace FondOfImpala\Zed\ConditionalAvailability\Business\Model;

use DateTime;
use FondOfImpala\Zed\ConditionalAvailability\Business\Generator\KeyGeneratorInterface;
use FondOfImpala\Zed\ConditionalAvailability\Persistence\ConditionalAvailabilityEntityManagerInterface;
use Generated\Shared\Transfer\ConditionalAvailabilityTransfer;

class ConditionalAvailabilityPeriodsPersister implements ConditionalAvailabilityPeriodsPersisterInterface
{
protected KeyGeneratorInterface $keyGenerator;

protected ConditionalAvailabilityEntityManagerInterface $entityManager;

/**
* @param \FondOfImpala\Zed\ConditionalAvailability\Business\Generator\KeyGeneratorInterface $keyGenerator
* @param \FondOfImpala\Zed\ConditionalAvailability\Persistence\ConditionalAvailabilityEntityManagerInterface $entityManager
*/
public function __construct(ConditionalAvailabilityEntityManagerInterface $entityManager)
{
public function __construct(
KeyGeneratorInterface $keyGenerator,
ConditionalAvailabilityEntityManagerInterface $entityManager
) {
$this->keyGenerator = $keyGenerator;
$this->entityManager = $entityManager;
}

Expand All @@ -40,10 +48,14 @@ public function persist(
->getConditionalAvailabilityPeriodCollection()
->getConditionalAvailabilityPeriods();

$now = new DateTime();

foreach ($conditionalAvailabilityPeriodTransfers as $conditionalAvailabilityPeriodTransfer) {
$conditionalAvailabilityPeriodTransfer->setFkConditionalAvailability(
$conditionalAvailabilityTransfer->getIdConditionalAvailability(),
);
$fkConditionalAvailability = $conditionalAvailabilityTransfer->getIdConditionalAvailability();
$key = $this->keyGenerator->generate($conditionalAvailabilityPeriodTransfer, $now);

$conditionalAvailabilityPeriodTransfer->setKey($key)
->setFkConditionalAvailability($fkConditionalAvailability);

$this->entityManager->createConditionalAvailabilityPeriod($conditionalAvailabilityPeriodTransfer);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,17 @@

<table name="foi_conditional_availability_period" phpName="FoiConditionalAvailabilityPeriod">
<column name="fk_conditional_availability" type="INTEGER" required="true" primaryKey="true"/>
<column name="key" size="255" type="VARCHAR"/>
<column name="start_at" required="true" type="TIMESTAMP" primaryKey="true"/>
<column name="end_at" required="true" type="TIMESTAMP" primaryKey="true"/>
<column name="original_start_at" type="TIMESTAMP"/>
<column name="quantity" type="INTEGER" required="true"/>
<column name="created_at" required="true" type="TIMESTAMP"/>

<!--<unique name="foi_conditional_availability_period-unique-key">
<unique-column name="key"/>
</unique>-->

<index name="index-foi_conditional_availability-fk_conditional_availability">
<index-column name="fk_conditional_availability"/>
</index>
Expand All @@ -60,6 +65,7 @@

<behavior name="event">
<parameter name="foi_conditional_availability_period_all" column="*"/>
<parameter name="foi_conditional_availability_period_key" column="key" keep-additional="true"/>
</behavior>
</table>
</database>
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?php

namespace FondOfImpala\Zed\ConditionalAvailability\Business\Generator;

use Codeception\Test\Unit;
use DateInterval;
use DateTime;
use Generated\Shared\Transfer\ConditionalAvailabilityPeriodTransfer;
use PHPUnit\Framework\MockObject\MockObject;

class KeyGeneratorTest extends Unit
{
protected ConditionalAvailabilityPeriodTransfer|MockObject $conditionalAvailabilityPeriodTransferMock;

protected KeyGenerator $keyGenerator;

/**
* @return void
*/
protected function _before(): void
{
parent::_before();

$this->conditionalAvailabilityPeriodTransferMock = $this->getMockBuilder(ConditionalAvailabilityPeriodTransfer::class)
->disableOriginalConstructor()
->getMock();

$this->keyGenerator = new KeyGenerator();
}

/**
* @return void
*/
public function testGenerate(): void
{
$idConditionalAvailability = 2;

$startAt = (new DateTime())->add(new DateInterval('P1D'))
->format('Y-m-d H:i:s.u');
$endAt = (new DateTime())->add(new DateInterval('P11D'))
->format('Y-m-d H:i:s.u');
$now = new DateTime();

$keyParts = [
$idConditionalAvailability,
$startAt,
$endAt,
$now->format('Y-m-d H:i:s.u'),
];

$key = sha1(implode(':', $keyParts));

$this->conditionalAvailabilityPeriodTransferMock->expects(static::atLeastOnce())
->method('getFkConditionalAvailability')
->willReturn($idConditionalAvailability);

$this->conditionalAvailabilityPeriodTransferMock->expects(static::atLeastOnce())
->method('getStartAt')
->willReturn($startAt);

$this->conditionalAvailabilityPeriodTransferMock->expects(static::atLeastOnce())
->method('getEndAt')
->willReturn($endAt);

static::assertEquals(
$key,
$this->keyGenerator->generate(
$this->conditionalAvailabilityPeriodTransferMock,
$now,
),
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,37 +3,29 @@
namespace FondOfImpala\Zed\ConditionalAvailability\Business\Model;

use Codeception\Test\Unit;
use FondOfImpala\Zed\ConditionalAvailability\Business\Generator\KeyGeneratorInterface;
use FondOfImpala\Zed\ConditionalAvailability\Persistence\ConditionalAvailabilityEntityManagerInterface;
use Generated\Shared\Transfer\ConditionalAvailabilityPeriodCollectionTransfer;
use Generated\Shared\Transfer\ConditionalAvailabilityPeriodTransfer;
use Generated\Shared\Transfer\ConditionalAvailabilityTransfer;
use PHPUnit\Framework\MockObject\MockObject;

class ConditionalAvailabilityPeriodsPersisterTest extends Unit
{
/**
* @var \PHPUnit\Framework\MockObject\MockObject|\FondOfImpala\Zed\ConditionalAvailability\Persistence\ConditionalAvailabilityEntityManagerInterface
*/
protected $conditionalAvailabilityEntityManagerMock;
protected MockObject|ConditionalAvailabilityEntityManagerInterface $conditionalAvailabilityEntityManagerMock;

/**
* @var \PHPUnit\Framework\MockObject\MockObject|\Generated\Shared\Transfer\ConditionalAvailabilityTransfer
*/
protected $conditionalAvailabilityTransferMock;
protected MockObject|KeyGeneratorInterface $keyGeneratorMock;

/**
* @var \PHPUnit\Framework\MockObject\MockObject|\Generated\Shared\Transfer\ConditionalAvailabilityPeriodCollectionTransfer
*/
protected $conditionalAvailabilityPeriodCollectionTransferMock;
protected MockObject|ConditionalAvailabilityTransfer $conditionalAvailabilityTransferMock;

protected MockObject|ConditionalAvailabilityPeriodCollectionTransfer $conditionalAvailabilityPeriodCollectionTransferMock;

/**
* @var array<\Generated\Shared\Transfer\ConditionalAvailabilityPeriodTransfer>|array<\PHPUnit\Framework\MockObject\MockObject>
*/
protected $conditionalAvailabilityPeriodTransferMocks;
protected array $conditionalAvailabilityPeriodTransferMocks;

/**
* @var \FondOfImpala\Zed\ConditionalAvailability\Business\Model\ConditionalAvailabilityPeriodsPersister
*/
protected $conditionalAvailabilityPeriodsPersister;
protected ConditionalAvailabilityPeriodsPersister $conditionalAvailabilityPeriodsPersister;

/**
* @return void
Expand All @@ -56,11 +48,16 @@ protected function _before(): void
->getMock(),
];

$this->keyGeneratorMock = $this->getMockBuilder(KeyGeneratorInterface::class)
->disableOriginalConstructor()
->getMock();

$this->conditionalAvailabilityEntityManagerMock = $this->getMockBuilder(ConditionalAvailabilityEntityManagerInterface::class)
->disableOriginalConstructor()
->getMock();

$this->conditionalAvailabilityPeriodsPersister = new ConditionalAvailabilityPeriodsPersister(
$this->keyGeneratorMock,
$this->conditionalAvailabilityEntityManagerMock,
);
}
Expand Down Expand Up @@ -104,6 +101,7 @@ public function testPersistWithoutConditionalAvailabilityPeriodCollection(): voi
*/
public function testPersist(): void
{
$key = sha1('foo');
$idConditionalAvailability = 1;

$this->conditionalAvailabilityTransferMock->expects(static::atLeastOnce())
Expand All @@ -122,11 +120,21 @@ public function testPersist(): void
->method('getConditionalAvailabilityPeriods')
->willReturn($this->conditionalAvailabilityPeriodTransferMocks);

$this->keyGeneratorMock->expects(static::atLeastOnce())
->method('generate')
->with($this->conditionalAvailabilityPeriodTransferMocks[0], static::callback(static fn (): bool => true))
->willReturn($key);

$this->conditionalAvailabilityPeriodTransferMocks[0]->expects(static::atLeastOnce())
->method('setFkConditionalAvailability')
->with($idConditionalAvailability)
->willReturn($this->conditionalAvailabilityPeriodTransferMocks[0]);

$this->conditionalAvailabilityPeriodTransferMocks[0]->expects(static::atLeastOnce())
->method('setKey')
->with($key)
->willReturn($this->conditionalAvailabilityPeriodTransferMocks[0]);

$this->conditionalAvailabilityEntityManagerMock->expects(static::atLeastOnce())
->method('createConditionalAvailabilityPeriod')
->with($this->conditionalAvailabilityPeriodTransferMocks[0]);
Expand Down

0 comments on commit 4c219e5

Please sign in to comment.