Big refactor to create route Import participants Signed-off-by: Vitor Mattos <vitor@php.rio>
364 lines
9.9 KiB
PHP
364 lines
9.9 KiB
PHP
<?php
|
|
/**
|
|
* @copyright Copyright (c) 2021 Vitor Mattos <vitor@php.rio>
|
|
*
|
|
* @author Vitor Mattos <vitor@php.rio>
|
|
*
|
|
* @license GNU AGPL version 3 or any later version
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Affero General Public License as
|
|
* published by the Free Software Foundation, either version 3 of the
|
|
* License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Affero General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
namespace OCA\Deck\Service;
|
|
|
|
use JsonSchema\Constraints\Constraint;
|
|
use JsonSchema\Validator;
|
|
use OCA\Deck\AppInfo\Application;
|
|
use OCA\Deck\BadRequestException;
|
|
use OCA\Deck\Db\AclMapper;
|
|
use OCA\Deck\Db\Board;
|
|
use OCA\Deck\Db\BoardMapper;
|
|
use OCA\Deck\Db\Card;
|
|
use OCA\Deck\Db\CardMapper;
|
|
use OCA\Deck\Db\Label;
|
|
use OCA\Deck\Db\LabelMapper;
|
|
use OCA\Deck\Db\StackMapper;
|
|
use OCA\Deck\NotFoundException;
|
|
use OCP\Comments\IComment;
|
|
use OCP\Comments\ICommentsManager;
|
|
use OCP\Comments\MessageTooLongException;
|
|
use OCP\Comments\NotFoundException as CommentNotFoundException;
|
|
use OCP\IDBConnection;
|
|
use OCP\IUserManager;
|
|
|
|
class BoardImportService {
|
|
/** @var IDBConnection */
|
|
protected $dbConn;
|
|
/** @var IUserManager */
|
|
private $userManager;
|
|
/** @var BoardMapper */
|
|
private $boardMapper;
|
|
/** @var AclMapper */
|
|
private $aclMapper;
|
|
/** @var LabelMapper */
|
|
private $labelMapper;
|
|
/** @var StackMapper */
|
|
private $stackMapper;
|
|
/** @var CardMapper */
|
|
private $cardMapper;
|
|
/** @var ICommentsManager */
|
|
private $commentsManager;
|
|
/** @var string */
|
|
private $system;
|
|
/** @var ABoardImportService */
|
|
private $systemInstance;
|
|
/** @var string[] */
|
|
private $allowedSystems;
|
|
/**
|
|
* Data object created from config JSON
|
|
*
|
|
* @var \stdClass
|
|
*/
|
|
public $config;
|
|
/**
|
|
* Data object created from JSON of origin system
|
|
*
|
|
* @var \stdClass
|
|
*/
|
|
private $data;
|
|
/** @var Board */
|
|
private $board;
|
|
|
|
public function __construct(
|
|
IDBConnection $dbConn,
|
|
IUserManager $userManager,
|
|
BoardMapper $boardMapper,
|
|
AclMapper $aclMapper,
|
|
LabelMapper $labelMapper,
|
|
StackMapper $stackMapper,
|
|
CardMapper $cardMapper,
|
|
ICommentsManager $commentsManager
|
|
) {
|
|
$this->dbConn = $dbConn;
|
|
$this->userManager = $userManager;
|
|
$this->boardMapper = $boardMapper;
|
|
$this->aclMapper = $aclMapper;
|
|
$this->labelMapper = $labelMapper;
|
|
$this->stackMapper = $stackMapper;
|
|
$this->cardMapper = $cardMapper;
|
|
$this->commentsManager = $commentsManager;
|
|
}
|
|
|
|
public function import(): void {
|
|
$this->validate();
|
|
$schemaPath = __DIR__ . '/fixtures/config-' . $system . '-schema.json';
|
|
$validator = new Validator();
|
|
$validator->validate(
|
|
$config,
|
|
(object)['$ref' => 'file://' . realpath($schemaPath)],
|
|
Constraint::CHECK_MODE_APPLY_DEFAULTS
|
|
);
|
|
if (!$validator->isValid()) {
|
|
throw new BadRequestException('invalid config');
|
|
}
|
|
|
|
if (empty($data)) {
|
|
throw new BadRequestException('data must be provided');
|
|
}
|
|
$this->getImportService()->setData($data);
|
|
$this->getImportService()->import();
|
|
// return $newBoard;
|
|
}
|
|
|
|
public function validate(): self {
|
|
if (is_string($system) === false) {
|
|
throw new BadRequestException('system must be provided');
|
|
}
|
|
|
|
if (!in_array($system, $this->getAllowedImportSystems())) {
|
|
throw new BadRequestException('not allowed system');
|
|
}
|
|
|
|
if (empty($config)) {
|
|
throw new BadRequestException('config must be provided');
|
|
}
|
|
return $this;
|
|
}
|
|
|
|
public function setSystem(string $system): self {
|
|
$this->system = $system;
|
|
return $this;
|
|
}
|
|
|
|
public function getSystem() {
|
|
return $this->system;
|
|
}
|
|
|
|
public function getAllowedImportSystems(): array {
|
|
if (!$this->allowedSystems) {
|
|
$allowedSystems = glob(__DIR__ . '/BoardImport*Service.php');
|
|
$allowedSystems = array_filter($allowedSystems, function($name) {
|
|
$name = basename($name);
|
|
switch($name) {
|
|
case 'ABoardImportService.php':
|
|
case 'BoardImportService.php':
|
|
case 'BoardImportCommandService.php':
|
|
return false;
|
|
}
|
|
return true;
|
|
});
|
|
$this->allowedSystems = array_map(function ($name) {
|
|
preg_match('/\/BoardImport(?<system>\w+)Service\.php$/', $name, $matches);
|
|
return lcfirst($matches['system']);
|
|
}, $allowedSystems);
|
|
}
|
|
return $this->allowedSystems;
|
|
}
|
|
|
|
public function getImportSystem(): ABoardImportService {
|
|
$systemClass = 'OCA\\Deck\\Service\\BoardImport' . ucfirst($this->getSystem()) . 'Service';
|
|
if (!is_object($this->systemInstance)) {
|
|
$this->systemInstance = \OC::$server->get($systemClass);
|
|
$this->systemInstance->setImportService($this);
|
|
}
|
|
|
|
return $this->systemInstance;
|
|
}
|
|
|
|
public function importBoard() {
|
|
$board = $this->getImportSystem()->getBoard();
|
|
if ($board) {
|
|
$this->boardMapper->insert($board);
|
|
$this->board = $board;
|
|
}
|
|
return $this;
|
|
}
|
|
|
|
public function getBoard(): Board {
|
|
return $this->board;
|
|
}
|
|
|
|
public function importAcl(): self {
|
|
$aclList = $this->getImportSystem()->getAclList();
|
|
foreach ($aclList as $acl) {
|
|
$this->aclMapper->insert($acl);
|
|
}
|
|
return $this;
|
|
}
|
|
|
|
public function importLabels(): self {
|
|
$this->getImportSystem()->importLabels();
|
|
return $this;
|
|
}
|
|
|
|
public function createLabel($title, $color, $boardId): Label {
|
|
$label = new Label();
|
|
$label->setTitle($title);
|
|
$label->setColor($color);
|
|
$label->setBoardId($boardId);
|
|
return $this->labelMapper->insert($label);
|
|
}
|
|
|
|
public function importStacks(): self {
|
|
$stack = $this->getImportSystem()->getStacks();
|
|
foreach ($stack as $code => $stack) {
|
|
$this->stackMapper->insert($stack);
|
|
$this->getImportSystem()->updateStack($code, $stack);
|
|
}
|
|
return $this;
|
|
}
|
|
|
|
public function importCards(): self {
|
|
$cards = $this->getImportSystem()->getCards();
|
|
foreach ($cards as $code => $card) {
|
|
$this->cardMapper->insert($card);
|
|
$this->getImportSystem()->updateCard($code, $card);
|
|
}
|
|
return $this;
|
|
}
|
|
|
|
public function assignCardToLabel($cardId, $labelId): self {
|
|
$this->cardMapper->assignLabel(
|
|
$cardId,
|
|
$labelId
|
|
);
|
|
return $this;
|
|
}
|
|
|
|
public function assignCardsToLabels(): self {
|
|
$this->getImportSystem()->assignCardsToLabels();
|
|
return $this;
|
|
}
|
|
|
|
public function importComments(): self {
|
|
$this->getImportSystem()->importComments();
|
|
return $this;
|
|
}
|
|
|
|
public function insertComment($cardId, IComment $comment): IComment {
|
|
$comment->setObject('deckCard', (string) $cardId);
|
|
$comment->setVerb('comment');
|
|
// Check if parent is a comment on the same card
|
|
if ($comment->getParentId() !== '0') {
|
|
try {
|
|
$comment = $this->commentsManager->get($comment->getParentId());
|
|
if ($comment->getObjectType() !== Application::COMMENT_ENTITY_TYPE || $comment->getObjectId() !== $cardId) {
|
|
throw new CommentNotFoundException();
|
|
}
|
|
} catch (CommentNotFoundException $e) {
|
|
throw new BadRequestException('Invalid parent id: The parent comment was not found or belongs to a different card');
|
|
}
|
|
}
|
|
|
|
try {
|
|
$qb = $this->dbConn->getQueryBuilder();
|
|
|
|
$values = [
|
|
'parent_id' => $qb->createNamedParameter($comment->getParentId()),
|
|
'topmost_parent_id' => $qb->createNamedParameter($comment->getTopmostParentId()),
|
|
'children_count' => $qb->createNamedParameter($comment->getChildrenCount()),
|
|
'actor_type' => $qb->createNamedParameter($comment->getActorType()),
|
|
'actor_id' => $qb->createNamedParameter($comment->getActorId()),
|
|
'message' => $qb->createNamedParameter($comment->getMessage()),
|
|
'verb' => $qb->createNamedParameter($comment->getVerb()),
|
|
'creation_timestamp' => $qb->createNamedParameter($comment->getCreationDateTime(), 'datetime'),
|
|
'latest_child_timestamp' => $qb->createNamedParameter($comment->getLatestChildDateTime(), 'datetime'),
|
|
'object_type' => $qb->createNamedParameter($comment->getObjectType()),
|
|
'object_id' => $qb->createNamedParameter($comment->getObjectId()),
|
|
'reference_id' => $qb->createNamedParameter($comment->getReferenceId())
|
|
];
|
|
|
|
$affectedRows = $qb->insert('comments')
|
|
->values($values)
|
|
->execute();
|
|
|
|
if ($affectedRows > 0) {
|
|
$comment->setId((string)$qb->getLastInsertId());
|
|
}
|
|
return $comment;
|
|
} catch (\InvalidArgumentException $e) {
|
|
throw new BadRequestException('Invalid input values');
|
|
} catch (CommentNotFoundException $e) {
|
|
throw new NotFoundException('Could not create comment.');
|
|
}
|
|
}
|
|
|
|
public function importParticipants() {
|
|
$this->getImportSystem()->importParticipants();
|
|
}
|
|
|
|
public function setData(\stdClass $data): self {
|
|
$this->data = $data;
|
|
return $this;
|
|
}
|
|
|
|
public function getData() {
|
|
return $this->data;
|
|
}
|
|
|
|
/**
|
|
* Define a config
|
|
*
|
|
* @param string $configName
|
|
* @param mixed $value
|
|
* @return self
|
|
*/
|
|
public function setConfig(string $configName, $value): self {
|
|
if (!$this->config) {
|
|
$this->setConfigInstance(new \stdClass);
|
|
}
|
|
$this->config->$configName = $value;
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Get a config
|
|
*
|
|
* @param string $configName config name
|
|
* @return mixed
|
|
*/
|
|
public function getConfig(string $configName = null) {
|
|
if (!is_object($this->config)) {
|
|
return;
|
|
}
|
|
if (!$configName) {
|
|
return $this->config;
|
|
}
|
|
if (!property_exists($this->config, $configName)) {
|
|
return;
|
|
}
|
|
return $this->config->$configName;
|
|
}
|
|
|
|
public function setConfigInstance(\stdClass $config): self {
|
|
$this->config = $config;
|
|
return $this;
|
|
}
|
|
|
|
public function validateOwner(): self {
|
|
$owner = $this->userManager->get($this->getConfig('owner'));
|
|
if (!$owner) {
|
|
throw new \LogicException('Owner "' . $this->getConfigboardImportService->getConfig('owner')->getUID() . '" not found on Nextcloud. Check setting json.');
|
|
}
|
|
$this->setConfig('owner', $owner);
|
|
return $this;
|
|
}
|
|
|
|
public function validateUsers(): self {
|
|
$this->getImportSystem()->validateUsers();
|
|
return $this;
|
|
}
|
|
}
|