diff --git a/lib/DAV/Calendar.php b/lib/DAV/Calendar.php index 5fb7ee652..8563c3679 100644 --- a/lib/DAV/Calendar.php +++ b/lib/DAV/Calendar.php @@ -27,7 +27,9 @@ use OCA\DAV\CalDAV\Plugin; use OCA\DAV\DAV\Sharing\IShareable; use OCA\Deck\Db\Board; use OCA\Deck\Db\Card; +use OCA\Deck\Db\Stack; use OCA\Deck\Service\CardService; +use OCA\Deck\Service\StackService; use Sabre\CalDAV\Xml\Property\SupportedCalendarComponentSet; use Sabre\DAV\PropPatch; @@ -62,9 +64,14 @@ class Calendar extends ExternalCalendar implements IShareable { if ($board) { - /** @var CardService cardService */ + /** @var CardService $cardService */ $cardService = \OC::$server->query(CardService::class); - $this->children = $cardService->findCalendarEntries($board->getId()); + /** @var StackService $stackService */ + $stackService = \OC::$server->query(StackService::class); + $this->children = array_merge( + $cardService->findCalendarEntries($board->getId()), + $stackService->findCalendarEntries($board->getId()) + ); } else { $this->children = []; } @@ -120,8 +127,8 @@ class Calendar extends ExternalCalendar implements IShareable { */ function calendarQuery(array $filters) { // In a real implementation this should actually filter - return array_map(function (Card $card) { - return $card->getId() . '.ics'; + return array_map(function ($card) { + return $card->getCalendarPrefix() . '-' . $card->getId() . '.ics'; }, $this->children); } @@ -140,7 +147,7 @@ class Calendar extends ExternalCalendar implements IShareable { $card = array_values(array_filter( $this->children, function ($card) use (&$name) { - return $card->getId() . '.ics' === $name; + return $card->getCalendarPrefix() . '-' . $card->getId() . '.ics' === $name; } )); if (count($card) > 0) { @@ -153,8 +160,8 @@ class Calendar extends ExternalCalendar implements IShareable { * @inheritDoc */ function getChildren() { - $childNames = array_map(function (Card $card) { - return $card->getId() . '.ics'; + $childNames = array_map(function ($card) { + return $card->getCalendarPrefix() . '-' . $card->getId() . '.ics'; }, $this->children); $children = []; @@ -173,7 +180,7 @@ class Calendar extends ExternalCalendar implements IShareable { return count(array_filter( $this->children, function ($card) use (&$name) { - return $card->getId() . '.ics' === $name; + return $card->getCalendarPrefix() . '-' . $card->getId() . '.ics' === $name; } )) > 0; } diff --git a/lib/DAV/CalendarObject.php b/lib/DAV/CalendarObject.php index 0dc0c78aa..82633dd30 100644 --- a/lib/DAV/CalendarObject.php +++ b/lib/DAV/CalendarObject.php @@ -36,7 +36,7 @@ class CalendarObject implements \Sabre\CalDAV\ICalendarObject, \Sabre\DAVACL\IAC /** * @var Card */ - private $card; + private $sourceItem; /** * CalendarObject constructor. @@ -44,10 +44,10 @@ class CalendarObject implements \Sabre\CalDAV\ICalendarObject, \Sabre\DAVACL\IAC * @param Calendar $calendar * @param string $name */ - public function __construct(Calendar $calendar, string $name, Card $card = null) { + public function __construct(Calendar $calendar, string $name, $sourceItem = null) { $this->calendar = $calendar; $this->name = $name; - $this->card = $card; + $this->sourceItem = $sourceItem; } /** @@ -96,8 +96,8 @@ class CalendarObject implements \Sabre\CalDAV\ICalendarObject, \Sabre\DAVACL\IAC * @inheritDoc */ function get() { - if ($this->card) { - return $this->card->getCalendarObject()->serialize(); + if ($this->sourceItem) { + return $this->sourceItem->getCalendarObject()->serialize(); } } @@ -147,6 +147,6 @@ class CalendarObject implements \Sabre\CalDAV\ICalendarObject, \Sabre\DAVACL\IAC * @inheritDoc */ function getLastModified() { - return $this->card->getLastModified(); + return $this->sourceItem->getLastModified(); } } diff --git a/lib/Db/Card.php b/lib/Db/Card.php index 107c253fd..f91092a84 100644 --- a/lib/Db/Card.php +++ b/lib/Db/Card.php @@ -121,14 +121,32 @@ class Card extends RelationalEntity { public function getCalendarObject(): VCalendar { $calendar = new VCalendar(); - $event = $calendar->createComponent('VEVENT'); - $event->UID = 'deck-cardevent' . $this->getId() . '@example.com'; + $event = $calendar->createComponent('VTODO'); + $event->UID = 'deck-card-' . $this->getId(); $event->DTSTAMP = new \DateTime($this->getDuedate()); $event->DTSTART = new \DateTime($this->getDuedate()); $event->DTEND = new \DateTime($this->getDuedate()); + $event->add('RELATED-TO', 'deck-stack-' . $this->getStackId()); + + // For write support: CANCELLED / IN-PROCESS handling + $event->STATUS = $this->getArchived() ? "COMPLETED" : "NEEDS-ACTION"; + if ($this->getArchived()) { + $date = new DateTime(); + $date->setTimestamp($this->getLastModified()); + $event->COMPLETED = $date; + } + if (count($this->getLabels()) > 0) { + $event->CATEGORIES = array_map(function ($label) { + return $label->getTitle(); + }, $this->getLabels()); + } $event->SUMMARY = $this->getTitle(); $calendar->add($event); return $calendar; } + public function getCalendarPrefix(): string { + return 'card'; + } + } diff --git a/lib/Db/CardMapper.php b/lib/Db/CardMapper.php index a929bec3b..549aadfe0 100644 --- a/lib/Db/CardMapper.php +++ b/lib/Db/CardMapper.php @@ -175,9 +175,7 @@ class CardMapper extends QBMapper implements IPermissionMapper { ->from('deck_cards', 'c') ->join('c', 'deck_stacks', 's', 's.id = c.stack_id') ->where($qb->expr()->eq('s.board_id', $qb->createNamedParameter($boardId))) - ->andWhere($qb->expr()->neq('c.archived', $qb->createNamedParameter(true))) ->andWhere($qb->expr()->eq('c.deleted_at', $qb->createNamedParameter('0'))) - ->andWhere($qb->expr()->isNotNull('c.duedate')) ->orderBy('c.duedate') ->setMaxResults($limit) ->setFirstResult($offset); diff --git a/lib/Db/Stack.php b/lib/Db/Stack.php index 85d9c4553..7dc9310ba 100644 --- a/lib/Db/Stack.php +++ b/lib/Db/Stack.php @@ -23,6 +23,8 @@ namespace OCA\Deck\Db; +use Sabre\VObject\Component\VCalendar; + class Stack extends RelationalEntity { protected $title; protected $boardId; @@ -50,4 +52,18 @@ class Stack extends RelationalEntity { } return $json; } + + public function getCalendarObject(): VCalendar { + $calendar = new VCalendar(); + $event = $calendar->createComponent('VTODO'); + $event->UID = 'deck-stack-' . $this->getId(); + $event->SUMMARY = '[Stack]: ' . $this->getTitle(); + $calendar->add($event); + return $calendar; + } + + public function getCalendarPrefix(): string { + return 'stack'; + } + } diff --git a/lib/Service/CardService.php b/lib/Service/CardService.php index 31df0c48b..bd9c11e0c 100644 --- a/lib/Service/CardService.php +++ b/lib/Service/CardService.php @@ -146,8 +146,11 @@ class CardService { public function findCalendarEntries($boardId) { $this->permissionService->checkPermission($this->boardMapper, $boardId, Acl::PERMISSION_READ); - - return $this->cardMapper->findCalendarEntries($boardId); + $cards = $this->cardMapper->findCalendarEntries($boardId); + foreach ($cards as $card) { + $this->enrich($card); + } + return $cards; } /** diff --git a/lib/Service/StackService.php b/lib/Service/StackService.php index 7df627e06..a31d13854 100644 --- a/lib/Service/StackService.php +++ b/lib/Service/StackService.php @@ -146,6 +146,11 @@ class StackService { return $stacks; } + public function findCalendarEntries($boardId) { + $this->permissionService->checkPermission(null, $boardId, Acl::PERMISSION_READ); + return $this->stackMapper->findAll($boardId); + } + public function fetchDeleted($boardId) { $this->permissionService->checkPermission($this->boardMapper, $boardId, Acl::PERMISSION_READ); $stacks = $this->stackMapper->findDeleted($boardId);