Default valute to board property fix command flow and refactor
Fixes on getBoard tests Refactor Reduce psalm info Refactor to implement pattern Change order of methods to put all abstract first and all public first Signed-off-by: Vitor Mattos <vitor@php.rio>
This commit is contained in:
committed by
Julius Härtl
parent
6714c89220
commit
19c609540b
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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()) {
|
||||
public function getCardAssignments(): array {
|
||||
$assignments = [];
|
||||
foreach ($this->getImportService()->getData()->cards as $trelloCard) {
|
||||
foreach ($trelloCard->idMembers as $idMember) {
|
||||
if (empty($this->members[$idMember])) {
|
||||
continue;
|
||||
}
|
||||
$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;
|
||||
$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;
|
||||
}
|
||||
}
|
||||
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';
|
||||
private function checklistItem(\stdClass $item): string {
|
||||
if (($item->state == 'incomplete')) {
|
||||
$string_start = '- [ ]';
|
||||
} else {
|
||||
$labelTitle = $label->name;
|
||||
$string_start = '- [x]';
|
||||
}
|
||||
$newLabel = $this->getImportService()->createLabel(
|
||||
$labelTitle,
|
||||
$this->translateColor($label->color),
|
||||
$this->getImportService()->getBoard()->getId()
|
||||
);
|
||||
$this->labels[$label->id] = $newLabel;
|
||||
$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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
"owner": "admin",
|
||||
"color": "0800fd",
|
||||
"uidRelation": {
|
||||
"johndoe": "admin"
|
||||
"johndoe": "johndoe"
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user