diff --git a/lib/Controller/BoardImportApiController.php b/lib/Controller/BoardImportApiController.php index b6c32183f..2d2545105 100644 --- a/lib/Controller/BoardImportApiController.php +++ b/lib/Controller/BoardImportApiController.php @@ -24,12 +24,12 @@ namespace OCA\Deck\Controller; use OCA\Deck\Service\BoardImportService; -use OCP\AppFramework\ApiController; use OCP\AppFramework\Http; use OCP\AppFramework\Http\DataResponse; +use OCP\AppFramework\OCSController; use OCP\IRequest; -class BoardImportApiController extends ApiController { +class BoardImportApiController extends OCSController { /** @var BoardImportService */ private $boardImportService; /** @var string */ diff --git a/lib/Service/ABoardImportService.php b/lib/Service/ABoardImportService.php index 614c31225..6b942410e 100644 --- a/lib/Service/ABoardImportService.php +++ b/lib/Service/ABoardImportService.php @@ -24,14 +24,38 @@ namespace OCA\Deck\Service; use OCA\Deck\Db\Acl; +use OCA\Deck\Db\Assignment; use OCA\Deck\Db\Board; use OCA\Deck\Db\Card; use OCA\Deck\Db\Label; use OCA\Deck\Db\Stack; +use OCP\AppFramework\Db\Entity; +use OCP\Comments\IComment; abstract class ABoardImportService { /** @var BoardImportService */ private $boardImportService; + /** @var Stack[] */ + protected $stacks = []; + /** @var Label[] */ + protected $labels = []; + /** @var Card[] */ + protected $cards = []; + /** @var Acl[] */ + protected $acls = []; + /** @var IComment[][] */ + protected $comments = []; + /** @var Assignment[] */ + protected $assignments = []; + /** @var string[][] */ + protected $labelCardAssignments = []; + + /** + * Configure import service + * + * @return void + */ + abstract public function bootstrap(): void; abstract public function getBoard(): ?Board; @@ -50,25 +74,47 @@ abstract class ABoardImportService { */ abstract public function getCards(): array; - abstract public function updateStack(string $id, Stack $stack): void; + abstract public function getCardAssignments(): array; - abstract public function updateCard(string $id, Card $card): void; - - abstract public function importParticipants(): void; - - abstract public function importComments(): void; - - /** @return Label[] */ - abstract public function importLabels(): array; - - abstract public function assignCardsToLabels(): void; + abstract public function getCardLabelAssignment(): array; /** - * Configure import service - * - * @return void + * @return IComment[][]|array */ - abstract public function bootstrap(): void; + abstract public function getComments(): array; + + /** @return Label[] */ + abstract public function getLabels(): array; + + abstract public function validateUsers(): void; + + public function updateStack(string $id, Stack $stack): void { + $this->stacks[$id] = $stack; + } + + public function updateCard(string $id, Card $card): void { + $this->cards[$id] = $card; + } + + public function updateLabel(string $code, Label $label): void { + $this->labels[$code] = $label; + } + + public function updateAcl(string $code, Acl $acl): void { + $this->acls[$code] = $acl; + } + + public function updateComment(string $cardId, string $commentId, IComment $comment): void { + $this->comments[$cardId][$commentId] = $comment; + } + + public function updateCardAssignment(string $cardId, string $assignmentId, Entity $assignment): void { + $this->assignments[$cardId][$assignmentId] = $assignment; + } + + public function updateCardLabelsAssignment(string $cardId, string $assignmentId, string $assignment): void { + $this->labelCardAssignments[$cardId][$assignmentId] = $assignment; + } public function setImportService(BoardImportService $service): void { $this->boardImportService = $service; diff --git a/lib/Service/BoardImportCommandService.php b/lib/Service/BoardImportCommandService.php index bff49e5a0..1a3300cc1 100644 --- a/lib/Service/BoardImportCommandService.php +++ b/lib/Service/BoardImportCommandService.php @@ -114,10 +114,9 @@ class BoardImportCommandService extends BoardImportService { $this->getOutput()->writeln('Valid schema:'); $schemaPath = __DIR__ . '/fixtures/config-' . $this->getSystem() . '-schema.json'; $this->getOutput()->writeln(print_r(file_get_contents($schemaPath), true)); - $this->getInput()->setOption('config', null); + $this->getInput()->setOption('config', ''); } - parent::validateConfig(); - return; + $this->validateConfig(); } public function validateSystem(): void { @@ -186,9 +185,9 @@ class BoardImportCommandService extends BoardImportService { $this->importCards(); $this->getOutput()->writeln('Assign cards to labels...'); $this->assignCardsToLabels(); - $this->getOutput()->writeln('Iporting comments...'); + $this->getOutput()->writeln('Importing comments...'); $this->importComments(); - $this->getOutput()->writeln('Iporting participants...'); - $this->importParticipants(); + $this->getOutput()->writeln('Importing participants...'); + $this->importCardAssignments(); } } diff --git a/lib/Service/BoardImportService.php b/lib/Service/BoardImportService.php index a295f12a2..61e126177 100644 --- a/lib/Service/BoardImportService.php +++ b/lib/Service/BoardImportService.php @@ -25,22 +25,20 @@ namespace OCA\Deck\Service; use JsonSchema\Constraints\Constraint; use JsonSchema\Validator; -use OC\Comments\Comment; use OCA\Deck\AppInfo\Application; use OCA\Deck\BadRequestException; use OCA\Deck\Db\AclMapper; -use OCA\Deck\Db\Assignment; use OCA\Deck\Db\AssignmentMapper; use OCA\Deck\Db\Board; use OCA\Deck\Db\BoardMapper; use OCA\Deck\Db\CardMapper; use OCA\Deck\Db\Label; use OCA\Deck\Db\LabelMapper; -use OCA\Deck\Db\Stack; use OCA\Deck\Db\StackMapper; use OCA\Deck\Exceptions\ConflictException; use OCA\Deck\NotFoundException; use OCP\AppFramework\Db\Entity; +use OCP\Comments\IComment; use OCP\Comments\ICommentsManager; use OCP\Comments\NotFoundException as CommentNotFoundException; use OCP\IDBConnection; @@ -87,7 +85,6 @@ class BoardImportService { private $data; /** * @var Board - * @psalm-suppress PropertyNotSetInConstructor */ private $board; @@ -111,6 +108,21 @@ class BoardImportService { $this->cardMapper = $cardMapper; $this->assignmentMapper = $assignmentMapper; $this->commentsManager = $commentsManager; + $this->board = new Board(); + $this->disableCommentsEvents(); + } + + private function disableCommentsEvents(): void { + if (defined('PHPUNIT_RUN')) { + return; + } + $propertyEventHandlers = new \ReflectionProperty($this->commentsManager, 'eventHandlers'); + $propertyEventHandlers->setAccessible(true); + $propertyEventHandlers->setValue($this->commentsManager, []); + + $propertyEventHandlerClosures = new \ReflectionProperty($this->commentsManager, 'eventHandlerClosures'); + $propertyEventHandlerClosures->setAccessible(true); + $propertyEventHandlerClosures->setValue($this->commentsManager, []); } public function import(): void { @@ -123,7 +135,7 @@ class BoardImportService { $this->importCards(); $this->assignCardsToLabels(); $this->importComments(); - $this->importParticipants(); + $this->importCardAssignments(); } catch (\Throwable $th) { throw new BadRequestException($th->getMessage()); } @@ -171,15 +183,14 @@ class BoardImportService { } public function getImportSystem(): ABoardImportService { - $systemClass = 'OCA\\Deck\\Service\\BoardImport' . ucfirst($this->getSystem()) . 'Service'; if (!$this->getSystem()) { throw new NotFoundException('System to import not found'); } if (!is_object($this->systemInstance)) { + $systemClass = 'OCA\\Deck\\Service\\BoardImport' . ucfirst($this->getSystem()) . 'Service'; $this->systemInstance = \OC::$server->get($systemClass); $this->systemInstance->setImportService($this); } - return $this->systemInstance; } @@ -187,11 +198,6 @@ class BoardImportService { $this->systemInstance = $instance; } - public function insertAssignment(Assignment $assignment): self { - $this->assignmentMapper->insert($assignment); - return $this; - } - public function importBoard(): void { $board = $this->getImportSystem()->getBoard(); if ($board) { @@ -200,23 +206,29 @@ class BoardImportService { } } - public function getBoard(): Board { + public function getBoard(bool $reset = false): Board { + if ($reset) { + $this->board = new Board(); + } return $this->board; } - public function importAcl(): self { + public function importAcl(): void { $aclList = $this->getImportSystem()->getAclList(); - foreach ($aclList as $acl) { + foreach ($aclList as $code => $acl) { $this->aclMapper->insert($acl); + $this->getImportSystem()->updateAcl($code, $acl); } $this->getBoard()->setAcl($aclList); - return $this; } - public function importLabels(): array { - $labels = $this->getImportSystem()->importLabels(); + public function importLabels(): void { + $labels = $this->getImportSystem()->getLabels(); + foreach ($labels as $code => $label) { + $this->labelMapper->insert($label); + $this->getImportSystem()->updateLabel($code, $label); + } $this->getBoard()->setLabels($labels); - return $labels; } public function createLabel(string $title, string $color, int $boardId): Entity { @@ -227,26 +239,21 @@ class BoardImportService { return $this->labelMapper->insert($label); } - /** - * @return Stack[] - */ - public function importStacks(): array { + public function importStacks(): void { $stacks = $this->getImportSystem()->getStacks(); foreach ($stacks as $code => $stack) { $this->stackMapper->insert($stack); $this->getImportSystem()->updateStack($code, $stack); } $this->getBoard()->setStacks(array_values($stacks)); - return $stacks; } - public function importCards(): self { + public function importCards(): void { $cards = $this->getImportSystem()->getCards(); foreach ($cards as $code => $card) { $this->cardMapper->insert($card); $this->getImportSystem()->updateCard($code, $card); } - return $this; } /** @@ -263,21 +270,36 @@ class BoardImportService { } public function assignCardsToLabels(): void { - $this->getImportSystem()->assignCardsToLabels(); + $data = $this->getImportSystem()->getCardLabelAssignment(); + foreach ($data as $cardId => $assignemnt) { + foreach ($assignemnt as $assignmentId => $labelId) { + $this->assignCardToLabel( + $cardId, + $labelId + ); + $this->getImportSystem()->updateCardLabelsAssignment($cardId, $assignmentId, $labelId); + } + } } public function importComments(): void { - $this->getImportSystem()->importComments(); + $allComments = $this->getImportSystem()->getComments(); + foreach ($allComments as $cardId => $comments) { + foreach ($comments as $commentId => $comment) { + $this->insertComment($cardId, $comment); + $this->getImportSystem()->updateComment($cardId, $commentId, $comment); + } + } } - public function insertComment(string $cardId, Comment $comment): void { + private function insertComment(string $cardId, IComment $comment): void { $comment->setObject('deckCard', $cardId); $comment->setVerb('comment'); // Check if parent is a comment on the same card if ($comment->getParentId() !== '0') { try { - $comment = $this->commentsManager->get($comment->getParentId()); - if ($comment->getObjectType() !== Application::COMMENT_ENTITY_TYPE || $comment->getObjectId() !== $cardId) { + $parent = $this->commentsManager->get($comment->getParentId()); + if ($parent->getObjectType() !== Application::COMMENT_ENTITY_TYPE || $parent->getObjectId() !== $cardId) { throw new CommentNotFoundException(); } } catch (CommentNotFoundException $e) { @@ -286,30 +308,7 @@ class BoardImportService { } try { - $qb = $this->dbConn->getQueryBuilder(); - - $values = [ - 'parent_id' => $qb->createNamedParameter($comment->getParentId()), - 'topmost_parent_id' => $qb->createNamedParameter($comment->getTopmostParentId()), - 'children_count' => $qb->createNamedParameter($comment->getChildrenCount()), - 'actor_type' => $qb->createNamedParameter($comment->getActorType()), - 'actor_id' => $qb->createNamedParameter($comment->getActorId()), - 'message' => $qb->createNamedParameter($comment->getMessage()), - 'verb' => $qb->createNamedParameter($comment->getVerb()), - 'creation_timestamp' => $qb->createNamedParameter($comment->getCreationDateTime(), 'datetime'), - 'latest_child_timestamp' => $qb->createNamedParameter($comment->getLatestChildDateTime(), 'datetime'), - 'object_type' => $qb->createNamedParameter($comment->getObjectType()), - 'object_id' => $qb->createNamedParameter($comment->getObjectId()), - 'reference_id' => $qb->createNamedParameter($comment->getReferenceId()) - ]; - - $affectedRows = $qb->insert('comments') - ->values($values) - ->execute(); - - if ($affectedRows > 0) { - $comment->setId((string)$qb->getLastInsertId()); - } + $this->commentsManager->save($comment); } catch (\InvalidArgumentException $e) { throw new BadRequestException('Invalid input values'); } catch (CommentNotFoundException $e) { @@ -317,8 +316,14 @@ class BoardImportService { } } - public function importParticipants(): void { - $this->getImportSystem()->importParticipants(); + public function importCardAssignments(): void { + $allAssignments = $this->getImportSystem()->getCardAssignments(); + foreach ($allAssignments as $cardId => $assignments) { + foreach ($assignments as $assignmentId => $assignment) { + $this->assignmentMapper->insert($assignment); + $this->getImportSystem()->updateCardAssignment($cardId, $assignmentId, $assignment); + } + } } public function setData(\stdClass $data): void { diff --git a/lib/Service/BoardImportTrelloService.php b/lib/Service/BoardImportTrelloService.php index 1598e20f2..3068ad66f 100644 --- a/lib/Service/BoardImportTrelloService.php +++ b/lib/Service/BoardImportTrelloService.php @@ -31,7 +31,6 @@ use OCA\Deck\Db\Board; use OCA\Deck\Db\Card; use OCA\Deck\Db\Label; use OCA\Deck\Db\Stack; -use OCP\AppFramework\Db\Entity; use OCP\IL10N; use OCP\IUser; use OCP\IUserManager; @@ -41,20 +40,6 @@ class BoardImportTrelloService extends ABoardImportService { private $userManager; /** @var IL10N */ private $l10n; - /** - * Array of stacks - * - * @var Stack[] - */ - private $stacks = []; - /** - * Array of Labels - * - * @var Label[]|Entity[] - */ - private $labels = []; - /** @var Card[] */ - private $cards = []; /** @var IUser[] */ private $members = []; @@ -94,46 +79,115 @@ class BoardImportTrelloService extends ABoardImportService { } } - /** - * @return Acl[] - */ - public function getAclList(): array { - $return = []; - foreach ($this->members as $member) { - if ($member->getUID() === $this->getImportService()->getConfig('owner')->getUID()) { - continue; + public function getCardAssignments(): array { + $assignments = []; + foreach ($this->getImportService()->getData()->cards as $trelloCard) { + foreach ($trelloCard->idMembers as $idMember) { + if (empty($this->members[$idMember])) { + continue; + } + $assignment = new Assignment(); + $assignment->setCardId($this->cards[$trelloCard->id]->getId()); + $assignment->setParticipant($this->members[$idMember]->getUID()); + $assignment->setType(Assignment::TYPE_USER); + $assignments[$trelloCard->id][] = $assignment; } - $acl = new Acl(); - $acl->setBoardId($this->getImportService()->getBoard()->getId()); - $acl->setType(Acl::PERMISSION_TYPE_USER); - $acl->setParticipant($member->getUID()); - $acl->setPermissionEdit(false); - $acl->setPermissionShare(false); - $acl->setPermissionManage(false); - $return[] = $acl; + } + return $assignments; + } + + public function getComments(): array { + $comments = []; + foreach ($this->getImportService()->getData()->cards as $trelloCard) { + $values = array_filter( + $this->getImportService()->getData()->actions, + function (\stdClass $a) use ($trelloCard) { + return $a->type === 'commentCard' && $a->data->card->id === $trelloCard->id; + } + ); + $keys = array_map(function (\stdClass $c): string { + return $c->id; + }, $values); + $trelloComments = array_combine($keys, $values); + foreach ($trelloComments as $commentId => $trelloComment) { + $comment = new Comment(); + if (!empty($this->getImportService()->getConfig('uidRelation')->{$trelloComment->memberCreator->username})) { + $actor = $this->getImportService()->getConfig('uidRelation')->{$trelloComment->memberCreator->username}->getUID(); + } else { + $actor = $this->getImportService()->getConfig('owner')->getUID(); + } + $comment + ->setActor('users', $actor) + ->setMessage($this->replaceUsernames($trelloComment->data->text), 0) + ->setCreationDateTime( + \DateTime::createFromFormat('Y-m-d\TH:i:s.v\Z', $trelloComment->date) + ); + $cardId = $this->cards[$trelloCard->id]->getId(); + $comments[$cardId][$commentId] = $comment; + } + } + return $comments; + } + + public function getCardLabelAssignment(): array { + $cardsLabels = []; + foreach ($this->getImportService()->getData()->cards as $trelloCard) { + foreach ($trelloCard->labels as $label) { + $cardId = $this->cards[$trelloCard->id]->getId(); + $labelId = $this->labels[$label->id]->getId(); + $cardsLabels[$cardId][] = $labelId; + } + } + return $cardsLabels; + } + + public function getBoard(): Board { + $board = $this->getImportService()->getBoard(); + if (empty($this->getImportService()->getData()->name)) { + throw new BadRequestException('Invalid name of board'); + } + $board->setTitle($this->getImportService()->getData()->name); + $board->setOwner($this->getImportService()->getConfig('owner')->getUID()); + $board->setColor($this->getImportService()->getConfig('color')); + return $board; + } + + /** + * @return Label[] + */ + public function getLabels(): array { + foreach ($this->getImportService()->getData()->labels as $trelloLabel) { + $label = new Label(); + if (empty($trelloLabel->name)) { + $label->setTitle('Unnamed ' . $trelloLabel->color . ' label'); + } else { + $label->setTitle($trelloLabel->name); + } + $label->setColor($this->translateColor($trelloLabel->color)); + $label->setBoardId($this->getImportService()->getBoard()->getId()); + $this->labels[$trelloLabel->id] = $label; + } + return $this->labels; + } + + /** + * @return Stack[] + */ + public function getStacks(): array { + $return = []; + foreach ($this->getImportService()->getData()->lists as $order => $list) { + $stack = new Stack(); + if ($list->closed) { + $stack->setDeletedAt(time()); + } + $stack->setTitle($list->name); + $stack->setBoardId($this->getImportService()->getBoard()->getId()); + $stack->setOrder($order + 1); + $return[$list->id] = $stack; } return $return; } - private function checklistItem(\stdClass $item): string { - if (($item->state == 'incomplete')) { - $string_start = '- [ ]'; - } else { - $string_start = '- [x]'; - } - $check_item_string = $string_start . ' ' . $item->name . "\n"; - return $check_item_string; - } - - private function formulateChecklistText(\stdClass $checklist): string { - $checklist_string = "\n\n## {$checklist->name}\n"; - foreach ($checklist->checkItems as $item) { - $checklist_item_string = $this->checklistItem($item); - $checklist_string = $checklist_string . "\n" . $checklist_item_string; - } - return $checklist_string; - } - /** * @return Card[] */ @@ -144,6 +198,7 @@ class BoardImportTrelloService extends ABoardImportService { } $this->getImportService()->getData()->checklists = $checklists; + $cards = []; foreach ($this->getImportService()->getData()->cards as $trelloCard) { $card = new Card(); $lastModified = \DateTime::createFromFormat('Y-m-d\TH:i:s.v\Z', $trelloCard->dateLastActivity); @@ -172,112 +227,32 @@ class BoardImportTrelloService extends ABoardImportService { ->format('Y-m-d H:i:s'); $card->setDuedate($duedate); } - $this->cards[$trelloCard->id] = $card; - } - return $this->cards; - } - - public function updateCard(string $id, Card $card): void { - $this->cards[$id] = $card; - } - - private function appendAttachmentsToDescription(\stdClass $trelloCard): void { - if (empty($trelloCard->attachments)) { - return; - } - $trelloCard->desc .= "\n\n## {$this->l10n->t('Attachments')}\n"; - $trelloCard->desc .= "| {$this->l10n->t('File')} | {$this->l10n->t('date')} |\n"; - $trelloCard->desc .= "|---|---\n"; - foreach ($trelloCard->attachments as $attachment) { - $name = $attachment->name === $attachment->url ? null : $attachment->name; - $trelloCard->desc .= "| [{$name}]({$attachment->url}) | {$attachment->date} |\n"; - } - } - - public function importParticipants(): void { - foreach ($this->getImportService()->getData()->cards as $trelloCard) { - foreach ($trelloCard->idMembers as $idMember) { - if (empty($this->members[$idMember])) { - continue; - } - $assignment = new Assignment(); - $assignment->setCardId($this->cards[$trelloCard->id]->getId()); - $assignment->setParticipant($this->members[$idMember]->getUID()); - $assignment->setType(Assignment::TYPE_USER); - $this->getImportService()->insertAssignment($assignment); - } - } - } - - public function importComments(): void { - foreach ($this->getImportService()->getData()->cards as $trelloCard) { - $comments = array_filter( - $this->getImportService()->getData()->actions, - function (\stdClass $a) use ($trelloCard) { - return $a->type === 'commentCard' && $a->data->card->id === $trelloCard->id; - } - ); - foreach ($comments as $trelloComment) { - if (!empty($this->getImportService()->getConfig('uidRelation')->{$trelloComment->memberCreator->username})) { - $actor = $this->getImportService()->getConfig('uidRelation')->{$trelloComment->memberCreator->username}->getUID(); - } else { - $actor = $this->getImportService()->getConfig('owner')->getUID(); - } - $comment = new Comment(); - $comment - ->setActor('users', $actor) - ->setMessage($this->replaceUsernames($trelloComment->data->text), 0) - ->setCreationDateTime( - \DateTime::createFromFormat('Y-m-d\TH:i:s.v\Z', $trelloComment->date) - ); - $this->getImportService()->insertComment( - (string) $this->cards[$trelloCard->id]->getId(), - $comment - ); - } - } - } - - private function replaceUsernames(string $text): string { - foreach ($this->getImportService()->getConfig('uidRelation') as $trello => $nextcloud) { - $text = str_replace($trello, $nextcloud->getUID(), $text); - } - return $text; - } - - public function assignCardsToLabels(): void { - foreach ($this->getImportService()->getData()->cards as $trelloCard) { - foreach ($trelloCard->labels as $label) { - $this->getImportService()->assignCardToLabel( - $this->cards[$trelloCard->id]->getId(), - $this->labels[$label->id]->getId() - ); - } + $cards[$trelloCard->id] = $card; } + return $cards; } /** - * @return Stack[] + * @return Acl[] */ - public function getStacks(): array { + public function getAclList(): array { $return = []; - foreach ($this->getImportService()->getData()->lists as $order => $list) { - $stack = new Stack(); - if ($list->closed) { - $stack->setDeletedAt(time()); + foreach ($this->members as $member) { + if ($member->getUID() === $this->getImportService()->getConfig('owner')->getUID()) { + continue; } - $stack->setTitle($list->name); - $stack->setBoardId($this->getImportService()->getBoard()->getId()); - $stack->setOrder($order + 1); - $return[$list->id] = $stack; + $acl = new Acl(); + $acl->setBoardId($this->getImportService()->getBoard()->getId()); + $acl->setType(Acl::PERMISSION_TYPE_USER); + $acl->setParticipant($member->getUID()); + $acl->setPermissionEdit(false); + $acl->setPermissionShare(false); + $acl->setPermissionManage(false); + $return[] = $acl; } return $return; } - public function updateStack(string $id, Stack $stack): void { - $this->stacks[$id] = $stack; - } - private function translateColor(string $color): string { switch ($color) { case 'red': @@ -305,31 +280,42 @@ class BoardImportTrelloService extends ABoardImportService { } } - public function getBoard(): Board { - $board = new Board(); - if (empty($this->getImportService()->getData()->name)) { - throw new BadRequestException('Invalid name of board'); + private function replaceUsernames(string $text): string { + foreach ($this->getImportService()->getConfig('uidRelation') as $trello => $nextcloud) { + $text = str_replace($trello, $nextcloud->getUID(), $text); } - $board->setTitle($this->getImportService()->getData()->name); - $board->setOwner($this->getImportService()->getConfig('owner')->getUID()); - $board->setColor($this->getImportService()->getConfig('color')); - return $board; + return $text; } - public function importLabels(): array { - foreach ($this->getImportService()->getData()->labels as $label) { - if (empty($label->name)) { - $labelTitle = 'Unnamed ' . $label->color . ' label'; - } else { - $labelTitle = $label->name; - } - $newLabel = $this->getImportService()->createLabel( - $labelTitle, - $this->translateColor($label->color), - $this->getImportService()->getBoard()->getId() - ); - $this->labels[$label->id] = $newLabel; + private function checklistItem(\stdClass $item): string { + if (($item->state == 'incomplete')) { + $string_start = '- [ ]'; + } else { + $string_start = '- [x]'; + } + $check_item_string = $string_start . ' ' . $item->name . "\n"; + return $check_item_string; + } + + private function formulateChecklistText(\stdClass $checklist): string { + $checklist_string = "\n\n## {$checklist->name}\n"; + foreach ($checklist->checkItems as $item) { + $checklist_item_string = $this->checklistItem($item); + $checklist_string = $checklist_string . "\n" . $checklist_item_string; + } + return $checklist_string; + } + + private function appendAttachmentsToDescription(\stdClass $trelloCard): void { + if (empty($trelloCard->attachments)) { + return; + } + $trelloCard->desc .= "\n\n## {$this->l10n->t('Attachments')}\n"; + $trelloCard->desc .= "| {$this->l10n->t('File')} | {$this->l10n->t('date')} |\n"; + $trelloCard->desc .= "|---|---\n"; + foreach ($trelloCard->attachments as $attachment) { + $name = $attachment->name === $attachment->url ? null : $attachment->name; + $trelloCard->desc .= "| [{$name}]({$attachment->url}) | {$attachment->date} |\n"; } - return $this->labels; } } diff --git a/tests/data/config-trello.json b/tests/data/config-trello.json index 544118212..48a27f54e 100644 --- a/tests/data/config-trello.json +++ b/tests/data/config-trello.json @@ -2,6 +2,6 @@ "owner": "admin", "color": "0800fd", "uidRelation": { - "johndoe": "admin" + "johndoe": "johndoe" } } \ No newline at end of file diff --git a/tests/unit/Service/BoardImportServiceTest.php b/tests/unit/Service/BoardImportServiceTest.php index 9d0ccbd6b..e0baab7c3 100644 --- a/tests/unit/Service/BoardImportServiceTest.php +++ b/tests/unit/Service/BoardImportServiceTest.php @@ -22,38 +22,46 @@ */ namespace OCA\Deck\Service; +use OC\Comments\Comment; +use OCA\Deck\Db\Acl; use OCA\Deck\Db\AclMapper; +use OCA\Deck\Db\Assignment; use OCA\Deck\Db\AssignmentMapper; -use OCA\Deck\Db\Board; use OCA\Deck\Db\BoardMapper; +use OCA\Deck\Db\Card; use OCA\Deck\Db\CardMapper; +use OCA\Deck\Db\Label; use OCA\Deck\Db\LabelMapper; +use OCA\Deck\Db\Stack; use OCA\Deck\Db\StackMapper; use OCP\Comments\ICommentsManager; use OCP\IDBConnection; use OCP\IUser; use OCP\IUserManager; +use PHPUnit\Framework\MockObject\MockObject; class BoardImportServiceTest extends \Test\TestCase { - /** @var IDBConnection */ + /** @var IDBConnection|MockObject */ protected $dbConn; - /** @var IUserManager */ + /** @var IUserManager|MockObject */ private $userManager; - /** @var BoardMapper */ + /** @var BoardMapper|MockObject */ private $boardMapper; - /** @var AclMapper */ + /** @var AclMapper|MockObject */ private $aclMapper; - /** @var LabelMapper */ + /** @var LabelMapper|MockObject */ private $labelMapper; - /** @var StackMapper */ + /** @var StackMapper|MockObject */ private $stackMapper; - /** @var CardMapper */ + /** @var CardMapper|MockObject */ private $cardMapper; - /** @var AssignmentMapper */ + /** @var AssignmentMapper|MockObject */ private $assignmentMapper; - /** @var ICommentsManager */ + /** @var ICommentsManager|MockObject */ private $commentsManager; - /** @var BoardImportService */ + /** @var BoardImportTrelloService|MockObject */ + private $importTrelloService; + /** @var BoardImportService|MockObject */ private $boardImportService; public function setUp(): void { $this->dbConn = $this->createMock(IDBConnection::class); @@ -85,40 +93,83 @@ class BoardImportServiceTest extends \Test\TestCase { $configInstance = json_decode(file_get_contents(__DIR__ . '/../../data/config-trello.json')); $this->boardImportService->setConfigInstance($configInstance); + $this->importTrelloService = $this->createMock(BoardImportTrelloService::class); + $this->boardImportService->setImportSystem($this->importTrelloService); + $owner = $this->createMock(IUser::class); $owner ->method('getUID') ->willReturn('admin'); + + $johndoe = $this->createMock(IUser::class); + $johndoe + ->method('getUID') + ->willReturn('johndoe'); $this->userManager ->method('get') - ->willReturn($owner); + ->withConsecutive( + ['admin'], + ['johndoe'] + ) + ->willReturnonConsecutiveCalls( + $owner, + $johndoe + ); } public function testImportSuccess() { - $importService = $this->createMock(ABoardImportService::class); - $board = new Board(); - $importService - ->method('getBoard') - ->willReturn($board); - $this->boardImportService->setSystem('trello'); - $this->boardImportService->setImportSystem($importService); + $this->boardMapper + ->expects($this->once()) + ->method('insert'); + + $this->importTrelloService + ->method('getAclList') + ->willReturn([new Acl()]); + $this->aclMapper + ->expects($this->once()) + ->method('insert'); + + $this->importTrelloService + ->method('getLabels') + ->willReturn([new Label()]); + $this->labelMapper + ->expects($this->once()) + ->method('insert'); + + $this->importTrelloService + ->method('getStacks') + ->willReturn([new Stack()]); + $this->stackMapper + ->expects($this->once()) + ->method('insert'); + + $this->importTrelloService + ->method('getCards') + ->willReturn([new Card()]); + $this->cardMapper + ->expects($this->any()) + ->method('insert'); + + $this->importTrelloService + ->method('getComments') + ->willReturn([ + 'fakecardid' => [new Comment()] + ]); + $this->commentsManager + ->expects($this->once()) + ->method('save'); + + $this->importTrelloService + ->method('getCardAssignments') + ->willReturn([ + 'fakecardid' => [new Assignment()] + ]); + $this->assignmentMapper + ->expects($this->once()) + ->method('insert'); + $actual = $this->boardImportService->import(); - $this->assertNull($actual); - } - public function testImportBoard() { - $this->boardImportService->validateOwner(); - $actual = $this->boardImportService->importBoard(); - $this->assertNull($actual); - $board = $this->boardImportService->getBoard(); - $this->assertEquals('Test Board Name', $board->getTitle()); - $this->assertEquals('admin', $board->getOwner()); - $this->assertEquals('0800fd', $board->getColor()); - } - - public function testImportAcl() { - $this->markTestIncomplete(); - $actual = $this->boardImportService->importAcl(); $this->assertNull($actual); } } diff --git a/tests/unit/Service/BoardImportTrelloServiceTest.php b/tests/unit/Service/BoardImportTrelloServiceTest.php index dbfbcd7eb..734347008 100644 --- a/tests/unit/Service/BoardImportTrelloServiceTest.php +++ b/tests/unit/Service/BoardImportTrelloServiceTest.php @@ -22,7 +22,6 @@ */ namespace OCA\Deck\Service; -use OCA\Deck\Db\Board; use OCP\IL10N; use OCP\IUser; use OCP\IUserManager; @@ -114,39 +113,32 @@ class BoardImportTrelloServiceTest extends \Test\TestCase { $this->assertNull($actual); } - public function testGetBoardWithSuccess() { + public function testGetBoardWithNoName() { + $this->expectErrorMessage('Invalid name of board'); $importService = $this->createMock(BoardImportService::class); + $this->service->setImportService($importService); + $this->service->getBoard(); + } + + public function testGetBoardWithSuccess() { + $importService = \OC::$server->get(BoardImportService::class); + + $data = json_decode(file_get_contents(__DIR__ . '/../../data/data-trello.json')); + $importService->setData($data); + + $configInstance = json_decode(file_get_contents(__DIR__ . '/../../data/config-trello.json')); + $importService->setConfigInstance($configInstance); + $owner = $this->createMock(IUser::class); $owner ->method('getUID') ->willReturn('owner'); - $importService - ->method('getConfig') - ->withConsecutive( - ['owner'], - ['color'] - )->willReturnonConsecutiveCalls( - $owner, - '000000' - ); - $importService - ->method('getData') - ->willReturn(json_decode('{"name": "test"}')); + $importService->setConfig('owner', $owner); + $this->service->setImportService($importService); $actual = $this->service->getBoard(); - $this->assertInstanceOf(Board::class, $actual); - $this->assertEquals('test', $actual->getTitle()); + $this->assertEquals('Test Board Name', $actual->getTitle()); $this->assertEquals('owner', $actual->getOwner()); - $this->assertEquals('000000', $actual->getColor()); - } - - public function testGetBoardWithInvalidName() { - $this->expectErrorMessage('Invalid name of board'); - $importService = $this->createMock(BoardImportService::class); - $importService - ->method('getData') - ->willReturn(new \stdClass); - $this->service->setImportService($importService); - $this->service->getBoard(); + $this->assertEquals('0800fd', $actual->getColor()); } }