diff --git a/lib/Db/Card.php b/lib/Db/Card.php index 6813c0167..0dccdddf0 100644 --- a/lib/Db/Card.php +++ b/lib/Db/Card.php @@ -12,6 +12,7 @@ use DateTime; use DateTimeZone; use Sabre\VObject\Component\VCalendar; +use OCA\Deck\Model\Public\CardEventData; /** * @method string getTitle() @@ -175,4 +176,31 @@ public function getCalendarPrefix(): string { public function getETag(): string { return md5((string)$this->getLastModified()); } + + public function toEventData(?array $previousValues = null): CardEventData { + return new CardEventData( + title: $this->getTitle(), + description: $this->getDescription(), + boardId: $this->getRelatedBoard()->getId(), + stackId: $this->getStackId(), + lastModified: new DateTime('@' . $this->getLastModified()), + createdAt: new DateTime('@' . $this->getCreatedAt()), + labels: array_map(fn($label) => [ + 'id' => $label->getId(), + 'title' => $label->getTitle() + ], $this->getLabels() ?? []), + assignedUsers: $this->getAssignedUsers() ?: [], + order: $this->getOrder(), + archived: $this->getArchived(), + commentsUnread: $this->getCommentsUnread(), + commentsCount: $this->getCommentsCount(), + owner: $this->getOwner(), + lastEditor: $this->getLastEditor(), + duedate: $this->getDuedate(), + doneAt: $this->getDone(), + deletedAt: ($this->getDeletedAt() > 0) + ? new DateTime('@' . $this->getDeletedAt()) + : null + ); + } } diff --git a/lib/Event/ACardEvent.php b/lib/Event/ACardEvent.php index 212e5b778..d2f82fa0d 100644 --- a/lib/Event/ACardEvent.php +++ b/lib/Event/ACardEvent.php @@ -11,8 +11,9 @@ use OCA\Deck\Db\Card; use OCP\EventDispatcher\Event; +use OCP\EventDispatcher\IWebhookCompatibleEvent; -abstract class ACardEvent extends Event { +abstract class ACardEvent extends Event implements IWebhookCompatibleEvent { private $card; public function __construct(Card $card) { @@ -24,4 +25,8 @@ public function __construct(Card $card) { public function getCard(): Card { return $this->card; } + + public function getWebhookSerializable(): array { + return $this->getCard()->jsonSerialize(); + } } diff --git a/lib/Model/Public/CardEventData.php b/lib/Model/Public/CardEventData.php new file mode 100644 index 000000000..aa5f6bde9 --- /dev/null +++ b/lib/Model/Public/CardEventData.php @@ -0,0 +1,125 @@ + $labels + * @param array $assignedUsers + * @param int $order + * @param bool $archived + * @param int $commentsUnread + * @param int $commentsCount + * @param ?string $owner + * @param ?string $lastEditor + * @param ?\DateTime $duedate + * @param ?\DateTime $doneAt + * @param ?\DateTime $deletedAt + * + * @since 2.0.0 + */ + public function __construct( + /** @readonly */ + public string $title, + /** @readonly */ + public string $description, + /** @readonly */ + public int $boardId, + /** @readonly */ + public int $stackId, + /** @readonly */ + public \DateTime $lastModified, + /** @readonly */ + public \DateTime $createdAt, + /** @readonly */ + public array $labels = [], + /** @readonly */ + public array $assignedUsers = [], + /** @readonly */ + public int $order = 0, + /** @readonly */ + public bool $archived = false, + /** @readonly */ + public int $commentsUnread = 0, + /** @readonly */ + public int $commentsCount = 0, + /** @readonly */ + public ?string $owner = null, + /** @readonly */ + public ?string $lastEditor, + /** @readonly */ + public ?\DateTime $duedate = null, + /** @readonly */ + public ?\DateTime $doneAt = null, + /** @readonly */ + public ?\DateTime $deletedAt = null, + ) { + } + + + /** + * Serialize the object to a JSON-compatible array. + * + * @return array{ + * title: string, + * description: string, + * boardId: int, + * stackId: int, + * lastModified: int, + * createdAt: int, + * labels: array, + * assignedUsers: array, + * order: int, + * archived: bool, + * commentsUnread: int, + * commentsCount: int, + * owner: ?string, + * lastEditor: ?string, + * duedate: ?string, + * doneAt: ?string, + * deletedAt: ?int, + * } + */ + public function jsonSerialize(): array + { + return [ + 'title' => $this->title, + 'description' => $this->description, + 'boardId' => $this->boardId, + 'stackId' => $this->stackId, + 'lastModified' => $this->lastModified->format(DATE_ATOM), + 'createdAt' => $this->createdAt->format(DATE_ATOM), + 'labels' => $this->labels, + 'assignedUsers' => $this->assignedUsers, + 'order' => $this->order, + 'archived' => $this->archived, + 'commentsUnread' => $this->commentsUnread, + 'commentsCount' => $this->commentsCount, + 'owner' => $this->owner, + 'lastEditor' => $this->lastEditor, + 'duedate' => $this->duedate?->format(DATE_ATOM), + 'doneAt' => $this->doneAt?->format(DATE_ATOM), + 'deletedAt' => $this->deletedAt?->format(DATE_ATOM), + ]; + } +} \ No newline at end of file diff --git a/tests/unit/Db/CardTest.php b/tests/unit/Db/CardTest.php index f38549f8c..ec5281339 100644 --- a/tests/unit/Db/CardTest.php +++ b/tests/unit/Db/CardTest.php @@ -26,6 +26,7 @@ use DateInterval; use DateTime; use OCA\Deck\Model\CardDetails; +use OCA\Deck\Db\Board; use Test\TestCase; class CardTest extends TestCase { @@ -46,6 +47,14 @@ private function createCard() { return $card; } + private function createLabel() { + $label = new Label(); + $label->setId(1); + $label->setTitle('Label 1'); + $label->setColor('000000'); + return $label; + } + public function dataDuedate() { return [ [(new DateTime()), Card::DUEDATE_NOW], @@ -149,4 +158,85 @@ public function testJsonSerializeAsignedUsers() { 'done' => false, ], (new CardDetails($card))->jsonSerialize()); } + + public function testToEventDataSerializationSimple() { + $card = $this->createCard(); + $board = new Board(); + $board->setId(1); + $card->setRelatedBoard($board); + + $lastmodified = new DateTime('2024-01-01 00:00:00'); + $card->setLastModified($lastmodified->getTimestamp()); + $created = new DateTime('2024-01-02 00:00:00'); + $card->setCreatedAt($created->getTimestamp()); + + $this->assertEquals([ + 'title' => 'My Card', + 'description' => 'a long description', + 'boardId' => 1, + 'stackId' => 1, + 'lastModified' => $lastmodified->format(DATE_ATOM), + 'createdAt' => $created->format(DATE_ATOM), + 'labels' => [], + 'assignedUsers' => [], + 'order' => 12, + 'archived' => false, + 'commentsUnread' => 0, + 'commentsCount' => 0, + 'owner' => 'admin', + 'lastEditor' => null, + 'duedate' => null, + 'doneAt' => null, + 'deletedAt' => null, + ], $card->toEventData()->jsonSerialize()); + } + + public function testToEventDataSerializationFull() { + $card = $this->createCard(); + + $board = new Board(); + $board->setId(1); + $card->setRelatedBoard($board); + + $card->setAssignedUsers([ 'user1' ]); + $card->setLabels([$this->createLabel()]); + $card->setLastEditor('someuser'); + $card->setArchived(true); + + $lastModified = new DateTime('2024-01-01 00:00:00'); + $card->setLastModified($lastModified->getTimestamp()); + $createdAt = new DateTime('2024-01-02 00:00:00'); + $card->setCreatedAt($createdAt->getTimestamp()); + $doneAt = new DateTime('2024-01-03 00:00:00'); + $card->setDone($doneAt); + $duedate = new DateTime('2024-01-05 00:00:00'); + $card->setDuedate($duedate); + $deletedAt = new DateTime('2024-01-05 00:00:00'); + $card->setDeletedAt($deletedAt->getTimestamp()); + + $this->assertEquals([ + 'title' => 'My Card', + 'description' => 'a long description', + 'boardId' => 1, + 'stackId' => 1, + 'lastModified' => $lastModified->format(DATE_ATOM), + 'createdAt' => $createdAt->format(DATE_ATOM), + 'labels' => [ + [ + 'id' => 1, + 'title' => 'Label 1' + ] + ], + 'assignedUsers' => ['user1'], + 'order' => 12, + 'archived' => true, + 'commentsUnread' => 0, + 'commentsCount' => 0, + 'doneAt' => $doneAt->format(DATE_ATOM), + 'owner' => 'admin', + 'lastEditor' => 'someuser', + 'duedate' => $duedate->format(DATE_ATOM), + 'deletedAt' => $deletedAt->format(DATE_ATOM), + ], $card->toEventData()->jsonSerialize()); + } }