diff --git a/composer.json b/composer.json
index 69b51702..1ec26243 100644
--- a/composer.json
+++ b/composer.json
@@ -12,6 +12,7 @@
"spryker/propel": "^3.45.0",
"spryker/propel-orm": "^1.16.0",
"spryker/symfony": "^3.1.0",
+ "spryker/transfer": "^3.39.0",
"spryker/util-encoding": "^2.1.0"
},
"require-dev": {
@@ -28,8 +29,7 @@
"spryker/monolog": "*",
"spryker/queue": "*",
"spryker/silex": "^2.0.0",
- "spryker/testify": "^3.58.0",
- "spryker/transfer": "^3.39.0"
+ "spryker/testify": "^3.58.0"
},
"suggest": {
"spryker/console": "If you want to execute console commands",
diff --git a/dependency.json b/dependency.json
index 38f65ca2..3ceee424 100644
--- a/dependency.json
+++ b/dependency.json
@@ -1,4 +1,7 @@
{
+ "include": {
+ "spryker/transfer": "Provides transfer objects definition with `::get*OrFail()` functionality."
+ },
"include-dev": {
"codeception/module-asserts": "Codeception module containing various assertions.",
"phpunit/phpunit": "Need due to compatibility minimal version package with PHP 8."
diff --git a/src/Spryker/Shared/EventBehavior/Transfer/event_behavior.transfer.xml b/src/Spryker/Shared/EventBehavior/Transfer/event_behavior.transfer.xml
index 88db82b8..90472812 100644
--- a/src/Spryker/Shared/EventBehavior/Transfer/event_behavior.transfer.xml
+++ b/src/Spryker/Shared/EventBehavior/Transfer/event_behavior.transfer.xml
@@ -3,10 +3,23 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="spryker:transfer-01 http://static.spryker.com/transfer-01.xsd">
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Spryker/Zed/EventBehavior/Business/EventBehaviorFacade.php b/src/Spryker/Zed/EventBehavior/Business/EventBehaviorFacade.php
index 59195554..c5ca6ed7 100644
--- a/src/Spryker/Zed/EventBehavior/Business/EventBehaviorFacade.php
+++ b/src/Spryker/Zed/EventBehavior/Business/EventBehaviorFacade.php
@@ -8,6 +8,8 @@
namespace Spryker\Zed\EventBehavior\Business;
use Generated\Shared\Transfer\EventTriggerResponseTransfer;
+use Generated\Shared\Transfer\HydrateEventsRequestTransfer;
+use Generated\Shared\Transfer\HydrateEventsResponseTransfer;
use Spryker\Zed\Kernel\Business\AbstractFacade;
/**
@@ -126,6 +128,20 @@ public function getEventTransfersAdditionalValues(array $eventTransfers, string
return $this->getFactory()->createEventEntityTransferFilter()->getEventTransfersAdditionalValues($eventTransfers, $columnName);
}
+ /**
+ * {@inheritDoc}
+ *
+ * @api
+ *
+ * @param \Generated\Shared\Transfer\HydrateEventsRequestTransfer $hydrateEventsRequestTransfer
+ *
+ * @return \Generated\Shared\Transfer\HydrateEventsResponseTransfer
+ */
+ public function hydrateEventDataTransfer(HydrateEventsRequestTransfer $hydrateEventsRequestTransfer): HydrateEventsResponseTransfer
+ {
+ return $this->getFactory()->createEventEntityTransferFilter()->hydrateEventDataTransfer($hydrateEventsRequestTransfer);
+ }
+
/**
* {@inheritDoc}
*
diff --git a/src/Spryker/Zed/EventBehavior/Business/EventBehaviorFacadeInterface.php b/src/Spryker/Zed/EventBehavior/Business/EventBehaviorFacadeInterface.php
index 5e6b65e2..c9300da7 100644
--- a/src/Spryker/Zed/EventBehavior/Business/EventBehaviorFacadeInterface.php
+++ b/src/Spryker/Zed/EventBehavior/Business/EventBehaviorFacadeInterface.php
@@ -8,6 +8,8 @@
namespace Spryker\Zed\EventBehavior\Business;
use Generated\Shared\Transfer\EventTriggerResponseTransfer;
+use Generated\Shared\Transfer\HydrateEventsRequestTransfer;
+use Generated\Shared\Transfer\HydrateEventsResponseTransfer;
interface EventBehaviorFacadeInterface
{
@@ -101,7 +103,7 @@ public function getEventTransfersOriginalValues(array $eventTransfers, string $c
/**
* Specification:
- * - Returns field value of the specficed column in eventTransfers.
+ * - Returns field value of the specified column in eventTransfers.
*
* @api
*
@@ -112,6 +114,26 @@ public function getEventTransfersOriginalValues(array $eventTransfers, string $c
*/
public function getEventTransfersAdditionalValues(array $eventTransfers, string $columnName): array;
+ /**
+ * Specification:
+ * - Extracts timestamp information for event entities passed in the request.
+ * - Always returns a map of entity IDs to their respective timestamps.
+ * - Optionally extracts additional values with timestamps for:
+ * - Foreign key values if `foreignKeyName` is provided.
+ * - Additional values if `additionalValueName` is provided.
+ * - Response structure (in HydrateEventsResponseTransfer):
+ * - `idTimestampMap`: [id => timestamp]
+ * - `foreignKeyTimestampMap`: [foreignKeyValue => timestamp] (if requested)
+ * - `additionalValueTimestampMap`: [additionalValue => timestamp] (if requested)
+ *
+ * @api
+ *
+ * @param \Generated\Shared\Transfer\HydrateEventsRequestTransfer $hydrateEventsRequestTransfer
+ *
+ * @return \Generated\Shared\Transfer\HydrateEventsResponseTransfer
+ */
+ public function hydrateEventDataTransfer(HydrateEventsRequestTransfer $hydrateEventsRequestTransfer): HydrateEventsResponseTransfer;
+
/**
* Specification:
* - Triggers events for specified resources.
diff --git a/src/Spryker/Zed/EventBehavior/Business/Model/EventEntityTransferFilter.php b/src/Spryker/Zed/EventBehavior/Business/Model/EventEntityTransferFilter.php
index a45661f4..1f094b8a 100644
--- a/src/Spryker/Zed/EventBehavior/Business/Model/EventEntityTransferFilter.php
+++ b/src/Spryker/Zed/EventBehavior/Business/Model/EventEntityTransferFilter.php
@@ -7,6 +7,10 @@
namespace Spryker\Zed\EventBehavior\Business\Model;
+use Generated\Shared\Transfer\EventEntityTransfer;
+use Generated\Shared\Transfer\HydrateEventsRequestTransfer;
+use Generated\Shared\Transfer\HydrateEventsResponseTransfer;
+
class EventEntityTransferFilter implements EventEntityTransferFilterInterface
{
/**
@@ -145,6 +149,93 @@ public function getEventTransfersAdditionalValues(array $eventTransfers, string
return array_unique($additionalValues);
}
+ /**
+ * @param \Generated\Shared\Transfer\HydrateEventsRequestTransfer $hydrateEventsRequestTransfer
+ *
+ * @return \Generated\Shared\Transfer\HydrateEventsResponseTransfer
+ */
+ public function hydrateEventDataTransfer(HydrateEventsRequestTransfer $hydrateEventsRequestTransfer): HydrateEventsResponseTransfer
+ {
+ $hydrateEventsResponseTransfer = new HydrateEventsResponseTransfer();
+ $eventEntityTransfers = $hydrateEventsRequestTransfer->getEventEntities()->getArrayCopy();
+
+ if (count($eventEntityTransfers) === 0) {
+ return $hydrateEventsResponseTransfer;
+ }
+ usort($eventEntityTransfers, fn (EventEntityTransfer $a, EventEntityTransfer $b) => $a->getTimestamp() <=> $b->getTimestamp());
+
+ $hydrateEventsResponseTransfer->setIdTimestampMap($this->getIdsTimestampMap($eventEntityTransfers));
+
+ if ($hydrateEventsRequestTransfer->getAdditionalValueName()) {
+ $hydrateEventsResponseTransfer->setAdditionalValueTimestampMap($this->getAdditionalValueTimestampMap($eventEntityTransfers, $hydrateEventsRequestTransfer->getAdditionalValueName()));
+ }
+
+ if ($hydrateEventsRequestTransfer->getForeignKeyName()) {
+ $hydrateEventsResponseTransfer->setForeignKeyTimestampMap($this->getForeignKeyTimestampMap($eventEntityTransfers, $hydrateEventsRequestTransfer->getForeignKeyName()));
+ }
+
+ return $hydrateEventsResponseTransfer;
+ }
+
+ /**
+ * @param array<\Generated\Shared\Transfer\EventEntityTransfer> $eventTransfers
+ *
+ * @return array
+ */
+ protected function getIdsTimestampMap(array $eventTransfers): array
+ {
+ $ids = [];
+ foreach ($eventTransfers as $eventTransfer) {
+ $ids[(int)$eventTransfer->getId()] = (int)$eventTransfer->getTimestamp();
+ }
+
+ return $ids;
+ }
+
+ /**
+ * @param array<\Generated\Shared\Transfer\EventEntityTransfer> $eventTransfers
+ * @param string $columnName
+ *
+ * @return array
+ */
+ protected function getAdditionalValueTimestampMap(array $eventTransfers, string $columnName): array
+ {
+ $additionalValues = [];
+ foreach ($eventTransfers as $eventTransfer) {
+ $additionalValuesOfEvent = $eventTransfer->getAdditionalValues();
+ if (!isset($additionalValuesOfEvent[$columnName])) {
+ continue;
+ }
+
+ $additionalValues[$additionalValuesOfEvent[$columnName]] = (int)$eventTransfer->getTimestamp();
+ }
+
+ return $additionalValues;
+ }
+
+ /**
+ * @param array<\Generated\Shared\Transfer\EventEntityTransfer> $eventTransfers
+ * @param string $foreignKeyColumnName
+ *
+ * @return array
+ */
+ protected function getForeignKeyTimestampMap(array $eventTransfers, string $foreignKeyColumnName): array
+ {
+ $foreignKeys = [];
+ foreach ($eventTransfers as $eventTransfer) {
+ if (!isset($eventTransfer->getForeignKeys()[$foreignKeyColumnName])) {
+ continue;
+ }
+
+ $value = $eventTransfer->getForeignKeys()[$foreignKeyColumnName] ?? null;
+ if ($value !== null) {
+ $foreignKeys[(int)$value] = (int)$eventTransfer->getTimestamp();
+ }
+ }
+
+ return $foreignKeys;
+ }
+
/**
* @param array $columns
* @param array $modifiedColumns
diff --git a/src/Spryker/Zed/EventBehavior/Business/Model/EventEntityTransferFilterInterface.php b/src/Spryker/Zed/EventBehavior/Business/Model/EventEntityTransferFilterInterface.php
index dc8c3a02..ba6f3ed8 100644
--- a/src/Spryker/Zed/EventBehavior/Business/Model/EventEntityTransferFilterInterface.php
+++ b/src/Spryker/Zed/EventBehavior/Business/Model/EventEntityTransferFilterInterface.php
@@ -7,6 +7,9 @@
namespace Spryker\Zed\EventBehavior\Business\Model;
+use Generated\Shared\Transfer\HydrateEventsRequestTransfer;
+use Generated\Shared\Transfer\HydrateEventsResponseTransfer;
+
interface EventEntityTransferFilterInterface
{
/**
@@ -55,4 +58,11 @@ public function getEventTransfersOriginalValues(array $eventTransfers, string $c
* @return array
*/
public function getEventTransfersAdditionalValues(array $eventTransfers, string $columnName): array;
+
+ /**
+ * @param \Generated\Shared\Transfer\HydrateEventsRequestTransfer $hydrateEventsRequestTransfer
+ *
+ * @return \Generated\Shared\Transfer\HydrateEventsResponseTransfer
+ */
+ public function hydrateEventDataTransfer(HydrateEventsRequestTransfer $hydrateEventsRequestTransfer): HydrateEventsResponseTransfer;
}
diff --git a/src/Spryker/Zed/EventBehavior/Business/Model/EventResourceQueryContainerManager.php b/src/Spryker/Zed/EventBehavior/Business/Model/EventResourceQueryContainerManager.php
index dc4302ab..615a6f22 100644
--- a/src/Spryker/Zed/EventBehavior/Business/Model/EventResourceQueryContainerManager.php
+++ b/src/Spryker/Zed/EventBehavior/Business/Model/EventResourceQueryContainerManager.php
@@ -118,7 +118,9 @@ protected function createEventResourceQueryContainerPluginIterator(EventResource
protected function triggerBulk(EventResourceQueryContainerPluginInterface $plugin, array $ids): void
{
$eventEntityTransfers = array_map(function ($id) {
- return (new EventEntityTransfer())->setId($id);
+ return (new EventEntityTransfer())
+ ->setId($id)
+ ->setTimestamp(time());
}, $ids);
$this->eventFacade->triggerBulk($plugin->getEventName(), $eventEntityTransfers);
diff --git a/src/Spryker/Zed/EventBehavior/Business/Model/EventResourceRepositoryManager.php b/src/Spryker/Zed/EventBehavior/Business/Model/EventResourceRepositoryManager.php
index 209f6e83..11b40baa 100644
--- a/src/Spryker/Zed/EventBehavior/Business/Model/EventResourceRepositoryManager.php
+++ b/src/Spryker/Zed/EventBehavior/Business/Model/EventResourceRepositoryManager.php
@@ -204,7 +204,9 @@ protected function getIdColumnName($plugin): ?string
protected function triggerBulk(EventResourcePluginInterface $plugin, array $ids): void
{
$eventEntityTransfers = array_map(function ($id) {
- return (new EventEntityTransfer())->setId($id);
+ return (new EventEntityTransfer())
+ ->setId($id)
+ ->setTimestamp(time());
}, $ids);
$this->eventFacade->triggerBulk($plugin->getEventName(), $eventEntityTransfers);
diff --git a/src/Spryker/Zed/EventBehavior/Business/Model/TriggerManager.php b/src/Spryker/Zed/EventBehavior/Business/Model/TriggerManager.php
index e46e45a6..d3ea936d 100644
--- a/src/Spryker/Zed/EventBehavior/Business/Model/TriggerManager.php
+++ b/src/Spryker/Zed/EventBehavior/Business/Model/TriggerManager.php
@@ -285,6 +285,7 @@ protected function triggerEvents(array $events): int
$eventEntityTransfer->setEvent($data[EventBehavior::EVENT_CHANGE_NAME]);
$eventEntityTransfer->setName($data[EventBehavior::EVENT_CHANGE_ENTITY_NAME]);
$eventEntityTransfer->setId($id);
+ $eventEntityTransfer->setTimestamp($event->getCreatedAt()?->getTimestamp());
$eventEntityTransfer->setForeignKeys($data[EventBehavior::EVENT_CHANGE_ENTITY_FOREIGN_KEYS]);
if (isset($data[EventBehavior::EVENT_CHANGE_ENTITY_ORIGINAL_VALUES])) {
$eventEntityTransfer->setOriginalValues($data[EventBehavior::EVENT_CHANGE_ENTITY_ORIGINAL_VALUES]);
diff --git a/tests/SprykerTest/Zed/EventBehavior/Business/EventBehaviorFacadeTest.php b/tests/SprykerTest/Zed/EventBehavior/Business/EventBehaviorFacadeTest.php
index e13e70ca..5625c095 100644
--- a/tests/SprykerTest/Zed/EventBehavior/Business/EventBehaviorFacadeTest.php
+++ b/tests/SprykerTest/Zed/EventBehavior/Business/EventBehaviorFacadeTest.php
@@ -11,6 +11,7 @@
use DateInterval;
use DateTime;
use Generated\Shared\Transfer\EventEntityTransfer;
+use Generated\Shared\Transfer\HydrateEventsRequestTransfer;
use Orm\Zed\EventBehavior\Persistence\SpyEventBehaviorEntityChange;
use Orm\Zed\EventBehavior\Persistence\SpyEventBehaviorEntityChangeQuery;
use PHPUnit\Framework\MockObject\Rule\InvokedCount as InvokedCountMatcher;
@@ -41,6 +42,11 @@ class EventBehaviorFacadeTest extends Unit
*/
protected const ID = 'id';
+ /**
+ * @var string
+ */
+ protected const TIMESTAMP = 'timestamp';
+
/**
* @var string
*/
@@ -217,6 +223,46 @@ public function testGetEventTransferIds(): void
$this->assertEquals($eventTransferIds, [1, 2]);
}
+ /**
+ * @return void
+ */
+ public function testHydrateEventDataTransfer(): void
+ {
+ // Arrange
+ $hydrateEventsRequestTransfer = new HydrateEventsRequestTransfer();
+
+ $eventEntityTransfer = new EventEntityTransfer();
+ $eventEntityTransfer->setId(1);
+ $eventEntityTransfer->setAdditionalValues(['property1' => 'value1']);
+ $eventEntityTransfer->setTimestamp(102);
+ $eventEntityTransfer->setAdditionalValues(['property2' => 'value3']);
+ $hydrateEventsRequestTransfer->addEventEntity($eventEntityTransfer);
+
+ $eventEntityTransfer = new EventEntityTransfer();
+ $eventEntityTransfer->setId(2);
+ $eventEntityTransfer->setForeignKeys(['foreignKey' => 7]);
+ $eventEntityTransfer->setTimestamp(102);
+ $eventEntityTransfer->setAdditionalValues(['property2' => 'value1']);
+ $hydrateEventsRequestTransfer->addEventEntity($eventEntityTransfer);
+
+ $eventEntityTransfer = new EventEntityTransfer();
+ $eventEntityTransfer->setId(1);
+ $eventEntityTransfer->setForeignKeys(['foreignKey' => 5]);
+ $eventEntityTransfer->setTimestamp(106);
+ $eventEntityTransfer->setAdditionalValues(['property1' => 'value1', 'property2' => 'value2']);
+ $hydrateEventsRequestTransfer->addEventEntity($eventEntityTransfer);
+
+ $hydrateEventsRequestTransfer->setForeignKeyName('foreignKey');
+ $hydrateEventsRequestTransfer->setAdditionalValueName('property2');
+
+ $hydrateEventsResponseTransfer = $this->tester->getFacade()->hydrateEventDataTransfer($hydrateEventsRequestTransfer);
+
+ // Assert
+ $this->assertEquals($hydrateEventsResponseTransfer->getIdTimestampMap(), [1 => 106, 2 => 102]);
+ $this->assertEquals($hydrateEventsResponseTransfer->getForeignKeyTimestampMap(), [7 => 102, 5 => 106]);
+ $this->assertEquals($hydrateEventsResponseTransfer->getAdditionalValueTimestampMap(), ['value3' => 102, 'value1' => 102, 'value2' => 106]);
+ }
+
/**
* @return void
*/
@@ -347,7 +393,7 @@ public function assertTriggeredEvent(string $eventName, TransferInterface $event
$actualArray[EventBehavior::EVENT_CHANGE_ENTITY_ADDITIONAL_VALUES] = $actualArray[static::FIELD_ADDITIONAL_VALUES];
unset($actualArray[static::FIELD_ADDITIONAL_VALUES]);
- $this->assertEquals($actualArray, $this->createEventData($actualArray[static::ID]));
+ $this->assertEquals($actualArray, $this->createEventData($actualArray[static::ID], $actualArray[static::TIMESTAMP]));
}
/**
@@ -435,14 +481,16 @@ protected function createLostEntityChangeEvent(string $idEntity = '123'): void
/**
* @param string $idEntity
+ * @param int $timestamp
*
* @return array
*/
- protected function createEventData(string $idEntity = '123'): array
+ protected function createEventData(string $idEntity = '123', int $timestamp = 0): array
{
return [
EventBehavior::EVENT_CHANGE_ENTITY_NAME => 'name',
EventBehavior::EVENT_CHANGE_ENTITY_ID => $idEntity,
+ EventEntityTransfer::TIMESTAMP => $timestamp,
EventBehavior::EVENT_CHANGE_ENTITY_FOREIGN_KEYS => [1, 2, 3],
EventBehavior::EVENT_CHANGE_NAME => 'test',
EventBehavior::EVENT_CHANGE_ENTITY_MODIFIED_COLUMNS => [],