Skip to content

Commit

Permalink
Replace glob by EventDispatcher
Browse files Browse the repository at this point in the history
Signed-off-by: Vitor Mattos <vitor@php.rio>
  • Loading branch information
vitormattos authored and juliusknorr committed Dec 30, 2021
1 parent f2b6934 commit ccd5bce
Show file tree
Hide file tree
Showing 9 changed files with 173 additions and 28 deletions.
30 changes: 29 additions & 1 deletion docs/implement-import.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,32 @@
## Implement import

* Create a new class `lib/Service/Importer/Systems/<ImportName>Service.php` where `<ImportName>` is the name of the source system.
* Create a new importer class extending `ABoardImportService`
* Create a listener for event `BoardImportGetAllowedEvent` to enable your importer.
> You can read more about listeners on [Nextcloud](https://docs.nextcloud.com/server/latest/developer_manual/basics/events.html?highlight=event#writing-a-listener) doc.
Example:

```php
class YourCustomImporterListener {
public function handle(Event $event): void {
if (!($event instanceof BoardImportGetAllowedEvent)) {
return;
}

$event->getService()->addAllowedImportSystem([
'name' => YourCustomImporterService::$name,
'class' => YourCustomImporterService::class,
'internalName' => 'YourCustomImporter'
]);
}
}
```
* Register your listener on your `Application` class like this:
```php
$dispatcher = $this->getContainer()->query(IEventDispatcher::class);
$dispatcher->registerEventListener(
BoardImportGetAllowedEvent::class,
YourCustomImporterListener::class
);
```
* Use the `lib/Service/Importer/Systems/TrelloJsonService.php` class as inspiration
44 changes: 44 additions & 0 deletions lib/Event/ABoardImportGetAllowedEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?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/>.
*
*/

declare(strict_types=1);


namespace OCA\Deck\Event;

use OCA\Deck\Service\Importer\BoardImportService;
use OCP\EventDispatcher\Event;

abstract class ABoardImportGetAllowedEvent extends Event {
private $service;

public function __construct(BoardImportService $service) {
parent::__construct();

$this->service = $service;
}

public function getService(): BoardImportService {
return $this->service;
}
}
29 changes: 29 additions & 0 deletions lib/Event/BoardImportGetAllowedEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?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/>.
*
*/

declare(strict_types=1);

namespace OCA\Deck\Event;

class BoardImportGetAllowedEvent extends ABoardImportGetAllowedEvent {
}
2 changes: 2 additions & 0 deletions lib/Service/Importer/ABoardImportService.php
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ abstract public function getLabels(): array;

abstract public function validateUsers(): void;

abstract public function getJsonSchemaPath(): string;

public function updateStack(string $id, Stack $stack): void {
$this->stacks[$id] = $stack;
}
Expand Down
3 changes: 1 addition & 2 deletions lib/Service/Importer/BoardImportCommandService.php
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,7 @@ protected function validateConfig(): void {
return $v['message'];
}, $e->getData()));
$this->getOutput()->writeln('Valid schema:');
$schemaPath = __DIR__ . '/fixtures/config-' . $this->getSystem() . '-schema.json';
$this->getOutput()->writeln(print_r(file_get_contents($schemaPath), true));
$this->getOutput()->writeln(print_r(file_get_contents($this->getJsonSchemaPath()), true));
$this->getInput()->setOption('config', '');
}
$this->validateConfig();
Expand Down
51 changes: 28 additions & 23 deletions lib/Service/Importer/BoardImportService.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,16 @@
use OCA\Deck\Db\CardMapper;
use OCA\Deck\Db\LabelMapper;
use OCA\Deck\Db\StackMapper;
use OCA\Deck\Event\BoardImportGetAllowedEvent;
use OCA\Deck\Exceptions\ConflictException;
use OCA\Deck\NotFoundException;
use OCA\Deck\Service\FileService;
use OCA\Deck\Service\Importer\Systems\TrelloApiService;
use OCA\Deck\Service\Importer\Systems\TrelloJsonService;
use OCP\Comments\IComment;
use OCP\Comments\ICommentsManager;
use OCP\Comments\NotFoundException as CommentNotFoundException;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\IUserManager;

