From 77bd39621eee0b549cf0261b6ebd1a5761c5b113 Mon Sep 17 00:00:00 2001 From: samin-z Date: Mon, 9 Mar 2026 12:04:18 +0100 Subject: [PATCH 1/8] add function for import/export Signed-off-by: samin-z --- lib/Db/BoardMapper.php | 5 +++ lib/Service/AssignmentService.php | 28 +++++++++++++ lib/Service/BoardService.php | 50 +++++++++++++++++++++++ lib/Service/CardService.php | 54 +++++++++++++++++++++++++ lib/Service/CommentService.php | 47 ++++++++++++++++++++++ lib/Service/FilesAppService.php | 66 +++++++++++++++++++++++++++++++ lib/Service/LabelService.php | 24 +++++++++++ lib/Service/StackService.php | 26 ++++++++++++ 8 files changed, 300 insertions(+) diff --git a/lib/Db/BoardMapper.php b/lib/Db/BoardMapper.php index 3589668190..522ad29d89 100644 --- a/lib/Db/BoardMapper.php +++ b/lib/Db/BoardMapper.php @@ -583,4 +583,9 @@ public function flushCache(?int $boardId = null, ?string $userId = null) { $this->userBoardCache = new CappedMemoryCache(); } } + + public function getDbConnection() { + + return $this->db; + } } diff --git a/lib/Service/AssignmentService.php b/lib/Service/AssignmentService.php index 4d9a97486d..a4b663c90e 100644 --- a/lib/Service/AssignmentService.php +++ b/lib/Service/AssignmentService.php @@ -23,6 +23,8 @@ use OCP\AppFramework\Db\DoesNotExistException; use OCP\AppFramework\Db\MultipleObjectsReturnedException; use OCP\EventDispatcher\IEventDispatcher; +use Psr\Log\LoggerInterface; +use Symfony\Component\CssSelector\Exception\InternalErrorException; class AssignmentService { @@ -64,6 +66,10 @@ class AssignmentService { * @var AssignmentServiceValidator */ private $assignmentServiceValidator; + /** + * @var LoggerInterface + */ + private $logger; public function __construct( @@ -77,6 +83,7 @@ public function __construct( IEventDispatcher $eventDispatcher, AssignmentServiceValidator $assignmentServiceValidator, $userId, + LoggerInterface $logger, ) { $this->assignmentServiceValidator = $assignmentServiceValidator; $this->permissionService = $permissionService; @@ -88,6 +95,7 @@ public function __construct( $this->activityManager = $activityManager; $this->eventDispatcher = $eventDispatcher; $this->currentUser = $userId; + $this->logger = $logger; } /** @@ -169,4 +177,24 @@ public function unassignUser(int $cardId, string $userId, int $type = 0): Assign } throw new NotFoundException('No assignment for ' . $userId . 'found.'); } + + /** + * @param int $cardId + * @param array $assignedUser + * + * @return void + */ + public function importAssignedUser(int $cardId, array $assignedUser): void { + $newAssignedUser = new Assignment(); + $newAssignedUser->setCardId($cardId); + $newAssignedUser->setParticipant($assignedUser['participant']['uid']); + $newAssignedUser->setType($assignedUser['type']); + + try { + $this->assignedUsersMapper->insert($newAssignedUser); + } catch (\Exception $e) { + $this->logger->error('importAssignedUser insert error: ' . $e->getMessage()); + throw new InternalErrorException('importAssignedUser insert error: ' . $e->getMessage()); + } + } } diff --git a/lib/Service/BoardService.php b/lib/Service/BoardService.php index faf7102bc1..4b39ceaf91 100644 --- a/lib/Service/BoardService.php +++ b/lib/Service/BoardService.php @@ -52,6 +52,8 @@ use OCP\Server; use Psr\Container\ContainerExceptionInterface; use Psr\Container\NotFoundExceptionInterface; +use Psr\Log\LoggerInterface; +use Symfony\Component\CssSelector\Exception\InternalErrorException; class BoardService { private ?array $boardsCacheFull = null; @@ -83,6 +85,7 @@ public function __construct( private ISecureRandom $random, private ConfigService $configService, private ?string $userId, + private LoggerInterface $logger, ) { } @@ -848,4 +851,51 @@ private function enrichWithCards(Board $board): void { $board->setStacks($stacks); } + + /** + * @param array $board + * @param string $userId + * + * @return Board + * + * @throws InternalErrorException + */ + public function importBoard(array $board, string $userId): Board { + $item = new Board(); + $item->setTitle($board['title']); + $item->setOwner($userId); + $item->setColor($board['color']); + $item->setArchived((bool)$board['archived']); + $item->setDeletedAt($board['deletedAt']); + $item->setLastModified($board['lastModified']); + try { + $newBoard = $this->boardMapper->insert($item); + } catch (\Exception $e) { + $this->logger->error('importBoard insert error: ' . $e->getMessage()); + throw new InternalErrorException('importBoard insert error: ' . $e->getMessage()); + } + return $newBoard; + } + + /** + * @param Board $board + * @param array $acl + * + * @return void + */ + public function importAcl(Board $board, array $acl): void { + $aclEntity = new Acl(); + $aclEntity->setBoardId($board->getId()); + $aclEntity->setType((int)$acl['type']); + $aclEntity->setParticipant($acl['participant']); + $aclEntity->setPermissionEdit((bool)$acl['permissionEdit']); + $aclEntity->setPermissionShare((bool)$acl['permissionShare']); + $aclEntity->setPermissionManage((bool)$acl['permissionManage']); + try { + $this->aclMapper->insert($aclEntity); + } catch (\Exception $e) { + $this->logger->error('importAcl insert error: ' . $e->getMessage()); + throw new InternalErrorException('importAcl insert error: ' . $e->getMessage()); + } + } } diff --git a/lib/Service/CardService.php b/lib/Service/CardService.php index 8f0406700d..08dd56671d 100644 --- a/lib/Service/CardService.php +++ b/lib/Service/CardService.php @@ -36,6 +36,7 @@ use OCP\IURLGenerator; use OCP\IUserManager; use Psr\Log\LoggerInterface; +use Symfony\Component\CssSelector\Exception\InternalErrorException; class CardService { public function __construct( @@ -640,4 +641,57 @@ public function getCardUrl(int $cardId): string { public function getRedirectUrlForCard(int $cardId): string { return $this->urlGenerator->linkToRouteAbsolute('deck.page.redirectToCard', ['cardId' => $cardId]); } + + /** + * @param int $stackId + * @param array $card + * + * @return Card + * + * @throws InternalErrorException + */ + public function importCard (int $stackId, array $card): Card { + $item = new Card(); + $item->setStackId($stackId); + $item->setTitle($card['title']); + $item->setType($card['type']); + $item->setOrder($card['order']); + $item->setOwner($card['owner']); + $item->setDescription($card['description']); + $item->setDuedate($card['duedate']); + $item->setLastModified($card['lastModified']); + $item->setLastEditor($card['lastEditor']); + $item->setCreatedAt($card['createdAt']); + $item->isArchived($card['archived']); + $item->setDeletedAt($card['deletedAt']); + $item->setDone($card['done']); + $item->setNotified($card['notified']); + + try { + $newCard = $this->cardMapper->insert($item); + } catch (\Exception $e) { + $this->logger->error('importCard insert error: ' . $e->getMessage()); + throw new InternalErrorException('importCard insert error: ' . $e->getMessage()); + } + + return $newCard; + } + + /** + * @param int $cardId + * @param int $boardId + * @param array $importedLabel + * + * @return void + */ + public function importLabels(int $cardId, int $boardId, array $importedLabel): void { + $labels = $this->labelMapper->findAll($boardId); + + foreach ($labels as $label) { + if ($label->getTitle() === $importedLabel['title'] && $label->getColor() === $importedLabel['color']) { + $this->cardMapper->assignLabel($cardId, $label->getId()); + } + } + $this->changeHelper->cardChanged($cardId); + } } diff --git a/lib/Service/CommentService.php b/lib/Service/CommentService.php index 72a48c66c8..550ee56da1 100644 --- a/lib/Service/CommentService.php +++ b/lib/Service/CommentService.php @@ -7,6 +7,7 @@ namespace OCA\Deck\Service; +use OC\Comments\Comment; use OCA\Deck\AppInfo\Application; use OCA\Deck\BadRequestException; use OCA\Deck\Db\Acl; @@ -21,6 +22,7 @@ use OCP\IUserManager; use OutOfBoundsException; use Psr\Log\LoggerInterface; +use Symfony\Component\CssSelector\Exception\InternalErrorException; class CommentService { @@ -188,4 +190,49 @@ private function formatComment(IComment $comment, bool $addReplyTo = false): arr } return $formattedComment; } + + public function exportAllForCard(int $cardId, int $limit = 1000, int $offset = 0): array { + $comments = $this->commentsManager->getForObject( + Application::COMMENT_ENTITY_TYPE, + (string)$cardId, + $limit, + $offset + ); + $allComments = []; + foreach ($comments as $comment) { + $formattedComment = $this->formatComment($comment); + try { + if ($comment->getParentId() !== '0' && $replyTo = $this->commentsManager->get($comment->getParentId())) { + $formattedComment['replyTo'] = $this->formatComment($replyTo); + } + } catch (CommentNotFoundException $e) { + } + $allComments[] = $formattedComment; + } + return $allComments; + } + + /** + * @param int $cardId + * @param array $comment + * @param string $parentId + * + * @return int + */ + public function importComment(int $cardId, array $comment, string $parentId = '0'): int { + try { + $newComment = new Comment(); + $newComment->setMessage($comment['message']); + $newComment->setObject(Application::COMMENT_ENTITY_TYPE, (string)$cardId); + $newComment->setVerb('comment'); + $newComment->setParentId($parentId); + $newComment->setActor($comment['actorType'], $comment['actorId']); + $newComment->setCreationDateTime(new \DateTime($comment['creationDateTime'])); + $this->commentsManager->save($newComment); + } catch (\Exception $e) { + $this->logger->error('importComment insert error: ' . $e->getMessage()); + throw new InternalErrorException('importComment insert error: ' . $e->getMessage()); + } + return (int)$newComment->getId(); + } } diff --git a/lib/Service/FilesAppService.php b/lib/Service/FilesAppService.php index 931668d037..76d0a45785 100644 --- a/lib/Service/FilesAppService.php +++ b/lib/Service/FilesAppService.php @@ -33,6 +33,7 @@ use OCP\Share\IManager; use OCP\Share\IShare; use Psr\Log\LoggerInterface; +use Symfony\Component\CssSelector\Exception\InternalErrorException; class FilesAppService implements IAttachmentService, ICustomAttachmentService { /** @@ -339,4 +340,69 @@ private function validateFilename(string $fileName): void { throw new BadRequestException($errorMessage); } } + + /** + * @param int[] $cardIds + * @return array + */ + public function getAllDeckSharesForCards(array $cardIds): array { + $qb = $this->connection->getQueryBuilder(); + $qb->select('*') + ->from('share') + ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(12))) + ->andWhere($qb->expr()->in('share_with', $qb->createParameter('cardIds'))); + $qb->setParameter('cardIds', $cardIds, Connection::PARAM_STR_ARRAY); + + $sql = $qb->getSQL(); + $params = $qb->getParameters(); + $shares = $qb->executeQuery()->fetchAllAssociative(); + return $shares; + } + + /** + * @param int $cardId + * @param array $shareData + * @param string $userId + * @return bool + */ + public function importDeckSharesForCard(int $cardId, array $shareData, int $fileId, string $userId): void { + try { + $insert = [ + 'share_type' => $shareData['share_type'] ?? 12, + 'share_with' => (string)$cardId, + 'uid_owner' => $userId, + 'uid_initiator' => $userId, + 'file_source' => $fileId, + 'file_target' => $shareData['file_target'], + 'permissions' => $shareData['permissions'] ?? 1, + 'stime' => $shareData['stime'] ?? time(), + 'parent' => $shareData['parent'], + 'item_type' => $shareData['item_type'] ?? 'file', + 'item_source' => $fileId, + 'item_target' => $shareData['item_target'], + 'token' => $shareData['token'], + 'mail_send' => $shareData['mail_send'], + 'share_name' => $shareData['share_name'], + 'note' => $shareData['note'], + 'label' => $shareData['label'], + 'hide_download' => $shareData['hide_download'], + 'expiration' => $shareData['expiration'], + 'accepted' => $shareData['accepted'], + 'password' => $shareData['password'], + 'password_by_talk' => $shareData['password_by_talk'], + 'attributes' => $shareData['attributes'], + 'password_expiration_time' => $shareData['password_expiration_time'], + 'reminder_sent' => $shareData['reminder_sent'], + ]; + $qb = $this->connection->getQueryBuilder(); + $qb->insert('share'); + foreach ($insert as $key => $value) { + $qb->setValue($key, $qb->createNamedParameter($value)); + } + $qb->executeStatement(); + } catch (\Throwable $e) { + $this->logger->error('importDeckSharesForCard insert error: ' . $e->getMessage()); + throw new InternalErrorException('importDeckSharesForCard insert error: ' . $e->getMessage()); + } + } } diff --git a/lib/Service/LabelService.php b/lib/Service/LabelService.php index 309100c748..5611c4f542 100644 --- a/lib/Service/LabelService.php +++ b/lib/Service/LabelService.php @@ -9,11 +9,14 @@ use OCA\Deck\BadRequestException; use OCA\Deck\Db\Acl; +use OCA\Deck\Db\Board; use OCA\Deck\Db\ChangeHelper; use OCA\Deck\Db\Label; use OCA\Deck\Db\LabelMapper; use OCA\Deck\StatusException; use OCA\Deck\Validators\LabelServiceValidator; +use Psr\Log\LoggerInterface; +use Symfony\Component\CssSelector\Exception\InternalErrorException; class LabelService { @@ -23,6 +26,7 @@ public function __construct( private BoardService $boardService, private ChangeHelper $changeHelper, private LabelServiceValidator $labelServiceValidator, + private LoggerInterface $logger, ) { } @@ -136,4 +140,24 @@ public function update(int $id, string $title, string $color): Label { return $this->labelMapper->update($label); } + + /** + * @param Board $board + * @param array $$label + * + * @return void + */ + public function importBoardLabel(Board $board, array $label): void { + $labelEntity = new Label(); + $labelEntity->setBoardId($board->getId()); + $labelEntity->setTitle($label['title']); + $labelEntity->setColor($label['color']); + $labelEntity->setLastModified($label['lastModified']); + try { + $this->labelMapper->insert($labelEntity); + } catch (\Throwable $e) { + $this->logger->error('importBoardLabel insert error: ' . $e->getMessage()); + throw new InternalErrorException('importBoardLabel insert error: ' . $e->getMessage()); + } + } } diff --git a/lib/Service/StackService.php b/lib/Service/StackService.php index c2aed66e57..dc5ff4ee16 100644 --- a/lib/Service/StackService.php +++ b/lib/Service/StackService.php @@ -26,6 +26,7 @@ use OCA\Deck\Validators\StackServiceValidator; use OCP\EventDispatcher\IEventDispatcher; use Psr\Log\LoggerInterface; +use Symfony\Component\CssSelector\Exception\InternalErrorException; class StackService { private StackMapper $stackMapper; @@ -304,4 +305,29 @@ public function reorder(int $id, int $order): array { return $result; } + + /** + * @param int $boardId + * @param array $stack + * + * @return Stack + * + * @throws InternalErrorException + */ + public function importStack(int $boardId, array $stack): Stack { + $item = new Stack(); + $item->setBoardId($boardId); + $item->setTitle($stack['title']); + $item->setDeletedAt($stack['deletedAt']); + $item->setLastModified($stack['lastModified']); + $item->setOrder($stack['order']); + try { + $newStack = $this->stackMapper->insert($item); + } catch (\Exception $e) { + $this->logger->error('importStack insert error: ' . $e->getMessage()); + throw new InternalErrorException('importStack insert error: ' . $e->getMessage()); + } + + return $newStack; + } } From 34b098d54bb3c586debe7b373883d7db9aa04bc9 Mon Sep 17 00:00:00 2001 From: samin-z Date: Mon, 16 Mar 2026 18:15:44 +0100 Subject: [PATCH 2/8] update services Signed-off-by: samin-z --- lib/Errors/InternalError.php | 16 ++++++++++++++++ lib/Service/AssignmentService.php | 6 ++++-- lib/Service/BoardService.php | 5 ++++- lib/Service/CardService.php | 14 +++++++------- lib/Service/CommentService.php | 3 ++- lib/Service/FilesAppService.php | 8 ++++++-- lib/Service/LabelService.php | 8 +++++--- lib/Service/StackService.php | 12 ++++++------ 8 files changed, 50 insertions(+), 22 deletions(-) create mode 100644 lib/Errors/InternalError.php diff --git a/lib/Errors/InternalError.php b/lib/Errors/InternalError.php new file mode 100644 index 0000000000..8790991b41 --- /dev/null +++ b/lib/Errors/InternalError.php @@ -0,0 +1,16 @@ +assignedUsersMapper->insert($newAssignedUser); } catch (\Exception $e) { $this->logger->error('importAssignedUser insert error: ' . $e->getMessage()); - throw new InternalErrorException('importAssignedUser insert error: ' . $e->getMessage()); + throw new InternalError('importAssignedUser insert error: ' . $e->getMessage()); } } } diff --git a/lib/Service/BoardService.php b/lib/Service/BoardService.php index 4b39ceaf91..8d30ac743d 100644 --- a/lib/Service/BoardService.php +++ b/lib/Service/BoardService.php @@ -27,6 +27,7 @@ use OCA\Deck\Db\SessionMapper; use OCA\Deck\Db\Stack; use OCA\Deck\Db\StackMapper; +use OCA\Deck\Errors\InternalError; use OCA\Deck\Event\AclCreatedEvent; use OCA\Deck\Event\AclDeletedEvent; use OCA\Deck\Event\AclUpdatedEvent; @@ -882,6 +883,8 @@ public function importBoard(array $board, string $userId): Board { * @param array $acl * * @return void + * + * @throws InternalError */ public function importAcl(Board $board, array $acl): void { $aclEntity = new Acl(); @@ -895,7 +898,7 @@ public function importAcl(Board $board, array $acl): void { $this->aclMapper->insert($aclEntity); } catch (\Exception $e) { $this->logger->error('importAcl insert error: ' . $e->getMessage()); - throw new InternalErrorException('importAcl insert error: ' . $e->getMessage()); + throw new InternalError('importAcl insert error: ' . $e->getMessage()); } } } diff --git a/lib/Service/CardService.php b/lib/Service/CardService.php index 08dd56671d..8244f13962 100644 --- a/lib/Service/CardService.php +++ b/lib/Service/CardService.php @@ -20,6 +20,7 @@ use OCA\Deck\Db\Label; use OCA\Deck\Db\LabelMapper; use OCA\Deck\Db\StackMapper; +use OCA\Deck\Errors\InternalError; use OCA\Deck\Event\CardCreatedEvent; use OCA\Deck\Event\CardDeletedEvent; use OCA\Deck\Event\CardUpdatedEvent; @@ -36,7 +37,6 @@ use OCP\IURLGenerator; use OCP\IUserManager; use Psr\Log\LoggerInterface; -use Symfony\Component\CssSelector\Exception\InternalErrorException; class CardService { public function __construct( @@ -646,11 +646,11 @@ public function getRedirectUrlForCard(int $cardId): string { * @param int $stackId * @param array $card * - * @return Card + * @return int * - * @throws InternalErrorException + * @throws InternalError */ - public function importCard (int $stackId, array $card): Card { + public function importCard (int $stackId, array $card): int { $item = new Card(); $item->setStackId($stackId); $item->setTitle($card['title']); @@ -662,7 +662,7 @@ public function importCard (int $stackId, array $card): Card { $item->setLastModified($card['lastModified']); $item->setLastEditor($card['lastEditor']); $item->setCreatedAt($card['createdAt']); - $item->isArchived($card['archived']); + $item->setArchived($card['archived']); $item->setDeletedAt($card['deletedAt']); $item->setDone($card['done']); $item->setNotified($card['notified']); @@ -671,10 +671,10 @@ public function importCard (int $stackId, array $card): Card { $newCard = $this->cardMapper->insert($item); } catch (\Exception $e) { $this->logger->error('importCard insert error: ' . $e->getMessage()); - throw new InternalErrorException('importCard insert error: ' . $e->getMessage()); + throw new InternalError('importCard insert error: ' . $e->getMessage()); } - return $newCard; + return $newCard->getId(); } /** diff --git a/lib/Service/CommentService.php b/lib/Service/CommentService.php index 550ee56da1..f7b42da350 100644 --- a/lib/Service/CommentService.php +++ b/lib/Service/CommentService.php @@ -12,6 +12,7 @@ use OCA\Deck\BadRequestException; use OCA\Deck\Db\Acl; use OCA\Deck\Db\CardMapper; +use OCA\Deck\Errors\InternalError; use OCA\Deck\NoPermissionException; use OCA\Deck\NotFoundException; use OCP\AppFramework\Http\DataResponse; @@ -231,7 +232,7 @@ public function importComment(int $cardId, array $comment, string $parentId = '0 $this->commentsManager->save($newComment); } catch (\Exception $e) { $this->logger->error('importComment insert error: ' . $e->getMessage()); - throw new InternalErrorException('importComment insert error: ' . $e->getMessage()); + throw new InternalError('importComment insert error: ' . $e->getMessage()); } return (int)$newComment->getId(); } diff --git a/lib/Service/FilesAppService.php b/lib/Service/FilesAppService.php index 76d0a45785..0efe2b23b4 100644 --- a/lib/Service/FilesAppService.php +++ b/lib/Service/FilesAppService.php @@ -9,10 +9,12 @@ namespace OCA\Deck\Service; +use Doctrine\DBAL\Connection; use OCA\Deck\BadRequestException; use OCA\Deck\Db\Acl; use OCA\Deck\Db\Attachment; use OCA\Deck\Db\CardMapper; +use OCA\Deck\Errors\InternalError; use OCA\Deck\NoPermissionException; use OCA\Deck\Sharing\DeckShareProvider; use OCA\Deck\StatusException; @@ -33,7 +35,6 @@ use OCP\Share\IManager; use OCP\Share\IShare; use Psr\Log\LoggerInterface; -use Symfony\Component\CssSelector\Exception\InternalErrorException; class FilesAppService implements IAttachmentService, ICustomAttachmentService { /** @@ -363,7 +364,10 @@ public function getAllDeckSharesForCards(array $cardIds): array { * @param int $cardId * @param array $shareData * @param string $userId + * * @return bool + * + * @throws InternalError */ public function importDeckSharesForCard(int $cardId, array $shareData, int $fileId, string $userId): void { try { @@ -402,7 +406,7 @@ public function importDeckSharesForCard(int $cardId, array $shareData, int $file $qb->executeStatement(); } catch (\Throwable $e) { $this->logger->error('importDeckSharesForCard insert error: ' . $e->getMessage()); - throw new InternalErrorException('importDeckSharesForCard insert error: ' . $e->getMessage()); + throw new InternalError('importDeckSharesForCard insert error: ' . $e->getMessage()); } } } diff --git a/lib/Service/LabelService.php b/lib/Service/LabelService.php index 5611c4f542..859313f0fc 100644 --- a/lib/Service/LabelService.php +++ b/lib/Service/LabelService.php @@ -13,10 +13,10 @@ use OCA\Deck\Db\ChangeHelper; use OCA\Deck\Db\Label; use OCA\Deck\Db\LabelMapper; +use OCA\Deck\Errors\InternalError; use OCA\Deck\StatusException; use OCA\Deck\Validators\LabelServiceValidator; use Psr\Log\LoggerInterface; -use Symfony\Component\CssSelector\Exception\InternalErrorException; class LabelService { @@ -143,9 +143,11 @@ public function update(int $id, string $title, string $color): Label { /** * @param Board $board - * @param array $$label + * @param array $label * * @return void + * + * @throws InternalError */ public function importBoardLabel(Board $board, array $label): void { $labelEntity = new Label(); @@ -157,7 +159,7 @@ public function importBoardLabel(Board $board, array $label): void { $this->labelMapper->insert($labelEntity); } catch (\Throwable $e) { $this->logger->error('importBoardLabel insert error: ' . $e->getMessage()); - throw new InternalErrorException('importBoardLabel insert error: ' . $e->getMessage()); + throw new InternalError('importBoardLabel insert error: ' . $e->getMessage()); } } } diff --git a/lib/Service/StackService.php b/lib/Service/StackService.php index dc5ff4ee16..8ef5261b8c 100644 --- a/lib/Service/StackService.php +++ b/lib/Service/StackService.php @@ -19,6 +19,7 @@ use OCA\Deck\Db\LabelMapper; use OCA\Deck\Db\Stack; use OCA\Deck\Db\StackMapper; +use OCA\Deck\Errors\InternalError; use OCA\Deck\Event\BoardUpdatedEvent; use OCA\Deck\Model\CardDetails; use OCA\Deck\NoPermissionException; @@ -26,7 +27,6 @@ use OCA\Deck\Validators\StackServiceValidator; use OCP\EventDispatcher\IEventDispatcher; use Psr\Log\LoggerInterface; -use Symfony\Component\CssSelector\Exception\InternalErrorException; class StackService { private StackMapper $stackMapper; @@ -310,11 +310,11 @@ public function reorder(int $id, int $order): array { * @param int $boardId * @param array $stack * - * @return Stack + * @return int * - * @throws InternalErrorException + * @throws InternalError */ - public function importStack(int $boardId, array $stack): Stack { + public function importStack(int $boardId, array $stack): int { $item = new Stack(); $item->setBoardId($boardId); $item->setTitle($stack['title']); @@ -325,9 +325,9 @@ public function importStack(int $boardId, array $stack): Stack { $newStack = $this->stackMapper->insert($item); } catch (\Exception $e) { $this->logger->error('importStack insert error: ' . $e->getMessage()); - throw new InternalErrorException('importStack insert error: ' . $e->getMessage()); + throw new InternalError('importStack insert error: ' . $e->getMessage()); } - return $newStack; + return $newStack->getId(); } } From 80c6128b4e56a8fbafaaa5e0c692577286b7132a Mon Sep 17 00:00:00 2001 From: samin-z Date: Tue, 17 Mar 2026 10:43:50 +0100 Subject: [PATCH 3/8] cs fixes Signed-off-by: samin-z --- lib/Errors/InternalError.php | 4 +--- lib/Service/AssignmentService.php | 2 +- lib/Service/CardService.php | 2 +- lib/Service/CommentService.php | 1 - 4 files changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/Errors/InternalError.php b/lib/Errors/InternalError.php index 8790991b41..a85abd6a96 100644 --- a/lib/Errors/InternalError.php +++ b/lib/Errors/InternalError.php @@ -9,8 +9,6 @@ namespace OCA\Deck\Errors; -class InternalError extends \Exception -{ +class InternalError extends \Exception { } - diff --git a/lib/Service/AssignmentService.php b/lib/Service/AssignmentService.php index a3a69b1342..62d6ec7292 100644 --- a/lib/Service/AssignmentService.php +++ b/lib/Service/AssignmentService.php @@ -15,12 +15,12 @@ use OCA\Deck\Db\AssignmentMapper; use OCA\Deck\Db\CardMapper; use OCA\Deck\Db\ChangeHelper; +use OCA\Deck\Errors\InternalError; use OCA\Deck\Event\CardUpdatedEvent; use OCA\Deck\NoPermissionException; use OCA\Deck\NotFoundException; use OCA\Deck\Notification\NotificationHelper; use OCA\Deck\Validators\AssignmentServiceValidator; -use OCA\Deck\Errors\InternalError; use OCP\AppFramework\Db\DoesNotExistException; use OCP\AppFramework\Db\MultipleObjectsReturnedException; use OCP\EventDispatcher\IEventDispatcher; diff --git a/lib/Service/CardService.php b/lib/Service/CardService.php index 8244f13962..155dc45876 100644 --- a/lib/Service/CardService.php +++ b/lib/Service/CardService.php @@ -650,7 +650,7 @@ public function getRedirectUrlForCard(int $cardId): string { * * @throws InternalError */ - public function importCard (int $stackId, array $card): int { + public function importCard(int $stackId, array $card): int { $item = new Card(); $item->setStackId($stackId); $item->setTitle($card['title']); diff --git a/lib/Service/CommentService.php b/lib/Service/CommentService.php index f7b42da350..f58ade4ac1 100644 --- a/lib/Service/CommentService.php +++ b/lib/Service/CommentService.php @@ -23,7 +23,6 @@ use OCP\IUserManager; use OutOfBoundsException; use Psr\Log\LoggerInterface; -use Symfony\Component\CssSelector\Exception\InternalErrorException; class CommentService { From 4999a763f300a00414e92fe8c6acccc76b16cc29 Mon Sep 17 00:00:00 2001 From: samin-z Date: Tue, 17 Mar 2026 14:03:25 +0100 Subject: [PATCH 4/8] add DeckMigrator plus test Signed-off-by: samin-z --- lib/AppInfo/Application.php | 2 + lib/UserMigration/DeckMigrator.php | 476 +++++++++++++++++++++++++++++ tests/unit/DeckMigratorTest.php | 142 +++++++++ 3 files changed, 620 insertions(+) create mode 100644 lib/UserMigration/DeckMigrator.php create mode 100644 tests/unit/DeckMigratorTest.php diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 234af609fa..9f59f32550 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -52,6 +52,7 @@ use OCA\Deck\Sharing\Listener; use OCA\Deck\Teams\DeckTeamResourceProvider; use OCA\Text\Event\LoadEditor; +use OCA\Deck\UserMigration\DeckMigrator; use OCP\AppFramework\App; use OCP\AppFramework\Bootstrap\IBootContext; use OCP\AppFramework\Bootstrap\IBootstrap; @@ -181,6 +182,7 @@ public function register(IRegistrationContext $context): void { $context->registerEventListener(LoadAdditionalScriptsEvent::class, ResourceAdditionalScriptsListener::class); $context->registerTeamResourceProvider(DeckTeamResourceProvider::class); + $context->registerUserMigrator(DeckMigrator::class); } public function registerCommentsEntity(IEventDispatcher $eventDispatcher): void { diff --git a/lib/UserMigration/DeckMigrator.php b/lib/UserMigration/DeckMigrator.php new file mode 100644 index 0000000000..a3e98529eb --- /dev/null +++ b/lib/UserMigration/DeckMigrator.php @@ -0,0 +1,476 @@ +getUID(); + + try { + $boards = $this->boardMapper->findAllByUser($userId); + $exportDestination->addFileContents(self::BOARDS, json_encode($boards)); + + $boardAcls = []; + $boardLabels = []; + $boardStacks = []; + $stackCards = []; + $cardComments = []; + $cardAttachments = []; + foreach ($boards as $board) { + $acls = $this->aclMapper->findAll($board->getId()); + foreach ($acls as $acl) { + $boardAcls[] = $acl; + } + + $labels = $this->labelMapper->findAll($board->getId()); + $boardLabels = array_merge($boardLabels, $labels); + + list($newStacks, $newCards, $newComments) = $this->exportStacksCardsCommentsSimple($board->getId()); + $boardStacks = array_merge($boardStacks, $newStacks); + $stackCards = array_merge($stackCards, $newCards); + $cardComments = array_merge($cardComments, $newComments); + } + + $exportDestination->addFileContents(self::BOARD_ACLS, json_encode($boardAcls)); + $exportDestination->addFileContents(self::BOARD_LABELS, json_encode($boardLabels)); + $exportDestination->addFileContents(self::BOARD_STACKS, json_encode($boardStacks)); + $exportDestination->addFileContents(self::STACK_CARDS, json_encode($stackCards)); + usort($cardComments, function ($firstComment, $secondComment) { + return ($firstComment['id'] ?? 0) <=> ($secondComment['id'] ?? 0); + }); + $exportDestination->addFileContents(self::CARD_COMMENTS, json_encode($cardComments)); + + $cardIds = array_map(fn ($c) => $c->getId(), $stackCards); + $cardAssignments = $this->assignmentMapper->findIn($cardIds); + $exportDestination->addFileContents(self::CARD_ASSIGNED, json_encode($cardAssignments)); + + $cardLabels = $this->labelMapper->findAssignedLabelsForCards($cardIds); + $exportDestination->addFileContents(self::CARD_LABELS, json_encode($cardLabels)); + + $cardAttachments = $this->filesAppService->getAllDeckSharesForCards($cardIds); + $exportDestination->addFileContents(self::CARD_ATTACHMENTS, json_encode($cardAttachments)); + + $this->exportCardAttachmentsFiles($cardAttachments, $userId, $exportDestination); + + $output->writeln('Export completed.'); + } catch (\Throwable $e) { + throw new InternalError('Deck export error: ' . $e->getMessage()); + } + + } + + /** + * @param array $cardAttachments + * @param string $userId + * @param IExportDestination $exportDestination + * + * @return void + */ + private function exportCardAttachmentsFiles(array $cardAttachments, string $userId, IExportDestination $exportDestination): void { + foreach ($cardAttachments as $share) { + if (!empty($share['file_target'])) { + $fileTarget = $share['file_target']; + $fileTargetClean = str_replace('{DECK_PLACEHOLDER}/', '', ltrim($fileTarget, '/')); + if (strpos($fileTargetClean, 'Deck/') !== 0) { + $fileTargetClean = 'Deck/' . $fileTargetClean; + } + $baseDataDir = $this->config->getSystemValue('datadirectory', '/var/www/html/data'); + $username = $share['uid_owner'] ?? $userId; + $filePath = $baseDataDir . '/' . $username . '/files/' . $fileTargetClean; + if (is_readable($filePath)) { + $fileContents = file_get_contents($filePath); + $exportPath = 'files/' . $fileTargetClean; + $exportDestination->addFileContents($exportPath, $fileContents); + } + } + } + } + + /** + * @param int $boardId + * + * @return array[] [$stacks, $cards, $comments] + */ + private function exportStacksCardsCommentsSimple(int $boardId): array { + $stacks = $this->stackMapper->findAll($boardId); + $allBoardCards = []; + $allComments = []; + foreach ($stacks as $stack) { + $stackUnarchivedCards = $this->cardMapper->findAll($stack->getId()); + $stackArchivedCards = $this->cardMapper->findAllArchived($stack->getId()); + $allBoardCards = array_merge($allBoardCards, $stackUnarchivedCards, $stackArchivedCards); + $stackAllCards = array_merge($stackUnarchivedCards, $stackArchivedCards); + foreach ($stackAllCards as $card) { + $comments = $this->commentService->exportAllForCard($card->getId()); + $allComments = array_merge($allComments, $comments); + } + } + return [$stacks, $allBoardCards, $allComments]; + } + + /** + * {@inheritDoc} + */ + public function import( + IUser $user, + IImportSource $importSource, + OutputInterface $output, + ): void { + if ($importSource->getMigratorVersion($this->getId()) === null) { + $output->writeln('No version for migrator ' . $this->getId() . ' (' . static::class . '), skipping import…'); + return; + } + $output->writeln('Importing boards, cards, comments, shares...'); + + $boards = json_decode($importSource->getFileContents(self::BOARDS), true, self::JSON_DEPTH, self::JSON_OPTIONS); + $userId = $user->getUID(); + $connection = $this->boardMapper->getDbConnection(); + $connection->beginTransaction(); + + try { + $boardIdMap = []; + $cardIdMap = []; + $stackIdMap = []; + $commentIdMap = []; + foreach ($boards as $board) { + $newBoard = $this->boardService->importBoard($board, $userId); + $boardIdMap[$board['id']] = $newBoard->getId(); + + $this->importBoardLabels($importSource, $newBoard, $board['id']); + $this->importBoardAcls($importSource, $newBoard, $board['id']); + } + + $this->importBoardStacks($importSource, $boardIdMap, $stackIdMap); + $this->importStackCards($importSource, $stackIdMap, $cardIdMap); + $this->importCardLabels($importSource, $cardIdMap, $boardIdMap); + $this->importCardAssignments($importSource, $cardIdMap); + $this->importCardComments($importSource, $cardIdMap, $commentIdMap); + $this->importCardAttachment($importSource, $userId, $cardIdMap); + + + $connection->commit(); + } catch (\Throwable $e) { + $connection->rollBack(); + throw $e; + } + + $output->writeln('Import completed.'); + } + + /** + * @param IImportSource $importSource + * @param string $userId + * @param array $cardIdMap + * + * @return void + */ + private function importCardAttachment(IImportSource $importSource, string $userId, array $cardIdMap ): void { + $cardAttachments = json_decode($importSource->getFileContents(self::CARD_ATTACHMENTS), true); + $userFolder = $this->rootFolder->getUserFolder($userId); + try { + $deckFolder = $userFolder->get('Deck'); + } catch (NotFoundException $e) { + $deckFolder = $userFolder->newFolder('Deck'); + } + + foreach ($cardAttachments as $share) { + $this->importDeckAttachment($share, $deckFolder, $importSource, $cardIdMap, $userId); + } + } + + /** + * @param array $share + * @param Folder $deckFolder + * @param IImportSource $importSource + * @param array $cardIdMap + * @param string $userId + */ + private function importDeckAttachment( + array $share, + Folder $deckFolder, + IImportSource $importSource, + array $cardIdMap, + string $userId + ): void { + $fileTarget = $share['file_target']; + $fileTargetClean = str_replace('{DECK_PLACEHOLDER}/', '', ltrim($fileTarget, '/')); + if (strpos($fileTargetClean, 'Deck/') !== 0) { + $fileTargetClean = 'Deck/' . $fileTargetClean; + } + $importPath = 'files/' . $fileTargetClean; + $relativePath = substr($fileTargetClean, strlen('Deck/')); + $parts = explode('/', $relativePath); + if (empty($parts)) { + return; + } + + $currentFolder = $this->traverseOrCreateFolders($deckFolder, $parts); + $fileName = array_pop($parts); + if ($fileName === null) { + return; + } + + $fileId = null; + if ($currentFolder->nodeExists($fileName)) { + $file = $currentFolder->get($fileName); + $fileId = $file->getId(); + } else { + try { + $fileContents = $importSource->getFileContents($importPath); + } catch (\Throwable $e) { + return; + } + $file = $currentFolder->newFile($fileName); + $file->putContent($fileContents); + $fileId = $file->getId(); + } + + $newCardId = $cardIdMap[$share['share_with']] ?? $share['share_with']; + $this->filesAppService->importDeckSharesForCard($newCardId, $share, $fileId, $userId); + } + + /** + * @param Folder $baseFolder + * @param array $parts + * @return Folder + */ + private function traverseOrCreateFolders(Folder $baseFolder, array $parts): Folder { + $currentFolder = $baseFolder; + for ($i = 0, $n = count($parts) - 1; $i < $n; $i++) { + $part = $parts[$i]; + try { + $currentFolder = $currentFolder->get($part); + } catch (NotFoundException $e) { + $currentFolder = $currentFolder->newFolder($part); + } + } + return $currentFolder; + } + + /** + * @param IImportSource $importSource + * @param Board $newBoard + * @param int $oldBoardId + * + * @return void + */ + private function importBoardLabels(IImportSource $importSource, Board $newBoard, int $oldBoardId): void { + $boardLabels = json_decode($importSource->getFileContents(self::BOARD_LABELS), true); + foreach ($boardLabels as $label) { + if ($label['boardId'] === $oldBoardId) { + $this->labelService->importBoardLabel($newBoard, $label); + } + } + } + + /** + * @param IImportSource $importSource + * @param Board $newBoard + * @param int $oldBoardId + * + * @return void + */ + private function importBoardAcls(IImportSource $importSource, Board $newBoard, int $oldBoardId): void { + $boardAcls = json_decode($importSource->getFileContents(self::BOARD_ACLS), true); + foreach ($boardAcls as $acl) { + if ($acl['boardId'] === $oldBoardId) { + $this->boardService->importAcl($newBoard, $acl); + } + } + } + + /** + * @param IImportSource $importSource + * @param array $boardIdMap + * @param array $stackIdMap + * + * @return void + */ + private function importBoardStacks(IImportSource $importSource, array $boardIdMap, array &$stackIdMap): void { + $stacks = json_decode($importSource->getFileContents(self::BOARD_STACKS), true, self::JSON_DEPTH, self::JSON_OPTIONS); + foreach ($stacks as $stack) { + $newStackId = $this->stackService->importStack($boardIdMap[$stack['boardId']], $stack); + $stackIdMap[$stack['id']] = $newStackId; + } + } + + /** + * @param IImportSource $importSource + * @param array $stackIdMap + * @param array $cardIdMap + * + * @return void + */ + private function importStackCards(IImportSource $importSource, array $stackIdMap, array &$cardIdMap): void { + $stackCards = json_decode($importSource->getFileContents(self::STACK_CARDS), true); + foreach ($stackCards as $card) { + if (isset($stackIdMap[$card['stackId']])) { + $newCardId = $this->cardService->importCard($stackIdMap[$card['stackId']], $card); + $cardIdMap[$card['id']] = $newCardId; + } + } + } + + /** + * @param IImportSource $importSource + * @param array $cardIdMap + * @param array $boardIdMap + * + * @return void + */ + private function importCardLabels(IImportSource $importSource, array $cardIdMap, array $boardIdMap): void { + $cardLabels = json_decode($importSource->getFileContents(self::CARD_LABELS), true); + foreach ($cardLabels as $label) { + $newCardId = $cardIdMap[$label['cardId']] ?? null; + $newBoardId = $boardIdMap[$label['boardId']] ?? null; + if ($newCardId && $newBoardId) { + $this->cardService->importLabels($newCardId, $newBoardId, $label); + } + } + } + + /** + * @param IImportSource $importSource + * @param array $cardIdMap + * @param array $commentIdMap + * + * @return void + */ + private function importCardComments(IImportSource $importSource, array $cardIdMap, array $commentIdMap): void { + $cardComments = json_decode($importSource->getFileContents(self::CARD_COMMENTS), true); + + foreach ($cardComments as $comment) { + $cardId = $cardIdMap[$comment['objectId']] ?? null; + $parentId = '0'; + $replyToId = $comment['replyTo']['id'] ?? null; + if (isset($replyToId) && isset($commentIdMap[$replyToId])) { + $parentId = (string)$commentIdMap[$replyToId]; + } + $newCommentId = $this->commentService->importComment($cardId, $comment, $parentId); + $commentIdMap[$comment['id']] = $newCommentId; + } + } + + /** + * @param IImportSource $importSource + * @param array $cardIdMap + * + * @return void + */ + private function importCardAssignments(IImportSource $importSource, array $cardIdMap): void { + $cardAssignedUsers = json_decode($importSource->getFileContents(self::CARD_ASSIGNED), true); + foreach ($cardAssignedUsers as $assignedUser) { + if (isset($cardIdMap[$assignedUser['cardId']])) { + $this->assignmentService->importAssignedUser($cardIdMap[$assignedUser['cardId']], $assignedUser); + } + } + } + + /** + * {@inheritDoc} + */ + public function getId(): string { + return 'decks'; + } + + /** + * {@inheritDoc} + */ + public function getDisplayName(): string { + return $this->l10n->t('Decks'); + } + + /** + * {@inheritDoc} + */ + public function getDescription(): string { + return $this->l10n->t('All Boards, cards, comments, shares, and relations'); + } +} diff --git a/tests/unit/DeckMigratorTest.php b/tests/unit/DeckMigratorTest.php new file mode 100644 index 0000000000..25598e90f1 --- /dev/null +++ b/tests/unit/DeckMigratorTest.php @@ -0,0 +1,142 @@ +rootFolder = $this->createMock(IRootFolder::class); + $this->l10n = $this->createMock(IL10N::class); + $this->userFolder = $this->createMock(Folder::class); + $this->userFolder + ->method('getPath') + ->willReturn('/tmp/testuser'); + $this->rootFolder + ->method('getUserFolder') + ->willReturn($this->userFolder); + + $mockBoardService = $this->createMock(BoardService::class); + $mockBoardMapper = $this->createMock(BoardMapper::class); + $mockConnection = $this->getMockBuilder('stdClass') + ->addMethods(['beginTransaction', 'commit', 'rollBack']) + ->getMock(); + $mockConnection->method('beginTransaction')->willReturn(null); + $mockConnection->method('commit')->willReturn(null); + $mockConnection->method('rollBack')->willReturn(null); + $mockBoardMapper->method('getDbConnection')->willReturn($mockConnection); + $mockAclMapper = $this->createMock(AclMapper::class); + $mockLabelMapper = $this->createMock(LabelMapper::class); + $mockStackMapper = $this->createMock(StackMapper::class); + $mockCardMapper = $this->createMock(CardMapper::class); + $mockAssignmentMapper = $this->createMock(AssignmentMapper::class); + $mockCommentService = $this->createMock(CommentService::class); + $mockFilesAppService = $this->createMock(FilesAppService::class); + $mockConfig = $this->createMock(IConfig::class); + $mockStackService = $this->createMock(StackService::class); + $mockLabelService = $this->createMock(LabelService::class); + $mockCardService = $this->createMock(CardService::class); + $mockAssignmentService = $this->createMock(AssignmentService::class); + $mockLogger = $this->createMock(LoggerInterface::class); + + $this->deckMigrator = new DeckMigrator( + $this->l10n, + $this->rootFolder, + $mockBoardService, + $mockBoardMapper, + $mockAclMapper, + $mockLabelMapper, + $mockStackMapper, + $mockCardMapper, + $mockAssignmentMapper, + $mockCommentService, + $mockFilesAppService, + $mockConfig, + $mockStackService, + $mockLabelService, + $mockCardService, + $mockAssignmentService, + $mockLogger + ); + } + + public function testGetEstimatedExportSize(): void { + $user = $this->createMock(IUser::class); + $this->assertIsNumeric($this->deckMigrator->getEstimatedExportSize($user)); + } + + public function testExport(): void { + $user = $this->createMock(IUser::class); + $user->expects($this->once())->method('getUID')->willReturn('testuser'); + $exportDestination = $this->createMock(IExportDestination::class); + $output = $this->createMock(OutputInterface::class); + + $this->deckMigrator->export($user, $exportDestination, $output); + } + + public function testImport(): void { + $user = $this->createMock(IUser::class); + $user->expects($this->once())->method('getUID')->willReturn('testuser'); + $importSource = $this->createMock(IImportSource::class); + $output = $this->createMock(OutputInterface::class); + + $importSource + ->method('getMigratorVersion') + ->with('decks') + ->willReturn(1); + + $importSource + ->method('getFileContents') + ->willReturnMap([ + ['boards.json', '[]'], + ['board_labels.json', '[]'], + ['board_acl.json', '[]'], + ['board_stacks.json', '[]'], + ['stack_cards.json', '[]'], + ['card_labels.json', '[]'], + ['card_assigned.json', '[]'], + ['card_comments.json', '[]'], + ['card_attachments.json', '[]'], + ]); + + $this->deckMigrator->import($user, $importSource, $output); + } +} From 2d7a551c9cae6e1bafa46505d6a71cf292b7cb02 Mon Sep 17 00:00:00 2001 From: samin-z Date: Tue, 17 Mar 2026 17:03:33 +0100 Subject: [PATCH 5/8] cs and psalm fix Signed-off-by: samin-z --- lib/AppInfo/Application.php | 2 +- lib/Service/BoardService.php | 5 ++-- lib/Service/CommentService.php | 7 ++++- lib/Service/FilesAppService.php | 3 +- lib/UserMigration/DeckMigrator.php | 46 +++++++++++++++--------------- tests/unit/DeckMigratorTest.php | 1 - 6 files changed, 34 insertions(+), 30 deletions(-) diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 9f59f32550..42c0fcae79 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -51,8 +51,8 @@ use OCA\Deck\Sharing\DeckShareProvider; use OCA\Deck\Sharing\Listener; use OCA\Deck\Teams\DeckTeamResourceProvider; -use OCA\Text\Event\LoadEditor; use OCA\Deck\UserMigration\DeckMigrator; +use OCA\Text\Event\LoadEditor; use OCP\AppFramework\App; use OCP\AppFramework\Bootstrap\IBootContext; use OCP\AppFramework\Bootstrap\IBootstrap; diff --git a/lib/Service/BoardService.php b/lib/Service/BoardService.php index 8d30ac743d..c04afad3b5 100644 --- a/lib/Service/BoardService.php +++ b/lib/Service/BoardService.php @@ -54,7 +54,6 @@ use Psr\Container\ContainerExceptionInterface; use Psr\Container\NotFoundExceptionInterface; use Psr\Log\LoggerInterface; -use Symfony\Component\CssSelector\Exception\InternalErrorException; class BoardService { private ?array $boardsCacheFull = null; @@ -859,7 +858,7 @@ private function enrichWithCards(Board $board): void { * * @return Board * - * @throws InternalErrorException + * @throws InternalError */ public function importBoard(array $board, string $userId): Board { $item = new Board(); @@ -873,7 +872,7 @@ public function importBoard(array $board, string $userId): Board { $newBoard = $this->boardMapper->insert($item); } catch (\Exception $e) { $this->logger->error('importBoard insert error: ' . $e->getMessage()); - throw new InternalErrorException('importBoard insert error: ' . $e->getMessage()); + throw new InternalError('importBoard insert error: ' . $e->getMessage()); } return $newBoard; } diff --git a/lib/Service/CommentService.php b/lib/Service/CommentService.php index f58ade4ac1..9c3adec575 100644 --- a/lib/Service/CommentService.php +++ b/lib/Service/CommentService.php @@ -221,7 +221,12 @@ public function exportAllForCard(int $cardId, int $limit = 1000, int $offset = 0 */ public function importComment(int $cardId, array $comment, string $parentId = '0'): int { try { - $newComment = new Comment(); + $newComment = $this->commentsManager->create( + $comment['actorType'], + $comment['actorId'], + Application::COMMENT_ENTITY_TYPE, + (string)$cardId + ); $newComment->setMessage($comment['message']); $newComment->setObject(Application::COMMENT_ENTITY_TYPE, (string)$cardId); $newComment->setVerb('comment'); diff --git a/lib/Service/FilesAppService.php b/lib/Service/FilesAppService.php index 0efe2b23b4..0909d6723d 100644 --- a/lib/Service/FilesAppService.php +++ b/lib/Service/FilesAppService.php @@ -352,6 +352,7 @@ public function getAllDeckSharesForCards(array $cardIds): array { ->from('share') ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(12))) ->andWhere($qb->expr()->in('share_with', $qb->createParameter('cardIds'))); + /** @psalm-suppress UndefinedClass */ $qb->setParameter('cardIds', $cardIds, Connection::PARAM_STR_ARRAY); $sql = $qb->getSQL(); @@ -365,7 +366,7 @@ public function getAllDeckSharesForCards(array $cardIds): array { * @param array $shareData * @param string $userId * - * @return bool + * @return void * * @throws InternalError */ diff --git a/lib/UserMigration/DeckMigrator.php b/lib/UserMigration/DeckMigrator.php index a3e98529eb..e2e0642f79 100644 --- a/lib/UserMigration/DeckMigrator.php +++ b/lib/UserMigration/DeckMigrator.php @@ -25,9 +25,10 @@ use OCA\Deck\Service\LabelService; use OCA\Deck\Service\StackService; use OCP\Files\Folder; +use OCP\Files\IRootFolder; use OCP\Files\NotFoundException; +use OCP\IConfig; use OCP\IL10N; -use OCP\Files\IRootFolder; use OCP\IUser; use OCP\UserMigration\IExportDestination; use OCP\UserMigration\IImportSource; @@ -35,9 +36,8 @@ use OCP\UserMigration\ISizeEstimationMigrator; use OCP\UserMigration\TMigratorBasicVersionHandling; use Psr\Log\LoggerInterface; -use Symfony\Component\Console\Output\OutputInterface; -use OCP\IConfig; +use Symfony\Component\Console\Output\OutputInterface; class DeckMigrator implements IMigrator, ISizeEstimationMigrator { @@ -112,7 +112,7 @@ public function export( $labels = $this->labelMapper->findAll($board->getId()); $boardLabels = array_merge($boardLabels, $labels); - list($newStacks, $newCards, $newComments) = $this->exportStacksCardsCommentsSimple($board->getId()); + [$newStacks, $newCards, $newComments] = $this->exportStacksCardsCommentsSimple($board->getId()); $boardStacks = array_merge($boardStacks, $newStacks); $stackCards = array_merge($stackCards, $newCards); $cardComments = array_merge($cardComments, $newComments); @@ -122,9 +122,9 @@ public function export( $exportDestination->addFileContents(self::BOARD_LABELS, json_encode($boardLabels)); $exportDestination->addFileContents(self::BOARD_STACKS, json_encode($boardStacks)); $exportDestination->addFileContents(self::STACK_CARDS, json_encode($stackCards)); - usort($cardComments, function ($firstComment, $secondComment) { - return ($firstComment['id'] ?? 0) <=> ($secondComment['id'] ?? 0); - }); + usort($cardComments, function ($firstComment, $secondComment) { + return ($firstComment['id'] ?? 0) <=> ($secondComment['id'] ?? 0); + }); $exportDestination->addFileContents(self::CARD_COMMENTS, json_encode($cardComments)); $cardIds = array_map(fn ($c) => $c->getId(), $stackCards); @@ -179,20 +179,20 @@ private function exportCardAttachmentsFiles(array $cardAttachments, string $user * @return array[] [$stacks, $cards, $comments] */ private function exportStacksCardsCommentsSimple(int $boardId): array { - $stacks = $this->stackMapper->findAll($boardId); - $allBoardCards = []; - $allComments = []; - foreach ($stacks as $stack) { - $stackUnarchivedCards = $this->cardMapper->findAll($stack->getId()); - $stackArchivedCards = $this->cardMapper->findAllArchived($stack->getId()); - $allBoardCards = array_merge($allBoardCards, $stackUnarchivedCards, $stackArchivedCards); - $stackAllCards = array_merge($stackUnarchivedCards, $stackArchivedCards); - foreach ($stackAllCards as $card) { - $comments = $this->commentService->exportAllForCard($card->getId()); - $allComments = array_merge($allComments, $comments); - } - } - return [$stacks, $allBoardCards, $allComments]; + $stacks = $this->stackMapper->findAll($boardId); + $allBoardCards = []; + $allComments = []; + foreach ($stacks as $stack) { + $stackUnarchivedCards = $this->cardMapper->findAll($stack->getId()); + $stackArchivedCards = $this->cardMapper->findAllArchived($stack->getId()); + $allBoardCards = array_merge($allBoardCards, $stackUnarchivedCards, $stackArchivedCards); + $stackAllCards = array_merge($stackUnarchivedCards, $stackArchivedCards); + foreach ($stackAllCards as $card) { + $comments = $this->commentService->exportAllForCard($card->getId()); + $allComments = array_merge($allComments, $comments); + } + } + return [$stacks, $allBoardCards, $allComments]; } /** @@ -251,7 +251,7 @@ public function import( * * @return void */ - private function importCardAttachment(IImportSource $importSource, string $userId, array $cardIdMap ): void { + private function importCardAttachment(IImportSource $importSource, string $userId, array $cardIdMap): void { $cardAttachments = json_decode($importSource->getFileContents(self::CARD_ATTACHMENTS), true); $userFolder = $this->rootFolder->getUserFolder($userId); try { @@ -277,7 +277,7 @@ private function importDeckAttachment( Folder $deckFolder, IImportSource $importSource, array $cardIdMap, - string $userId + string $userId, ): void { $fileTarget = $share['file_target']; $fileTargetClean = str_replace('{DECK_PLACEHOLDER}/', '', ltrim($fileTarget, '/')); diff --git a/tests/unit/DeckMigratorTest.php b/tests/unit/DeckMigratorTest.php index 25598e90f1..31d44e1413 100644 --- a/tests/unit/DeckMigratorTest.php +++ b/tests/unit/DeckMigratorTest.php @@ -32,7 +32,6 @@ use OCP\UserMigration\IImportSource; use Psr\Log\LoggerInterface; use Symfony\Component\Console\Output\OutputInterface; -use PHPUnit\Framework\MockObject\MockObject; use Test\TestCase; class DeckMigratorTest extends TestCase { From ace4fd68e17c0b36b84008eceb2befe2ef614539 Mon Sep 17 00:00:00 2001 From: samin-z Date: Tue, 17 Mar 2026 17:17:57 +0100 Subject: [PATCH 6/8] fixes Signed-off-by: samin-z --- lib/Service/FilesAppService.php | 5 +---- lib/UserMigration/DeckMigrator.php | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/lib/Service/FilesAppService.php b/lib/Service/FilesAppService.php index 0909d6723d..349e08a82f 100644 --- a/lib/Service/FilesAppService.php +++ b/lib/Service/FilesAppService.php @@ -355,10 +355,7 @@ public function getAllDeckSharesForCards(array $cardIds): array { /** @psalm-suppress UndefinedClass */ $qb->setParameter('cardIds', $cardIds, Connection::PARAM_STR_ARRAY); - $sql = $qb->getSQL(); - $params = $qb->getParameters(); - $shares = $qb->executeQuery()->fetchAllAssociative(); - return $shares; + return $qb->executeQuery()->fetchAllAssociative(); } /** diff --git a/lib/UserMigration/DeckMigrator.php b/lib/UserMigration/DeckMigrator.php index e2e0642f79..abc56f1620 100644 --- a/lib/UserMigration/DeckMigrator.php +++ b/lib/UserMigration/DeckMigrator.php @@ -112,7 +112,7 @@ public function export( $labels = $this->labelMapper->findAll($board->getId()); $boardLabels = array_merge($boardLabels, $labels); - [$newStacks, $newCards, $newComments] = $this->exportStacksCardsCommentsSimple($board->getId()); + [$newStacks, $newCards, $newComments] = $this->exportStacksCardsCommentsSimple($board->getId()); $boardStacks = array_merge($boardStacks, $newStacks); $stackCards = array_merge($stackCards, $newCards); $cardComments = array_merge($cardComments, $newComments); From 26ca96966546c84c0352db17d029936781a9572d Mon Sep 17 00:00:00 2001 From: samin-z Date: Thu, 19 Mar 2026 15:58:31 +0100 Subject: [PATCH 7/8] pipeline fixes Signed-off-by: samin-z --- .php-cs-fixer.cache | 1 + lib/UserMigration/DeckMigrator.php | 28 ++++++++++---------- tests/unit/Service/AssignmentServiceTest.php | 9 ++++++- tests/unit/Service/BoardServiceTest.php | 8 +++++- tests/unit/Service/LabelServiceTest.php | 5 ++++ 5 files changed, 35 insertions(+), 16 deletions(-) create mode 100644 .php-cs-fixer.cache diff --git a/.php-cs-fixer.cache b/.php-cs-fixer.cache new file mode 100644 index 0000000000..49002b98a6 --- /dev/null +++ b/.php-cs-fixer.cache @@ -0,0 +1 @@ +{"php":"8.4.16","version":"3.93.0","indent":"\t","lineEnding":"\n","rules":{"encoding":true,"full_opening_tag":true,"blank_line_after_namespace":true,"braces_position":{"allow_single_line_anonymous_functions":false},"class_definition":true,"constant_case":true,"control_structure_braces":true,"control_structure_continuation_position":true,"elseif":true,"function_declaration":{"closure_function_spacing":"one"},"indentation_type":true,"line_ending":true,"lowercase_keywords":true,"method_argument_space":{"on_multiline":"ignore"},"modifier_keywords":{"elements":["method","property"]},"no_break_comment":true,"no_closing_tag":true,"no_multiple_statements_per_line":true,"no_space_around_double_colon":true,"no_spaces_after_function_name":true,"no_trailing_whitespace":true,"no_trailing_whitespace_in_comment":true,"single_blank_line_at_eof":true,"single_class_element_per_statement":true,"single_import_per_statement":true,"single_line_after_imports":true,"single_space_around_construct":{"constructs_followed_by_a_single_space":["abstract","as","case","catch","class","do","else","elseif","final","for","foreach","function","if","interface","namespace","private","protected","public","static","switch","trait","try","use_lambda","while"],"constructs_preceded_by_a_single_space":["as","else","elseif","use_lambda"]},"spaces_inside_parentheses":true,"statement_indentation":true,"switch_case_semicolon_to_colon":true,"switch_case_space":true,"align_multiline_comment":true,"array_indentation":true,"array_syntax":true,"binary_operator_spaces":{"default":"single_space"},"blank_line_after_opening_tag":true,"cast_spaces":{"space":"none"},"concat_space":{"spacing":"one"},"curly_braces_position":{"classes_opening_brace":"same_line","functions_opening_brace":"same_line"},"list_syntax":true,"lowercase_cast":true,"method_chaining_indentation":true,"no_leading_import_slash":true,"no_short_bool_cast":true,"no_spaces_inside_parenthesis":true,"no_unused_imports":true,"no_whitespace_in_blank_line":true,"nullable_type_declaration_for_default_null_value":true,"nullable_type_declaration":{"syntax":"question_mark"},"operator_linebreak":{"position":"beginning"},"ordered_imports":{"imports_order":["class","function","const"],"sort_algorithm":"alpha"},"phpdoc_align":{"align":"left"},"phpdoc_single_line_var_spacing":true,"phpdoc_var_annotation_correct_order":true,"short_scalar_cast":true,"single_quote":{"strings_containing_single_quote_chars":false},"trailing_comma_in_multiline":{"elements":["parameters"]},"types_spaces":{"space":"none","space_multiple_catch":"none"},"type_declaration_spaces":{"elements":["function","property"]},"visibility_required":{"elements":["property","method","const"]},"yoda_style":{"equal":false,"identical":false,"less_and_greater":false},"PhpCsFixerCustomFixers\/multiline_promoted_properties":true},"ruleCustomisationPolicyVersion":"null-policy","hashes":{"tests\/unit\/Middleware\/ExceptionMiddlewareTest.php":"354dd9ccf0fd3b179e5205be69e3ccc9","tests\/unit\/Notification\/NotificationHelperTest.php":"c5a2a3035d92eb2ee1b2b152f6aff430","tests\/unit\/Notification\/NotifierTest.php":"479d1d3140c88ea002a767d6f63f255f","tests\/unit\/Activity\/FilterTest.php":"d632c4d32c6ada1e54f45adb31baadbd","tests\/unit\/Activity\/ActivityManagerTest.php":"c1475547bd9681b1efa0da0e0d52ac4d","tests\/unit\/Activity\/DeckProviderTest.php":"c7e24b1521bef1c989a65866b66500a6","tests\/unit\/Activity\/SettingTest.php":"3dd384223e6c8be763c0674427585bef","tests\/unit\/Activity\/ChangeSetTest.php":"b02e6b2b88bedd339a7e1297b855c8b9","tests\/unit\/DeckMigratorTest.php":"1cba65e4d1b070943f55fa74dfabd0ce","tests\/unit\/controller\/CardControllerTest.php":"59fc813922f96ec9680c475d0953d99e","tests\/unit\/controller\/CardApiControllerTest.php":"5b05f695a22966512a90a2862b4a9fd3","tests\/unit\/controller\/BoardApiControllerTest.php":"27030d83f04b851f53eec941847fde8a","tests\/unit\/controller\/BoardImportApiControllerTest.php":"303827af15944458dfa954fdaf3a4014","tests\/unit\/controller\/StackControllerTest.php":"124d661707a0de9148fbb874303c5580","tests\/unit\/controller\/LabelControllerTest.php":"cd96a6556793611474c9ce745ca9bf3f","tests\/unit\/controller\/PageControllerTest.php":"aa6894c8bef03d412460ba42a2a3f905","tests\/unit\/controller\/BoardControllerTest.php":"1c96603c46c3a2b792fccd2bcb0fab60","tests\/unit\/controller\/StackApiControllerTest.php":"483459f6905488b4719aaf286e256a59","tests\/unit\/controller\/LabelApiControllerTest.php":"0b6a521a7d11e5aebbc7bd2c1a6eb910","tests\/unit\/Search\/FilterStringParserTest.php":"abcc13a720a3452eebabf64764b161fa","tests\/unit\/Search\/Query\/AQueryParameterTest.php":"9f331bc9ba60708d87897a990abf042b","tests\/unit\/Db\/BoardTest.php":"2e411f91007a4979ef5c53c647df6396","tests\/unit\/Db\/UserTest.php":"e1a5994ee6429355029b64ab075c98f2","tests\/unit\/Db\/RelationalEntityTest.php":"1b30a6017ef09252946d08b53e40b16f","tests\/unit\/Db\/AclMapperTest.php":"8b3eaa3e304832cd646784769d2b96e4","tests\/unit\/Db\/BoardMapperTest.php":"4d2c20e6111c3b91e3793d6b0276ef00","tests\/unit\/Db\/GroupTest.php":"b0de093875faefd9b030dbdec0fb113d","tests\/unit\/Db\/LabelTest.php":"362996963d8f7b01f9ec0392848a0307","tests\/unit\/Db\/AclTest.php":"59522cd80027451df59f63c47af0d2f4","tests\/unit\/Db\/AttachmentTest.php":"d4f94a49b089b4725a352c38918acff2","tests\/unit\/Db\/CardTest.php":"c3858c4fc36fb89471d56daf0e9d0d77","tests\/unit\/Db\/StackTest.php":"5e1d85db6d6af930a2e8c4fbf6a31549","tests\/unit\/Db\/AttachmentMapperTest.php":"1ac2b9bad049a517268ba3554b14b47f","tests\/unit\/Validators\/ValidatorTestBase.php":"489d73d6012fc936074a9bbca43bbefa","tests\/unit\/Validators\/StackServiceValidatorTest.php":"58262b987f2d9072ff88b0bdb4650d18","tests\/unit\/Validators\/BoardServiceValidatorTest.php":"9cc94aba92dd1379f71f24dc19abbb73","tests\/unit\/Command\/UserExportTest.php":"2a4b48e35e61dbb2c152fcf748e79fe1","tests\/unit\/Command\/BoardImportTest.php":"891acbba8561b00152427521fe84f2fb","tests\/unit\/Service\/LabelServiceTest.php":"9916eb1559a7f078bdc34c585fb50dc5","tests\/unit\/Service\/PermissionServiceTest.php":"c2a1288ce1160256dfbe32aa6ec7f6c7","tests\/unit\/Service\/Importer\/BoardImportServiceTest.php":"0a908f2f4ecf67838d0979da3205e724","tests\/unit\/Service\/Importer\/Systems\/DeckJsonServiceTest.php":"1936b6ac7c9350e67683f118ff10ca62","tests\/unit\/Service\/Importer\/Systems\/TrelloJsonServiceTest.php":"47f6d071a462c2f28d4f89b569f47753","tests\/unit\/Service\/CardServiceTest.php":"4e5ff1d24f51ea5d6c7bf7fb046aef0e","tests\/unit\/Service\/FilesAppServiceTest.php":"47907402ea861974fac7a76deb069808","tests\/unit\/Service\/FileServiceTest.php":"3ec1d17487b077d3a5cb259141a2eaf4","tests\/unit\/Service\/StackServiceTest.php":"8c923675c3e5d0b8d8a058ad8b5fb985","tests\/unit\/Service\/BoardServiceTest.php":"c2e532845dc62f7b208a2668bd545f69","tests\/unit\/Service\/AttachmentServiceTest.php":"a9aa99e65135fb892d4dcea8c4e99eb9","tests\/unit\/Service\/AssignmentServiceTest.php":"ff434c03bb4c5277382ed29d8d5b5d5d","tests\/unit\/Service\/DefaultBoardServiceTest.php":"c6ae6cebde1b769a22c623301f2fca93","tests\/unit\/Listeners\/CommentEventListenerTest.php":"f25c456e4dce4236412c88df7f2bec7e","tests\/unit\/Reference\/CardReferenceProviderTest.php":"0ad94faba4d90100e1012071cd7c39bd","tests\/unit\/ExceptionsTest.php":"5af6330b5725899c3e8860bf295ea450","tests\/unit\/Cron\/DeleteCronTest.php":"0690c8fcbadce3cfbc81a0aa814618cb","tests\/unit\/Cron\/ScheduledNoificationsTest.php":"379e557e4c15ebd1afbcb9e88c0be441","tests\/integration\/database\/BoardDatabaseTest.php":"a60798521ce8cc904fadad4b8e23ae4d","tests\/integration\/database\/TransferOwnershipTest.php":"83376bf7ebf7ec52073e2e33c22373f2","tests\/integration\/database\/AssignmentMapperTest.php":"12d612fa27b750928bcda17b2ebfe594","tests\/integration\/app\/AppTest.php":"d9e45b231b5127720114dc85539c5c68","tests\/integration\/features\/bootstrap\/SessionContext.php":"4cbcf446b2e39cb76b77fb767de97dce","tests\/integration\/features\/bootstrap\/RequestTrait.php":"020fa9411580d6c29099af41af6b3757","tests\/integration\/features\/bootstrap\/SearchContext.php":"5266ce5afa59262754b01f573f2c4b32","tests\/integration\/features\/bootstrap\/FederationContext.php":"774bdbf59228bc18788bde98ea940102","tests\/integration\/features\/bootstrap\/RequestContext.php":"6a7e73090bee3e0503f286b34711d40e","tests\/integration\/features\/bootstrap\/BoardContext.php":"3e354f8433d2cc64241708480535dc4f","tests\/integration\/features\/bootstrap\/CommentContext.php":"47b9ee5b1438d4f0506bfed344e5314c","tests\/integration\/features\/bootstrap\/ServerContext.php":"e1d7108f84442041e5e2c05e1ef7d6db","tests\/integration\/features\/bootstrap\/AttachmentContext.php":"074e470412e9a5f2aa928e46ac44b05e","tests\/integration\/import\/ImportExportTest.php":"97011893845e204d4450a74da7bb7523","tests\/bootstrap.php":"53bee9383167d59347d71fd57ee57c1f","lib\/Middleware\/FederationMiddleware.php":"4c9489ce3ee4ad77a98c4f8beb79a56d","lib\/Middleware\/DefaultBoardMiddleware.php":"ff162aa6de08c12223be88d914a0bac3","lib\/Middleware\/ExceptionMiddleware.php":"03c6190c926896c23c17f0daaeaac778","lib\/Collaboration\/Resources\/ResourceProvider.php":"76760e0096dfc6b8df8a8d3372654da8","lib\/Collaboration\/Resources\/ResourceProviderCard.php":"4a7fda5e0cc9c0a4273df9ed9bb45dde","lib\/Sharing\/ShareAPIHelper.php":"a7734c7bcf4bd3040679b86fe6474488","lib\/Sharing\/Listener.php":"2c8febc03a61860720e51bc71b0142db","lib\/Sharing\/DeckShareProvider.php":"a7570aea76c69288e4eb641dcc5abf42","lib\/Cache\/AttachmentCacheHelper.php":"2ef9d1b9cdf7ff6096a08c6b18e12aca","lib\/UserMigration\/DeckMigrator.php":"767f29510d9884098142b3df67f77120","lib\/NotFoundException.php":"cc22471994a7acd51b6125265aaf3525","lib\/Notification\/NotificationHelper.php":"48ae361fbc0c9fe434d479742c17faef","lib\/Notification\/Notifier.php":"52999c98bcc8438abf0ccedd6f7757c4","lib\/Activity\/SettingComment.php":"ac157bc7ca99333bbe635d9d241714a2","lib\/Activity\/SettingDescription.php":"ab9a2dbb19d2efc490fd5a66ee789a88","lib\/Activity\/ActivityManager.php":"b657b89c977201978b8aba1035e88a49","lib\/Activity\/SettingChanges.php":"faad9a6994b2a9f84ccf9f4660cddfad","lib\/Activity\/SettingBase.php":"c2d2f5d8e5e27228972cd92f2f75ac7e","lib\/Activity\/DeckProvider.php":"6ffc79f9318c4b179406ed625104553f","lib\/Activity\/Filter.php":"ed0eeef85d2bf56ea9acea3ea036659a","lib\/Activity\/ChangeSet.php":"0449998876a513c237d7d2bcddfb9806","lib\/NotifyPushEvents.php":"b00ce82f3eb95766049605ef5b29965e","lib\/Provider\/DeckProvider.php":"c9233171f9a532634535499d1b56a142","lib\/InvalidAttachmentType.php":"5964ebe6bc8ec08dc523409c4c7f59fc","lib\/Exceptions\/ConflictException.php":"554af323e3eeed26ae94ec9522ab555e","lib\/Exceptions\/FederationDisabledException.php":"e75488f00fa500628850a4e0455224d2","lib\/ArchivedItemException.php":"489157f79533a404643034df63074b67","lib\/BadRequestException.php":"8c505f975cafb9ed9cf3c99f22593c33","lib\/Capabilities.php":"1aeb16d382faf4ce8e82a42eeeb7266e","lib\/Controller\/BoardImportApiController.php":"375fd366478cb49037525daddefd27e0","lib\/Controller\/LabelController.php":"08dd8f96f433b060d8a3b5414a42f359","lib\/Controller\/CardController.php":"5a44d774cd65e8608d4118b19315f39b","lib\/Controller\/CommentsApiController.php":"13e4305002931c1cfa824b9ccc869c04","lib\/Controller\/SearchController.php":"50de19c4ad2f4174299707d743b9424e","lib\/Controller\/StackApiController.php":"a993aae2e4539564bf188c639c0c31fa","lib\/Controller\/StackOcsController.php":"2ef5dc5a790401fa34f14db6baf18f08","lib\/Controller\/CardOcsController.php":"0c0b31d468fe671e5188a630eb730771","lib\/Controller\/BoardController.php":"578b45c69568fd5fd22ce7e226c15b5d","lib\/Controller\/CardApiController.php":"36b99ae92d448112a7dcb2f7a19110ef","lib\/Controller\/ConfigController.php":"38e9e3b3131e3660aa810cd7f8e76a96","lib\/Controller\/AttachmentApiController.php":"ea82a8566eaba6beecb60cdaad937ff8","lib\/Controller\/AttachmentApiV11Controller.php":"bae1746ee4440ae5ca978d6febc7d535","lib\/Controller\/SessionController.php":"0b12c7648cd7067911bfa6ec0c4083b8","lib\/Controller\/AttachmentController.php":"b9f3b343fac1955f40f0204517e2cd55","lib\/Controller\/OverviewApiController.php":"d84e404678551275579ee74d5bd438e9","lib\/Controller\/LabelApiController.php":"f6347352e4dc9c3cb24c18f1236d1643","lib\/Controller\/BoardApiController.php":"3b3d0237e88ade2891628880ed11f36d","lib\/Controller\/PageController.php":"326118672c68617f201f119e68096293","lib\/Controller\/BoardOcsController.php":"111135b3a6a3939aad603076e7a7aa20","lib\/Controller\/StackController.php":"a81231f4ff0155be214c1b82baa6c13b","lib\/Search\/CardCommentProvider.php":"fcc3ae2d34ae1e706d65554c50602822","lib\/Search\/CardSearchResultEntry.php":"6780b6189616782626a982fa44f0a4ff","lib\/Search\/CommentSearchResultEntry.php":"681e8bd83005b86daa266ccb0e9f46f8","lib\/Search\/BoardSearchResultEntry.php":"9605659947b7bfecff4480a04653fb10","lib\/Search\/FilterStringParser.php":"3a49ee9b681903f3c913a362503767f7","lib\/Search\/DeckProvider.php":"f46d93de0976defca1eb0ab6cdda3603","lib\/Search\/Query\/AQueryParameter.php":"323af9216886dc0c19942afd6614ce87","lib\/Search\/Query\/DateQueryParameter.php":"f938dfb093010a03301633341378034d","lib\/Search\/Query\/SearchQuery.php":"e54bd541ba56bc6759b6b5d3edd91478","lib\/Search\/Query\/StringQueryParameter.php":"3f9c93fe3b110a732ee8bb715f2c7642","lib\/Dashboard\/DeckWidgetTomorrow.php":"0b84fbcdd987348e055ec89d57fc22f1","lib\/Dashboard\/DeckWidgetToday.php":"0815fe874acb138b3b15b68974adc790","lib\/Dashboard\/DeckWidgetUpcoming.php":"0e2a7c7551ea165c0b7b701fb49c3a11","lib\/NoPermissionException.php":"3812d8f1cfcf46e1c6cf3b8ef815a8bf","lib\/StatusException.php":"1d22687a09c47bbd1cf2fddb123193fb","lib\/Federation\/DeckFederationProxy.php":"4a54baf03502ab311f8b422f9add8437","lib\/Federation\/DeckFederationProvider.php":"0a8dc26f0d001889732efd594aecf04e","lib\/Model\/BoardSummary.php":"0e1a838ffed8e83322815e5eb5787c20","lib\/Model\/OptionalNullableValue.php":"f036eab84eefd745e82202aab17363f4","lib\/Model\/CardDetails.php":"277e4180484ffbd7b53d7fcf3487fbef","lib\/Teams\/DeckTeamResourceProvider.php":"0f800de43405827fb9cbfbcb95df347c","lib\/Db\/Card.php":"7d8be0f616814240efedd293fb46aedf","lib\/Db\/SessionMapper.php":"090537bd94b18649743bea0dd512d1fd","lib\/Db\/Group.php":"1b90c750ffaed2c053c4b0190fe9734e","lib\/Db\/RelationalObject.php":"dd1a1ae0945e19bd3352197fe6bfb414","lib\/Db\/LabelMapper.php":"4b473ca4c4686e414582f2863879ee32","lib\/Db\/Label.php":"2c786fd375cbe3e0786115d31c0f785d","lib\/Db\/AclMapper.php":"6928a9bd36b60cb8d3c3d35505f6e3e6","lib\/Db\/Session.php":"c0f1c6fbcb83c82983933952b4c4747c","lib\/Db\/RelationalEntity.php":"aee95af46f9527e91dd61f755150cb7b","lib\/Db\/User.php":"298d1ddd733711e1e66a3cf22d180a15","lib\/Db\/FederatedUser.php":"164d211a8ceec9878116fc44325768e9","lib\/Db\/Circle.php":"47226372be7d955bf40c0fbb665e602d","lib\/Db\/AttachmentMapper.php":"14f387fb7524ea7f5b8bef0ac88388f0","lib\/Db\/ChangeHelper.php":"984659676904dcb3fbf05cdf8992e705","lib\/Db\/AssignmentMapper.php":"d54ff3ca8d68ea391d42f95d9faa575d","lib\/Db\/Acl.php":"b6f3e0dcac8a6f3956cf2272b323cbe3","lib\/Db\/Stack.php":"976c1bfa7a6597a55c54ba52a7d28ed0","lib\/Db\/DeckMapper.php":"b944ceb9768bd6ea7a1e3d22c459fa95","lib\/Db\/Board.php":"7a0cf0336cce5f7eceb605aed2b715af","lib\/Db\/Assignment.php":"0625b53e8336dbf962efcac09262d644","lib\/Db\/Attachment.php":"17cd484061b53a1e6dac26ad2c4cee9a","lib\/Db\/IPermissionMapper.php":"eaf7419e8236dbccc823661532bd628d","lib\/Db\/StackMapper.php":"65c8de410e804c588db2dd5fc77c6e3e","lib\/Db\/BoardMapper.php":"5bbd6c702e4a35a9ba096bdaf1f72a8d","lib\/Db\/CardMapper.php":"bbb3286dceb204b6cbe5ed71235aeff5","lib\/Validators\/LabelServiceValidator.php":"d6ac86ca3616e37e76077441885d1bfc","lib\/Validators\/StackServiceValidator.php":"a99a6366c6ede5e5bc76a33b9657f913","lib\/Validators\/CardServiceValidator.php":"198c8b617e8acc0c5c9865ce348b361a","lib\/Validators\/AttachmentServiceValidator.php":"82e51705cadf84aa2ef29bf019d2fa79","lib\/Validators\/BaseValidator.php":"410c28730156833704bbdb6a8a0cdf44","lib\/Validators\/AssignmentServiceValidator.php":"96a432a0375d521830c8a8841f924d8d","lib\/Validators\/BoardServiceValidator.php":"224bcb672796fc393a18258f36b089cb","lib\/Command\/CalendarToggle.php":"073345ab4f3a8ea6044055dc6e43d2cc","lib\/Command\/BoardImport.php":"9aa00bc87e064636e2706294aa554a34","lib\/Command\/UserExport.php":"8d5b3e3b50cca2b33bc6f11092d75d8b","lib\/Command\/TransferOwnership.php":"0e7fd056889078acea1568914e5c52a2","lib\/DAV\/CalendarObject.php":"8090769df472f84c3bf5b98a2b28d763","lib\/DAV\/DeckCalendarBackend.php":"438208533a4d38943f057302f0adabf6","lib\/DAV\/CalendarPlugin.php":"80a8719407a7be88518ad4674f42d247","lib\/DAV\/Calendar.php":"d5c4c28c133eb2586a88463f071352ce","lib\/Errors\/InternalError.php":"fa1142d277981f6c1b798197a7b00a8f","lib\/Service\/DefaultBoardService.php":"572ffa1af2238f641b3cd88af73a892d","lib\/Service\/OverviewService.php":"406329da0afebf5e3f46fade9e93a3b3","lib\/Service\/PermissionService.php":"b3d647f2aab926d47db621aed4c7d6a7","lib\/Service\/Importer\/BoardImportService.php":"123cd210419fd7d393abeb6769f1daeb","lib\/Service\/Importer\/ABoardImportService.php":"d585d9ae854ef7e2d8f7785da163797f","lib\/Service\/Importer\/Systems\/DeckJsonService.php":"7f963589760b18702198d72e5f394e89","lib\/Service\/Importer\/Systems\/TrelloApiService.php":"685c9fc96ef7dddb4495b545f8b454cf","lib\/Service\/Importer\/Systems\/TrelloJsonService.php":"c6eb3043adcf9c4d083cbbe95433490b","lib\/Service\/Importer\/BoardImportCommandService.php":"1ee4e2ed1728ce6cff2af3fb0ceaea5b","lib\/Service\/AttachmentService.php":"124c8bdcd47cea3900a3723fbdca5ecc","lib\/Service\/CardService.php":"4ad547f512986cccd912f2c23337373d","lib\/Service\/FullTextSearchService.php":"fa0d4be054ef537531c3f273b15205d4","lib\/Service\/FilesAppService.php":"7e884fe79dc5f1cb6a77f630e8ba4512","lib\/Service\/FileService.php":"7245f27c159f584bd3b63469306fe0cd","lib\/Service\/CommentService.php":"a08ddac9d4b83e7c75763114faeb9d60","lib\/Service\/ConfigService.php":"11fe57b7c3668241a4994f4388e37cd8","lib\/Service\/AssignmentService.php":"e5d234bfd269c4966ca9a7129b9eb290","lib\/Service\/IAttachmentService.php":"43e00697aae1b373f8c4743a78dbef76","lib\/Service\/LabelService.php":"ccc83d1f5cb17c891acf7536664c9e17","lib\/Service\/BoardService.php":"ffd893eb940b8d5287f168c3330652fe","lib\/Service\/ICustomAttachmentService.php":"bd73412ad67f16033d87923fbcc8218b","lib\/Service\/SessionService.php":"e71e3cb0653d78719b2026a295dfcc57","lib\/Service\/ExternalBoardService.php":"c47ed5fa34eb24285aa2f6ab2a457a1d","lib\/Service\/StackService.php":"f9b0ecda3ecc3257a31d3cdd1c7d9a8f","lib\/Service\/SearchService.php":"22d5cbd4323c5b06c21cce2666e43670","lib\/Service\/CirclesService.php":"eb642cfdc4ce03580bfe4ce554e0c8a6","lib\/Migration\/Version10800Date20220422061816.php":"e8ba6f14ef20588edf01b7a07f5aefdf","lib\/Migration\/Version1000Date20200306161713.php":"82562a9b61c5a31613f59aa208534d12","lib\/Migration\/Version11001Date20251020122010.php":"72cc7254bbcfa17c2fd1db53f9a59b67","lib\/Migration\/Version10200Date20201111150114.php":"376a20164d1e9d50741c4e3c7bb4a89e","lib\/Migration\/Version1011Date20230901010840.php":"c0caea1dc1dbc9352c1f76e11b8ce004","lib\/Migration\/Version10900Date202206151724222.php":"86343d019bd5a172e4429369d8f4a2e3","lib\/Migration\/DeletedCircleCleanup.php":"17532a9418c1628c624df5cbda1e2856","lib\/Migration\/Version1000Date20200308073933.php":"00bbd47ef753630b72c122ad05e1babc","lib\/Migration\/Version11000Date20240222115515.php":"41fad9525613b229dab223fc39c1c219","lib\/Migration\/Version11001Date20251009165313.php":"df683d835cc1b633a48b6943d31c8ab9","lib\/Migration\/Version1011Date20231106160059.php":"fc35eb1e761a591390e004fb55b2cb22","lib\/Migration\/LabelMismatchCleanup.php":"ce4ae70d420fa9c0723718f1ba8baa25","lib\/Event\/AclUpdatedEvent.php":"1cc52e39754bcb8190ca6ada6b0f8174","lib\/Event\/SessionClosedEvent.php":"6405cae8b34bed4bbd667f5fa7078cd1","lib\/Event\/SessionCreatedEvent.php":"e13f0d2234a37ea4d3fb411f3536bc3c","lib\/Event\/CardDeletedEvent.php":"978a67335acc5c25a5e500c63498a7bb","lib\/Event\/AclCreatedEvent.php":"80c8dec71734902af22ba3e1081a8a08","lib\/Event\/ACardEvent.php":"0492ee448c3e9b167b806109b5475986","lib\/Event\/AclDeletedEvent.php":"60f760f0596a646771ed8dc513f4ffca","lib\/Event\/CardCreatedEvent.php":"411acb38a86528c87302ce49541c8b04","lib\/Event\/ABoardImportGetAllowedEvent.php":"9764edc27ee52eac04886852cc36c847","lib\/Event\/BoardImportGetAllowedEvent.php":"ef470b14f40108c09151cd129bec63ed","lib\/Event\/AAclEvent.php":"4ee2811c708009e20532e1183c4dccf7","lib\/Event\/BoardUpdatedEvent.php":"55c8911833ceeed09d33e74696a37d31","lib\/Event\/CardUpdatedEvent.php":"0a3ff12304b822494f69bb953d38b801","lib\/Listeners\/CommentEventListener.php":"452b0557762d19c881875a1b7c11ee34","lib\/Listeners\/FullTextSearchEventListener.php":"f01ba7c49df2072e6c8aa6984e3d84a3","lib\/Listeners\/BeforeTemplateRenderedListener.php":"3fb2d67b4a095e8aa34fff6f4d54acc3","lib\/Listeners\/AclCreatedRemovedListener.php":"1ffdeafea807e7a7006f5448c59dc040","lib\/Listeners\/ParticipantCleanupListener.php":"a1f28800657269d3049667369e508ac0","lib\/Listeners\/ResourceTypeRegisterListener.php":"7aae7055704560632b18bf6f3466cac4","lib\/Listeners\/ResourceAdditionalScriptsListener.php":"75f2c119b90801ade237594d04e8c88b","lib\/Listeners\/LiveUpdateListener.php":"8bd7c93d9a27a93de05e4732189e9d67","lib\/Listeners\/ResourceListener.php":"a11490b2d551b06c7fee73697bdd0b73","lib\/Reference\/CardReferenceProvider.php":"7c0daed5705113156d078bd7f2d37300","lib\/Reference\/CommentReferenceProvider.php":"15a93c88f8710758c3ec345141fb0284","lib\/Reference\/CreateCardReferenceProvider.php":"0a49dc73285a760ce575d9c71eb055ce","lib\/Reference\/BoardReferenceProvider.php":"ed5ca614b07b3ac7e107baf1cda88f98","lib\/AppInfo\/Application.php":"fa7133173f1174ea87787e24d037401a","lib\/Cron\/SessionsCleanup.php":"5542e5a486fbb17afb017b7d7fccb8a4","lib\/Cron\/CardDescriptionActivity.php":"d8910db39280acaeb6f64297cc4f6bf3","lib\/Cron\/ScheduledNotifications.php":"0266f829a96a39b9a7b1e0ba0f501070","lib\/Cron\/DeleteCron.php":"a3d3037c79354b3eb9f069c4b2344f23","templates\/main.php":"0ba2f93de5f8c4358fb6ef45f91c3ff9","appinfo\/autoload.php":"c9887cd20064590621418f687e8be54e","appinfo\/routes.php":"5b4628e0883658c32bdc604d5cdb7c7a"}} \ No newline at end of file diff --git a/lib/UserMigration/DeckMigrator.php b/lib/UserMigration/DeckMigrator.php index abc56f1620..7910b91bb0 100644 --- a/lib/UserMigration/DeckMigrator.php +++ b/lib/UserMigration/DeckMigrator.php @@ -112,7 +112,7 @@ public function export( $labels = $this->labelMapper->findAll($board->getId()); $boardLabels = array_merge($boardLabels, $labels); - [$newStacks, $newCards, $newComments] = $this->exportStacksCardsCommentsSimple($board->getId()); + [$newStacks, $newCards, $newComments] = $this->exportStacksCardsCommentsSimple($board->getId()); $boardStacks = array_merge($boardStacks, $newStacks); $stackCards = array_merge($stackCards, $newCards); $cardComments = array_merge($cardComments, $newComments); @@ -179,20 +179,20 @@ private function exportCardAttachmentsFiles(array $cardAttachments, string $user * @return array[] [$stacks, $cards, $comments] */ private function exportStacksCardsCommentsSimple(int $boardId): array { - $stacks = $this->stackMapper->findAll($boardId); - $allBoardCards = []; - $allComments = []; - foreach ($stacks as $stack) { - $stackUnarchivedCards = $this->cardMapper->findAll($stack->getId()); - $stackArchivedCards = $this->cardMapper->findAllArchived($stack->getId()); - $allBoardCards = array_merge($allBoardCards, $stackUnarchivedCards, $stackArchivedCards); - $stackAllCards = array_merge($stackUnarchivedCards, $stackArchivedCards); - foreach ($stackAllCards as $card) { - $comments = $this->commentService->exportAllForCard($card->getId()); - $allComments = array_merge($allComments, $comments); - } + $stacks = $this->stackMapper->findAll($boardId); + $allBoardCards = []; + $allComments = []; + foreach ($stacks as $stack) { + $stackUnarchivedCards = $this->cardMapper->findAll($stack->getId()); + $stackArchivedCards = $this->cardMapper->findAllArchived($stack->getId()); + $allBoardCards = array_merge($allBoardCards, $stackUnarchivedCards, $stackArchivedCards); + $stackAllCards = array_merge($stackUnarchivedCards, $stackArchivedCards); + foreach ($stackAllCards as $card) { + $comments = $this->commentService->exportAllForCard($card->getId()); + $allComments = array_merge($allComments, $comments); } - return [$stacks, $allBoardCards, $allComments]; + } + return [$stacks, $allBoardCards, $allComments]; } /** diff --git a/tests/unit/Service/AssignmentServiceTest.php b/tests/unit/Service/AssignmentServiceTest.php index bef8fa60d8..41f55f7d6f 100644 --- a/tests/unit/Service/AssignmentServiceTest.php +++ b/tests/unit/Service/AssignmentServiceTest.php @@ -37,6 +37,7 @@ use OCP\Activity\IEvent; use OCP\EventDispatcher\IEventDispatcher; use PHPUnit\Framework\MockObject\MockObject; +use Psr\Log\LoggerInterface; use Test\TestCase; class AssignmentServiceTest extends TestCase { @@ -82,6 +83,10 @@ class AssignmentServiceTest extends TestCase { * @var AssignmentServiceValidator */ private $assignmentServiceValidator; + /** + * @var LoggerInterface + */ + private $logger; public function setUp(): void { @@ -95,6 +100,7 @@ public function setUp(): void { $this->eventDispatcher = $this->createMock(IEventDispatcher::class); $this->changeHelper = $this->createMock(ChangeHelper::class); $this->assignmentServiceValidator = $this->createMock(AssignmentServiceValidator::class); + $this->logger = $this->createMock(LoggerInterface::class); $this->assignmentService = new AssignmentService( $this->permissionService, $this->cardMapper, @@ -105,7 +111,8 @@ public function setUp(): void { $this->changeHelper, $this->eventDispatcher, $this->assignmentServiceValidator, - 'admin' + 'admin', + $this->logger, ); } diff --git a/tests/unit/Service/BoardServiceTest.php b/tests/unit/Service/BoardServiceTest.php index 549021bf0c..5e3d514693 100644 --- a/tests/unit/Service/BoardServiceTest.php +++ b/tests/unit/Service/BoardServiceTest.php @@ -57,6 +57,7 @@ use OCP\IUser; use OCP\IUserManager; use PHPUnit\Framework\MockObject\MockObject; +use Psr\Log\LoggerInterface; use Test\TestCase; class BoardServiceTest extends TestCase { @@ -104,6 +105,9 @@ class BoardServiceTest extends TestCase { /** @var IUserManager */ private $userManager; + /** @var LoggerInterface */ + private $logger; + public function setUp(): void { parent::setUp(); $this->l10n = $this->createMock(L10N::class); @@ -125,6 +129,7 @@ public function setUp(): void { $this->boardServiceValidator = $this->createMock(BoardServiceValidator::class); $this->sessionMapper = $this->createMock(SessionMapper::class); $this->userManager = $this->createMock(IUserManager::class); + $this->logger = $this->createMock(LoggerInterface::class); $this->service = new BoardService( $this->boardMapper, @@ -151,7 +156,8 @@ public function setUp(): void { $this->userManager, $this->createMock(SecureRandom::class), $this->createMock(ConfigService::class), - $this->userId + $this->userId, + $this->logger, ); $user = $this->createMock(IUser::class); diff --git a/tests/unit/Service/LabelServiceTest.php b/tests/unit/Service/LabelServiceTest.php index c563bc1369..b6819eb80c 100644 --- a/tests/unit/Service/LabelServiceTest.php +++ b/tests/unit/Service/LabelServiceTest.php @@ -32,6 +32,7 @@ use OCA\Deck\Db\LabelMapper; use OCA\Deck\Validators\LabelServiceValidator; use PHPUnit\Framework\MockObject\MockObject; +use Psr\Log\LoggerInterface; use Test\TestCase; class LabelServiceTest extends TestCase { @@ -47,6 +48,8 @@ class LabelServiceTest extends TestCase { /** @var ChangeHelper|\PHPUnit\Framework\MockObject\MockObject */ private ChangeHelper&MockObject $changeHelper; private LabelServiceValidator&MockObject $labelServiceValidator; + /** @var LoggerInterface */ + private $logger; public function setUp(): void { parent::setUp(); @@ -57,6 +60,7 @@ public function setUp(): void { $this->boardService = $this->createMock(BoardService::class); $this->changeHelper = $this->createMock(ChangeHelper::class); $this->labelServiceValidator = $this->createMock(LabelServiceValidator::class); + $this->logger = $this->createMock(LoggerInterface::class); $this->labelService = new LabelService( $this->labelMapper, @@ -64,6 +68,7 @@ public function setUp(): void { $this->boardService, $this->changeHelper, $this->labelServiceValidator, + $this->logger, ); } From 15f814aa8b8b02b6401233cc3519cb479718d003 Mon Sep 17 00:00:00 2001 From: samin-z Date: Thu, 19 Mar 2026 16:27:06 +0100 Subject: [PATCH 8/8] remove cache file Signed-off-by: samin-z --- .php-cs-fixer.cache | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .php-cs-fixer.cache diff --git a/.php-cs-fixer.cache b/.php-cs-fixer.cache deleted file mode 100644 index 49002b98a6..0000000000 --- a/.php-cs-fixer.cache +++ /dev/null @@ -1 +0,0 @@ -{"php":"8.4.16","version":"3.93.0","indent":"\t","lineEnding":"\n","rules":{"encoding":true,"full_opening_tag":true,"blank_line_after_namespace":true,"braces_position":{"allow_single_line_anonymous_functions":false},"class_definition":true,"constant_case":true,"control_structure_braces":true,"control_structure_continuation_position":true,"elseif":true,"function_declaration":{"closure_function_spacing":"one"},"indentation_type":true,"line_ending":true,"lowercase_keywords":true,"method_argument_space":{"on_multiline":"ignore"},"modifier_keywords":{"elements":["method","property"]},"no_break_comment":true,"no_closing_tag":true,"no_multiple_statements_per_line":true,"no_space_around_double_colon":true,"no_spaces_after_function_name":true,"no_trailing_whitespace":true,"no_trailing_whitespace_in_comment":true,"single_blank_line_at_eof":true,"single_class_element_per_statement":true,"single_import_per_statement":true,"single_line_after_imports":true,"single_space_around_construct":{"constructs_followed_by_a_single_space":["abstract","as","case","catch","class","do","else","elseif","final","for","foreach","function","if","interface","namespace","private","protected","public","static","switch","trait","try","use_lambda","while"],"constructs_preceded_by_a_single_space":["as","else","elseif","use_lambda"]},"spaces_inside_parentheses":true,"statement_indentation":true,"switch_case_semicolon_to_colon":true,"switch_case_space":true,"align_multiline_comment":true,"array_indentation":true,"array_syntax":true,"binary_operator_spaces":{"default":"single_space"},"blank_line_after_opening_tag":true,"cast_spaces":{"space":"none"},"concat_space":{"spacing":"one"},"curly_braces_position":{"classes_opening_brace":"same_line","functions_opening_brace":"same_line"},"list_syntax":true,"lowercase_cast":true,"method_chaining_indentation":true,"no_leading_import_slash":true,"no_short_bool_cast":true,"no_spaces_inside_parenthesis":true,"no_unused_imports":true,"no_whitespace_in_blank_line":true,"nullable_type_declaration_for_default_null_value":true,"nullable_type_declaration":{"syntax":"question_mark"},"operator_linebreak":{"position":"beginning"},"ordered_imports":{"imports_order":["class","function","const"],"sort_algorithm":"alpha"},"phpdoc_align":{"align":"left"},"phpdoc_single_line_var_spacing":true,"phpdoc_var_annotation_correct_order":true,"short_scalar_cast":true,"single_quote":{"strings_containing_single_quote_chars":false},"trailing_comma_in_multiline":{"elements":["parameters"]},"types_spaces":{"space":"none","space_multiple_catch":"none"},"type_declaration_spaces":{"elements":["function","property"]},"visibility_required":{"elements":["property","method","const"]},"yoda_style":{"equal":false,"identical":false,"less_and_greater":false},"PhpCsFixerCustomFixers\/multiline_promoted_properties":true},"ruleCustomisationPolicyVersion":"null-policy","hashes":{"tests\/unit\/Middleware\/ExceptionMiddlewareTest.php":"354dd9ccf0fd3b179e5205be69e3ccc9","tests\/unit\/Notification\/NotificationHelperTest.php":"c5a2a3035d92eb2ee1b2b152f6aff430","tests\/unit\/Notification\/NotifierTest.php":"479d1d3140c88ea002a767d6f63f255f","tests\/unit\/Activity\/FilterTest.php":"d632c4d32c6ada1e54f45adb31baadbd","tests\/unit\/Activity\/ActivityManagerTest.php":"c1475547bd9681b1efa0da0e0d52ac4d","tests\/unit\/Activity\/DeckProviderTest.php":"c7e24b1521bef1c989a65866b66500a6","tests\/unit\/Activity\/SettingTest.php":"3dd384223e6c8be763c0674427585bef","tests\/unit\/Activity\/ChangeSetTest.php":"b02e6b2b88bedd339a7e1297b855c8b9","tests\/unit\/DeckMigratorTest.php":"1cba65e4d1b070943f55fa74dfabd0ce","tests\/unit\/controller\/CardControllerTest.php":"59fc813922f96ec9680c475d0953d99e","tests\/unit\/controller\/CardApiControllerTest.php":"5b05f695a22966512a90a2862b4a9fd3","tests\/unit\/controller\/BoardApiControllerTest.php":"27030d83f04b851f53eec941847fde8a","tests\/unit\/controller\/BoardImportApiControllerTest.php":"303827af15944458dfa954fdaf3a4014","tests\/unit\/controller\/StackControllerTest.php":"124d661707a0de9148fbb874303c5580","tests\/unit\/controller\/LabelControllerTest.php":"cd96a6556793611474c9ce745ca9bf3f","tests\/unit\/controller\/PageControllerTest.php":"aa6894c8bef03d412460ba42a2a3f905","tests\/unit\/controller\/BoardControllerTest.php":"1c96603c46c3a2b792fccd2bcb0fab60","tests\/unit\/controller\/StackApiControllerTest.php":"483459f6905488b4719aaf286e256a59","tests\/unit\/controller\/LabelApiControllerTest.php":"0b6a521a7d11e5aebbc7bd2c1a6eb910","tests\/unit\/Search\/FilterStringParserTest.php":"abcc13a720a3452eebabf64764b161fa","tests\/unit\/Search\/Query\/AQueryParameterTest.php":"9f331bc9ba60708d87897a990abf042b","tests\/unit\/Db\/BoardTest.php":"2e411f91007a4979ef5c53c647df6396","tests\/unit\/Db\/UserTest.php":"e1a5994ee6429355029b64ab075c98f2","tests\/unit\/Db\/RelationalEntityTest.php":"1b30a6017ef09252946d08b53e40b16f","tests\/unit\/Db\/AclMapperTest.php":"8b3eaa3e304832cd646784769d2b96e4","tests\/unit\/Db\/BoardMapperTest.php":"4d2c20e6111c3b91e3793d6b0276ef00","tests\/unit\/Db\/GroupTest.php":"b0de093875faefd9b030dbdec0fb113d","tests\/unit\/Db\/LabelTest.php":"362996963d8f7b01f9ec0392848a0307","tests\/unit\/Db\/AclTest.php":"59522cd80027451df59f63c47af0d2f4","tests\/unit\/Db\/AttachmentTest.php":"d4f94a49b089b4725a352c38918acff2","tests\/unit\/Db\/CardTest.php":"c3858c4fc36fb89471d56daf0e9d0d77","tests\/unit\/Db\/StackTest.php":"5e1d85db6d6af930a2e8c4fbf6a31549","tests\/unit\/Db\/AttachmentMapperTest.php":"1ac2b9bad049a517268ba3554b14b47f","tests\/unit\/Validators\/ValidatorTestBase.php":"489d73d6012fc936074a9bbca43bbefa","tests\/unit\/Validators\/StackServiceValidatorTest.php":"58262b987f2d9072ff88b0bdb4650d18","tests\/unit\/Validators\/BoardServiceValidatorTest.php":"9cc94aba92dd1379f71f24dc19abbb73","tests\/unit\/Command\/UserExportTest.php":"2a4b48e35e61dbb2c152fcf748e79fe1","tests\/unit\/Command\/BoardImportTest.php":"891acbba8561b00152427521fe84f2fb","tests\/unit\/Service\/LabelServiceTest.php":"9916eb1559a7f078bdc34c585fb50dc5","tests\/unit\/Service\/PermissionServiceTest.php":"c2a1288ce1160256dfbe32aa6ec7f6c7","tests\/unit\/Service\/Importer\/BoardImportServiceTest.php":"0a908f2f4ecf67838d0979da3205e724","tests\/unit\/Service\/Importer\/Systems\/DeckJsonServiceTest.php":"1936b6ac7c9350e67683f118ff10ca62","tests\/unit\/Service\/Importer\/Systems\/TrelloJsonServiceTest.php":"47f6d071a462c2f28d4f89b569f47753","tests\/unit\/Service\/CardServiceTest.php":"4e5ff1d24f51ea5d6c7bf7fb046aef0e","tests\/unit\/Service\/FilesAppServiceTest.php":"47907402ea861974fac7a76deb069808","tests\/unit\/Service\/FileServiceTest.php":"3ec1d17487b077d3a5cb259141a2eaf4","tests\/unit\/Service\/StackServiceTest.php":"8c923675c3e5d0b8d8a058ad8b5fb985","tests\/unit\/Service\/BoardServiceTest.php":"c2e532845dc62f7b208a2668bd545f69","tests\/unit\/Service\/AttachmentServiceTest.php":"a9aa99e65135fb892d4dcea8c4e99eb9","tests\/unit\/Service\/AssignmentServiceTest.php":"ff434c03bb4c5277382ed29d8d5b5d5d","tests\/unit\/Service\/DefaultBoardServiceTest.php":"c6ae6cebde1b769a22c623301f2fca93","tests\/unit\/Listeners\/CommentEventListenerTest.php":"f25c456e4dce4236412c88df7f2bec7e","tests\/unit\/Reference\/CardReferenceProviderTest.php":"0ad94faba4d90100e1012071cd7c39bd","tests\/unit\/ExceptionsTest.php":"5af6330b5725899c3e8860bf295ea450","tests\/unit\/Cron\/DeleteCronTest.php":"0690c8fcbadce3cfbc81a0aa814618cb","tests\/unit\/Cron\/ScheduledNoificationsTest.php":"379e557e4c15ebd1afbcb9e88c0be441","tests\/integration\/database\/BoardDatabaseTest.php":"a60798521ce8cc904fadad4b8e23ae4d","tests\/integration\/database\/TransferOwnershipTest.php":"83376bf7ebf7ec52073e2e33c22373f2","tests\/integration\/database\/AssignmentMapperTest.php":"12d612fa27b750928bcda17b2ebfe594","tests\/integration\/app\/AppTest.php":"d9e45b231b5127720114dc85539c5c68","tests\/integration\/features\/bootstrap\/SessionContext.php":"4cbcf446b2e39cb76b77fb767de97dce","tests\/integration\/features\/bootstrap\/RequestTrait.php":"020fa9411580d6c29099af41af6b3757","tests\/integration\/features\/bootstrap\/SearchContext.php":"5266ce5afa59262754b01f573f2c4b32","tests\/integration\/features\/bootstrap\/FederationContext.php":"774bdbf59228bc18788bde98ea940102","tests\/integration\/features\/bootstrap\/RequestContext.php":"6a7e73090bee3e0503f286b34711d40e","tests\/integration\/features\/bootstrap\/BoardContext.php":"3e354f8433d2cc64241708480535dc4f","tests\/integration\/features\/bootstrap\/CommentContext.php":"47b9ee5b1438d4f0506bfed344e5314c","tests\/integration\/features\/bootstrap\/ServerContext.php":"e1d7108f84442041e5e2c05e1ef7d6db","tests\/integration\/features\/bootstrap\/AttachmentContext.php":"074e470412e9a5f2aa928e46ac44b05e","tests\/integration\/import\/ImportExportTest.php":"97011893845e204d4450a74da7bb7523","tests\/bootstrap.php":"53bee9383167d59347d71fd57ee57c1f","lib\/Middleware\/FederationMiddleware.php":"4c9489ce3ee4ad77a98c4f8beb79a56d","lib\/Middleware\/DefaultBoardMiddleware.php":"ff162aa6de08c12223be88d914a0bac3","lib\/Middleware\/ExceptionMiddleware.php":"03c6190c926896c23c17f0daaeaac778","lib\/Collaboration\/Resources\/ResourceProvider.php":"76760e0096dfc6b8df8a8d3372654da8","lib\/Collaboration\/Resources\/ResourceProviderCard.php":"4a7fda5e0cc9c0a4273df9ed9bb45dde","lib\/Sharing\/ShareAPIHelper.php":"a7734c7bcf4bd3040679b86fe6474488","lib\/Sharing\/Listener.php":"2c8febc03a61860720e51bc71b0142db","lib\/Sharing\/DeckShareProvider.php":"a7570aea76c69288e4eb641dcc5abf42","lib\/Cache\/AttachmentCacheHelper.php":"2ef9d1b9cdf7ff6096a08c6b18e12aca","lib\/UserMigration\/DeckMigrator.php":"767f29510d9884098142b3df67f77120","lib\/NotFoundException.php":"cc22471994a7acd51b6125265aaf3525","lib\/Notification\/NotificationHelper.php":"48ae361fbc0c9fe434d479742c17faef","lib\/Notification\/Notifier.php":"52999c98bcc8438abf0ccedd6f7757c4","lib\/Activity\/SettingComment.php":"ac157bc7ca99333bbe635d9d241714a2","lib\/Activity\/SettingDescription.php":"ab9a2dbb19d2efc490fd5a66ee789a88","lib\/Activity\/ActivityManager.php":"b657b89c977201978b8aba1035e88a49","lib\/Activity\/SettingChanges.php":"faad9a6994b2a9f84ccf9f4660cddfad","lib\/Activity\/SettingBase.php":"c2d2f5d8e5e27228972cd92f2f75ac7e","lib\/Activity\/DeckProvider.php":"6ffc79f9318c4b179406ed625104553f","lib\/Activity\/Filter.php":"ed0eeef85d2bf56ea9acea3ea036659a","lib\/Activity\/ChangeSet.php":"0449998876a513c237d7d2bcddfb9806","lib\/NotifyPushEvents.php":"b00ce82f3eb95766049605ef5b29965e","lib\/Provider\/DeckProvider.php":"c9233171f9a532634535499d1b56a142","lib\/InvalidAttachmentType.php":"5964ebe6bc8ec08dc523409c4c7f59fc","lib\/Exceptions\/ConflictException.php":"554af323e3eeed26ae94ec9522ab555e","lib\/Exceptions\/FederationDisabledException.php":"e75488f00fa500628850a4e0455224d2","lib\/ArchivedItemException.php":"489157f79533a404643034df63074b67","lib\/BadRequestException.php":"8c505f975cafb9ed9cf3c99f22593c33","lib\/Capabilities.php":"1aeb16d382faf4ce8e82a42eeeb7266e","lib\/Controller\/BoardImportApiController.php":"375fd366478cb49037525daddefd27e0","lib\/Controller\/LabelController.php":"08dd8f96f433b060d8a3b5414a42f359","lib\/Controller\/CardController.php":"5a44d774cd65e8608d4118b19315f39b","lib\/Controller\/CommentsApiController.php":"13e4305002931c1cfa824b9ccc869c04","lib\/Controller\/SearchController.php":"50de19c4ad2f4174299707d743b9424e","lib\/Controller\/StackApiController.php":"a993aae2e4539564bf188c639c0c31fa","lib\/Controller\/StackOcsController.php":"2ef5dc5a790401fa34f14db6baf18f08","lib\/Controller\/CardOcsController.php":"0c0b31d468fe671e5188a630eb730771","lib\/Controller\/BoardController.php":"578b45c69568fd5fd22ce7e226c15b5d","lib\/Controller\/CardApiController.php":"36b99ae92d448112a7dcb2f7a19110ef","lib\/Controller\/ConfigController.php":"38e9e3b3131e3660aa810cd7f8e76a96","lib\/Controller\/AttachmentApiController.php":"ea82a8566eaba6beecb60cdaad937ff8","lib\/Controller\/AttachmentApiV11Controller.php":"bae1746ee4440ae5ca978d6febc7d535","lib\/Controller\/SessionController.php":"0b12c7648cd7067911bfa6ec0c4083b8","lib\/Controller\/AttachmentController.php":"b9f3b343fac1955f40f0204517e2cd55","lib\/Controller\/OverviewApiController.php":"d84e404678551275579ee74d5bd438e9","lib\/Controller\/LabelApiController.php":"f6347352e4dc9c3cb24c18f1236d1643","lib\/Controller\/BoardApiController.php":"3b3d0237e88ade2891628880ed11f36d","lib\/Controller\/PageController.php":"326118672c68617f201f119e68096293","lib\/Controller\/BoardOcsController.php":"111135b3a6a3939aad603076e7a7aa20","lib\/Controller\/StackController.php":"a81231f4ff0155be214c1b82baa6c13b","lib\/Search\/CardCommentProvider.php":"fcc3ae2d34ae1e706d65554c50602822","lib\/Search\/CardSearchResultEntry.php":"6780b6189616782626a982fa44f0a4ff","lib\/Search\/CommentSearchResultEntry.php":"681e8bd83005b86daa266ccb0e9f46f8","lib\/Search\/BoardSearchResultEntry.php":"9605659947b7bfecff4480a04653fb10","lib\/Search\/FilterStringParser.php":"3a49ee9b681903f3c913a362503767f7","lib\/Search\/DeckProvider.php":"f46d93de0976defca1eb0ab6cdda3603","lib\/Search\/Query\/AQueryParameter.php":"323af9216886dc0c19942afd6614ce87","lib\/Search\/Query\/DateQueryParameter.php":"f938dfb093010a03301633341378034d","lib\/Search\/Query\/SearchQuery.php":"e54bd541ba56bc6759b6b5d3edd91478","lib\/Search\/Query\/StringQueryParameter.php":"3f9c93fe3b110a732ee8bb715f2c7642","lib\/Dashboard\/DeckWidgetTomorrow.php":"0b84fbcdd987348e055ec89d57fc22f1","lib\/Dashboard\/DeckWidgetToday.php":"0815fe874acb138b3b15b68974adc790","lib\/Dashboard\/DeckWidgetUpcoming.php":"0e2a7c7551ea165c0b7b701fb49c3a11","lib\/NoPermissionException.php":"3812d8f1cfcf46e1c6cf3b8ef815a8bf","lib\/StatusException.php":"1d22687a09c47bbd1cf2fddb123193fb","lib\/Federation\/DeckFederationProxy.php":"4a54baf03502ab311f8b422f9add8437","lib\/Federation\/DeckFederationProvider.php":"0a8dc26f0d001889732efd594aecf04e","lib\/Model\/BoardSummary.php":"0e1a838ffed8e83322815e5eb5787c20","lib\/Model\/OptionalNullableValue.php":"f036eab84eefd745e82202aab17363f4","lib\/Model\/CardDetails.php":"277e4180484ffbd7b53d7fcf3487fbef","lib\/Teams\/DeckTeamResourceProvider.php":"0f800de43405827fb9cbfbcb95df347c","lib\/Db\/Card.php":"7d8be0f616814240efedd293fb46aedf","lib\/Db\/SessionMapper.php":"090537bd94b18649743bea0dd512d1fd","lib\/Db\/Group.php":"1b90c750ffaed2c053c4b0190fe9734e","lib\/Db\/RelationalObject.php":"dd1a1ae0945e19bd3352197fe6bfb414","lib\/Db\/LabelMapper.php":"4b473ca4c4686e414582f2863879ee32","lib\/Db\/Label.php":"2c786fd375cbe3e0786115d31c0f785d","lib\/Db\/AclMapper.php":"6928a9bd36b60cb8d3c3d35505f6e3e6","lib\/Db\/Session.php":"c0f1c6fbcb83c82983933952b4c4747c","lib\/Db\/RelationalEntity.php":"aee95af46f9527e91dd61f755150cb7b","lib\/Db\/User.php":"298d1ddd733711e1e66a3cf22d180a15","lib\/Db\/FederatedUser.php":"164d211a8ceec9878116fc44325768e9","lib\/Db\/Circle.php":"47226372be7d955bf40c0fbb665e602d","lib\/Db\/AttachmentMapper.php":"14f387fb7524ea7f5b8bef0ac88388f0","lib\/Db\/ChangeHelper.php":"984659676904dcb3fbf05cdf8992e705","lib\/Db\/AssignmentMapper.php":"d54ff3ca8d68ea391d42f95d9faa575d","lib\/Db\/Acl.php":"b6f3e0dcac8a6f3956cf2272b323cbe3","lib\/Db\/Stack.php":"976c1bfa7a6597a55c54ba52a7d28ed0","lib\/Db\/DeckMapper.php":"b944ceb9768bd6ea7a1e3d22c459fa95","lib\/Db\/Board.php":"7a0cf0336cce5f7eceb605aed2b715af","lib\/Db\/Assignment.php":"0625b53e8336dbf962efcac09262d644","lib\/Db\/Attachment.php":"17cd484061b53a1e6dac26ad2c4cee9a","lib\/Db\/IPermissionMapper.php":"eaf7419e8236dbccc823661532bd628d","lib\/Db\/StackMapper.php":"65c8de410e804c588db2dd5fc77c6e3e","lib\/Db\/BoardMapper.php":"5bbd6c702e4a35a9ba096bdaf1f72a8d","lib\/Db\/CardMapper.php":"bbb3286dceb204b6cbe5ed71235aeff5","lib\/Validators\/LabelServiceValidator.php":"d6ac86ca3616e37e76077441885d1bfc","lib\/Validators\/StackServiceValidator.php":"a99a6366c6ede5e5bc76a33b9657f913","lib\/Validators\/CardServiceValidator.php":"198c8b617e8acc0c5c9865ce348b361a","lib\/Validators\/AttachmentServiceValidator.php":"82e51705cadf84aa2ef29bf019d2fa79","lib\/Validators\/BaseValidator.php":"410c28730156833704bbdb6a8a0cdf44","lib\/Validators\/AssignmentServiceValidator.php":"96a432a0375d521830c8a8841f924d8d","lib\/Validators\/BoardServiceValidator.php":"224bcb672796fc393a18258f36b089cb","lib\/Command\/CalendarToggle.php":"073345ab4f3a8ea6044055dc6e43d2cc","lib\/Command\/BoardImport.php":"9aa00bc87e064636e2706294aa554a34","lib\/Command\/UserExport.php":"8d5b3e3b50cca2b33bc6f11092d75d8b","lib\/Command\/TransferOwnership.php":"0e7fd056889078acea1568914e5c52a2","lib\/DAV\/CalendarObject.php":"8090769df472f84c3bf5b98a2b28d763","lib\/DAV\/DeckCalendarBackend.php":"438208533a4d38943f057302f0adabf6","lib\/DAV\/CalendarPlugin.php":"80a8719407a7be88518ad4674f42d247","lib\/DAV\/Calendar.php":"d5c4c28c133eb2586a88463f071352ce","lib\/Errors\/InternalError.php":"fa1142d277981f6c1b798197a7b00a8f","lib\/Service\/DefaultBoardService.php":"572ffa1af2238f641b3cd88af73a892d","lib\/Service\/OverviewService.php":"406329da0afebf5e3f46fade9e93a3b3","lib\/Service\/PermissionService.php":"b3d647f2aab926d47db621aed4c7d6a7","lib\/Service\/Importer\/BoardImportService.php":"123cd210419fd7d393abeb6769f1daeb","lib\/Service\/Importer\/ABoardImportService.php":"d585d9ae854ef7e2d8f7785da163797f","lib\/Service\/Importer\/Systems\/DeckJsonService.php":"7f963589760b18702198d72e5f394e89","lib\/Service\/Importer\/Systems\/TrelloApiService.php":"685c9fc96ef7dddb4495b545f8b454cf","lib\/Service\/Importer\/Systems\/TrelloJsonService.php":"c6eb3043adcf9c4d083cbbe95433490b","lib\/Service\/Importer\/BoardImportCommandService.php":"1ee4e2ed1728ce6cff2af3fb0ceaea5b","lib\/Service\/AttachmentService.php":"124c8bdcd47cea3900a3723fbdca5ecc","lib\/Service\/CardService.php":"4ad547f512986cccd912f2c23337373d","lib\/Service\/FullTextSearchService.php":"fa0d4be054ef537531c3f273b15205d4","lib\/Service\/FilesAppService.php":"7e884fe79dc5f1cb6a77f630e8ba4512","lib\/Service\/FileService.php":"7245f27c159f584bd3b63469306fe0cd","lib\/Service\/CommentService.php":"a08ddac9d4b83e7c75763114faeb9d60","lib\/Service\/ConfigService.php":"11fe57b7c3668241a4994f4388e37cd8","lib\/Service\/AssignmentService.php":"e5d234bfd269c4966ca9a7129b9eb290","lib\/Service\/IAttachmentService.php":"43e00697aae1b373f8c4743a78dbef76","lib\/Service\/LabelService.php":"ccc83d1f5cb17c891acf7536664c9e17","lib\/Service\/BoardService.php":"ffd893eb940b8d5287f168c3330652fe","lib\/Service\/ICustomAttachmentService.php":"bd73412ad67f16033d87923fbcc8218b","lib\/Service\/SessionService.php":"e71e3cb0653d78719b2026a295dfcc57","lib\/Service\/ExternalBoardService.php":"c47ed5fa34eb24285aa2f6ab2a457a1d","lib\/Service\/StackService.php":"f9b0ecda3ecc3257a31d3cdd1c7d9a8f","lib\/Service\/SearchService.php":"22d5cbd4323c5b06c21cce2666e43670","lib\/Service\/CirclesService.php":"eb642cfdc4ce03580bfe4ce554e0c8a6","lib\/Migration\/Version10800Date20220422061816.php":"e8ba6f14ef20588edf01b7a07f5aefdf","lib\/Migration\/Version1000Date20200306161713.php":"82562a9b61c5a31613f59aa208534d12","lib\/Migration\/Version11001Date20251020122010.php":"72cc7254bbcfa17c2fd1db53f9a59b67","lib\/Migration\/Version10200Date20201111150114.php":"376a20164d1e9d50741c4e3c7bb4a89e","lib\/Migration\/Version1011Date20230901010840.php":"c0caea1dc1dbc9352c1f76e11b8ce004","lib\/Migration\/Version10900Date202206151724222.php":"86343d019bd5a172e4429369d8f4a2e3","lib\/Migration\/DeletedCircleCleanup.php":"17532a9418c1628c624df5cbda1e2856","lib\/Migration\/Version1000Date20200308073933.php":"00bbd47ef753630b72c122ad05e1babc","lib\/Migration\/Version11000Date20240222115515.php":"41fad9525613b229dab223fc39c1c219","lib\/Migration\/Version11001Date20251009165313.php":"df683d835cc1b633a48b6943d31c8ab9","lib\/Migration\/Version1011Date20231106160059.php":"fc35eb1e761a591390e004fb55b2cb22","lib\/Migration\/LabelMismatchCleanup.php":"ce4ae70d420fa9c0723718f1ba8baa25","lib\/Event\/AclUpdatedEvent.php":"1cc52e39754bcb8190ca6ada6b0f8174","lib\/Event\/SessionClosedEvent.php":"6405cae8b34bed4bbd667f5fa7078cd1","lib\/Event\/SessionCreatedEvent.php":"e13f0d2234a37ea4d3fb411f3536bc3c","lib\/Event\/CardDeletedEvent.php":"978a67335acc5c25a5e500c63498a7bb","lib\/Event\/AclCreatedEvent.php":"80c8dec71734902af22ba3e1081a8a08","lib\/Event\/ACardEvent.php":"0492ee448c3e9b167b806109b5475986","lib\/Event\/AclDeletedEvent.php":"60f760f0596a646771ed8dc513f4ffca","lib\/Event\/CardCreatedEvent.php":"411acb38a86528c87302ce49541c8b04","lib\/Event\/ABoardImportGetAllowedEvent.php":"9764edc27ee52eac04886852cc36c847","lib\/Event\/BoardImportGetAllowedEvent.php":"ef470b14f40108c09151cd129bec63ed","lib\/Event\/AAclEvent.php":"4ee2811c708009e20532e1183c4dccf7","lib\/Event\/BoardUpdatedEvent.php":"55c8911833ceeed09d33e74696a37d31","lib\/Event\/CardUpdatedEvent.php":"0a3ff12304b822494f69bb953d38b801","lib\/Listeners\/CommentEventListener.php":"452b0557762d19c881875a1b7c11ee34","lib\/Listeners\/FullTextSearchEventListener.php":"f01ba7c49df2072e6c8aa6984e3d84a3","lib\/Listeners\/BeforeTemplateRenderedListener.php":"3fb2d67b4a095e8aa34fff6f4d54acc3","lib\/Listeners\/AclCreatedRemovedListener.php":"1ffdeafea807e7a7006f5448c59dc040","lib\/Listeners\/ParticipantCleanupListener.php":"a1f28800657269d3049667369e508ac0","lib\/Listeners\/ResourceTypeRegisterListener.php":"7aae7055704560632b18bf6f3466cac4","lib\/Listeners\/ResourceAdditionalScriptsListener.php":"75f2c119b90801ade237594d04e8c88b","lib\/Listeners\/LiveUpdateListener.php":"8bd7c93d9a27a93de05e4732189e9d67","lib\/Listeners\/ResourceListener.php":"a11490b2d551b06c7fee73697bdd0b73","lib\/Reference\/CardReferenceProvider.php":"7c0daed5705113156d078bd7f2d37300","lib\/Reference\/CommentReferenceProvider.php":"15a93c88f8710758c3ec345141fb0284","lib\/Reference\/CreateCardReferenceProvider.php":"0a49dc73285a760ce575d9c71eb055ce","lib\/Reference\/BoardReferenceProvider.php":"ed5ca614b07b3ac7e107baf1cda88f98","lib\/AppInfo\/Application.php":"fa7133173f1174ea87787e24d037401a","lib\/Cron\/SessionsCleanup.php":"5542e5a486fbb17afb017b7d7fccb8a4","lib\/Cron\/CardDescriptionActivity.php":"d8910db39280acaeb6f64297cc4f6bf3","lib\/Cron\/ScheduledNotifications.php":"0266f829a96a39b9a7b1e0ba0f501070","lib\/Cron\/DeleteCron.php":"a3d3037c79354b3eb9f069c4b2344f23","templates\/main.php":"0ba2f93de5f8c4358fb6ef45f91c3ff9","appinfo\/autoload.php":"c9887cd20064590621418f687e8be54e","appinfo\/routes.php":"5b4628e0883658c32bdc604d5cdb7c7a"}} \ No newline at end of file