class BoardImportService {
Expand All @@ -62,6 +67,8 @@ class BoardImportService {
private $attachmentMapper;
/** @var ICommentsManager */
private $commentsManager;
/** @var IEventDispatcher */
private $eventDispatcher;
/** @var string */
private $system = '';
/** @var null|ABoardImportService */
Expand Down Expand Up @@ -96,7 +103,8 @@ public function __construct(
AssignmentMapper $assignmentMapper,
AttachmentMapper $attachmentMapper,
CardMapper $cardMapper,
ICommentsManager $commentsManager
ICommentsManager $commentsManager,
IEventDispatcher $eventDispatcher
) {
$this->userManager = $userManager;
$this->boardMapper = $boardMapper;
Expand All @@ -107,6 +115,7 @@ public function __construct(
$this->assignmentMapper = $assignmentMapper;
$this->attachmentMapper = $attachmentMapper;
$this->commentsManager = $commentsManager;
$this->eventDispatcher = $eventDispatcher;
$this->board = new Board();
$this->disableCommentsEvents();
}
Expand Down Expand Up @@ -161,29 +170,25 @@ public function getSystem(): string {
return $this->system;
}

public function addAllowedImportSystem($system): self {
$this->allowedSystems[] = $system;
return $this;
}

public function getAllowedImportSystems(): array {
if (!$this->allowedSystems) {
$allowedSystems = glob(__DIR__ . '/Systems/*Service.php');
$allowedSystems = array_map(function ($filename) {
preg_match('/\/(?<class>(?<system>\w+)Service)\.php$/', $filename, $matches);
$className = 'OCA\Deck\Service\Importer\Systems\\'.$matches['class'];
if (!class_exists($className)) {
/** @psalm-suppress UnresolvableInclude */
require_once $className;
}
/** @psalm-suppress InvalidPropertyFetch */
$name = $className::$name;
if (empty($name)) {
$name = lcfirst($matches['system']);
}
return [
'name' => $name,
'class' => $className,
'internalName' => lcfirst($matches['system'])
];
}, $allowedSystems);
$this->allowedSystems = array_values($allowedSystems);
$this->addAllowedImportSystem([
'name' => TrelloApiService::$name,
'class' => TrelloApiService::class,
'internalName' => 'TrelloApi'
]);
$this->addAllowedImportSystem([
'name' => TrelloJsonService::$name,
'class' => TrelloJsonService::class,
'internalName' => 'TrelloJson'
]);
}
$this->eventDispatcher->dispatchTyped(new BoardImportGetAllowedEvent($this));
return $this->allowedSystems;
}

Expand All @@ -192,7 +197,7 @@ public function getImportSystem(): ABoardImportService {
throw new NotFoundException('System to import not found');
}
if (!is_object($this->systemInstance)) {
$systemClass = 'OCA\\Deck\\Service\\BoardImport' . ucfirst($this->getSystem()) . 'Service';
$systemClass = 'OCA\\Deck\\Service\\Importer\\Systems\\' . ucfirst($this->getSystem()) . 'Service';
$this->systemInstance = \OC::$server->get($systemClass);
$this->systemInstance->setImportService($this);
}
Expand Down Expand Up @@ -421,7 +426,7 @@ protected function validateConfig(): void {
}

public function getJsonSchemaPath(): string {
return __DIR__ . '/fixtures/config-' . $this->getSystem() . '-schema.json';
return $this->getImportSystem()->getJsonSchemaPath();
}

public function validateOwner(): void {
Expand Down
9 changes: 9 additions & 0 deletions lib/Service/Importer/Systems/TrelloApiService.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,15 @@ public function bootstrap(): void {
parent::bootstrap();
}

public function getJsonSchemaPath(): string {
return implode(DIRECTORY_SEPARATOR, [
__DIR__,
'..',
'fixtures',
'config-trelloApi-schema.json',
]);
}

private function populateActions(): void {
$data = $this->getImportService()->getData();
$data->actions = $this->doRequest(
Expand Down
9 changes: 9 additions & 0 deletions lib/Service/Importer/Systems/TrelloJsonService.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,15 @@ public function bootstrap(): void {
$this->validateUsers();
}

public function getJsonSchemaPath(): string {
return implode(DIRECTORY_SEPARATOR, [
__DIR__,
'..',
'fixtures',
'config-trelloJson-schema.json',
]);
}

public function validateUsers(): void {
if (empty($this->getImportService()->getConfig('uidRelation'))) {
return;
Expand Down
24 changes: 22 additions & 2 deletions tests/unit/Service/Importer/BoardImportServiceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,10 @@
use OCA\Deck\Db\LabelMapper;
use OCA\Deck\Db\Stack;
use OCA\Deck\Db\StackMapper;
use OCA\Deck\Event\BoardImportGetAllowedEvent;
use OCA\Deck\Service\Importer\Systems\TrelloJsonService;
use OCP\Comments\ICommentsManager;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\IDBConnection;
use OCP\IUser;
use OCP\IUserManager;
Expand All @@ -63,6 +65,8 @@ class BoardImportServiceTest extends \Test\TestCase {
private $attachmentMapper;
/** @var ICommentsManager|MockObject */
private $commentsManager;
/** @var IEventDispatcher|MockObject */
private $eventDispatcher;
/** @var TrelloJsonService|MockObject */
private $trelloJsonService;
/** @var BoardImportService|MockObject */
Expand All @@ -77,6 +81,7 @@ public function setUp(): void {
$this->assignmentMapper = $this->createMock(AssignmentMapper::class);
$this->attachmentMapper = $this->createMock(AttachmentMapper::class);
$this->commentsManager = $this->createMock(ICommentsManager::class);
$this->eventDispatcher = $this->createMock(IEventDispatcher::class);
$this->boardImportService = new BoardImportService(
$this->userManager,
$this->boardMapper,
Expand All @@ -86,18 +91,33 @@ public function setUp(): void {
$this->assignmentMapper,
$this->attachmentMapper,
$this->cardMapper,
$this->commentsManager
$this->commentsManager,
$this->eventDispatcher
);

$this->boardImportService->setSystem('trelloJson');

$this->eventDispatcher
->method('dispatchTyped')
->willReturnCallback(function (BoardImportGetAllowedEvent $event) {
$event->getService()->addAllowedImportSystem([
'name' => TrelloJsonService::$name,
'class' => TrelloJsonService::class,
'internalName' => 'trelloJson'
]);
});

$data = json_decode(file_get_contents(__DIR__ . '/../../../data/data-trelloJson.json'));
$this->boardImportService->setData($data);

$configInstance = json_decode(file_get_contents(__DIR__ . '/../../../data/config-trelloJson.json'));
$configFile = __DIR__ . '/../../../data/config-trelloJson.json';
$configInstance = json_decode(file_get_contents($configFile));
$this->boardImportService->setConfigInstance($configInstance);

$this->trelloJsonService = $this->createMock(TrelloJsonService::class);
$this->trelloJsonService
->method('getJsonSchemaPath')
->willReturn($configFile);
$this->boardImportService->setImportSystem($this->trelloJsonService);

$owner = $this->createMock(IUser::class);
Expand Down

0 comments on commit ccd5bce

Please sign in to comment.