Skip to content

Commit

Permalink
Implement direct editing API
Browse files Browse the repository at this point in the history
Signed-off-by: Raul <[email protected]>

Implement direct editing API

Signed-off-by: Raul <[email protected]>
  • Loading branch information
Raudius authored and juliusknorr committed Aug 29, 2024
1 parent 4c37f2a commit 9981fe3
Show file tree
Hide file tree
Showing 7 changed files with 482 additions and 0 deletions.
3 changes: 3 additions & 0 deletions lib/AppInfo/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
use OCA\Richdocuments\Listener\ReferenceListener;
use OCA\Richdocuments\Listener\RegisterTemplateFileCreatorListener;
use OCA\Richdocuments\Listener\ShareLinkListener;
use OCA\Richdocuments\Listener\RegisterDirectEditorEventListener;
use OCA\Richdocuments\Middleware\WOPIMiddleware;
use OCA\Richdocuments\Preview\EMF;
use OCA\Richdocuments\Preview\MSExcel;
Expand All @@ -40,6 +41,7 @@
use OCP\Collaboration\Reference\RenderReferenceEvent;
use OCP\Collaboration\Resources\LoadAdditionalScriptsEvent;
use OCP\Files\Template\BeforeGetTemplatesEvent;
use OCP\DirectEditing\RegisterDirectEditorEvent;
use OCP\Files\Template\FileCreatedFromTemplateEvent;
use OCP\Files\Template\RegisterTemplateCreatorEvent;
use OCP\Preview\BeforePreviewFetchedEvent;
Expand Down Expand Up @@ -80,6 +82,7 @@ public function register(IRegistrationContext $context): void {
$context->registerPreviewProvider(OOXML::class, OOXML::MIMETYPE_REGEX);
$context->registerPreviewProvider(OpenDocument::class, OpenDocument::MIMETYPE_REGEX);
$context->registerPreviewProvider(Pdf::class, Pdf::MIMETYPE_REGEX);
$context->registerEventListener(RegisterDirectEditorEvent::class, RegisterDirectEditorEventListener::class);
}

public function boot(IBootContext $context): void {
Expand Down
198 changes: 198 additions & 0 deletions lib/DirectEditing/DirectEditor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
<?php
/**
* @copyright Copyright (c) 2022 Raul Ferreira Fuentes <[email protected]>
*
* @author Raul Ferreira Fuentes <[email protected]>
*
* @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\Richdocuments\DirectEditing;

use OCA\Richdocuments\AppConfig;
use OCA\Richdocuments\AppInfo\Application;
use OCA\Richdocuments\Capabilities;
use OCA\Richdocuments\Controller\DocumentTrait;
use OCA\Richdocuments\Service\InitialStateService;
use OCA\Richdocuments\TokenManager;
use OCP\AppFramework\Http\NotFoundResponse;
use OCP\AppFramework\Http\Response;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\DirectEditing\IEditor;
use OCP\DirectEditing\IToken;
use OCP\Files\InvalidPathException;
use OCP\Files\IRootFolder;
use OCP\Files\NotFoundException;
use OCP\Files\NotPermittedException;
use OCP\IConfig;
use OCP\IInitialStateService;
use OCP\IL10N;
use Psr\Log\LoggerInterface;

class DirectEditor implements IEditor {
use DocumentTrait;

/** @var IL10N */
private $l10n;

/** @var IInitialStateService */
private $initialStateService;

/** @var string[] */
private $mimetypes;

/** @var TokenManager */
private $tokenManager;

/** @var IRootFolder */
private $rootFolder;

/** @var IConfig */
private $config;

/** @var AppConfig */
private $appConfig;

/** @var LoggerInterface */
private $logger;


public function __construct(
IL10N $l10n,
InitialStateService $initialStateService,
Capabilities $capabilities,
TokenManager $tokenManager,
IConfig $config,
AppConfig $appConfig,
IRootFolder $rootFolder,
LoggerInterface $logger
) {
$this->l10n = $l10n;
$this->initialStateService = $initialStateService;

Check failure on line 85 in lib/DirectEditing/DirectEditor.php

View workflow job for this annotation

GitHub Actions / static-psalm-analysis

InvalidPropertyAssignmentValue

lib/DirectEditing/DirectEditor.php:85:32: InvalidPropertyAssignmentValue: $this->initialStateService with declared type 'OCP\IInitialStateService' cannot be assigned type 'OCA\Richdocuments\Service\InitialStateService' (see https://psalm.dev/145)
$this->mimetypes = $capabilities->getCapabilities()[Application::APPNAME]['mimetypes'];
$this->tokenManager = $tokenManager;
$this->config = $config;
$this->appConfig = $appConfig;
$this->rootFolder = $rootFolder;
$this->logger = $logger;
}

/**
* Return a unique identifier for the editor
*
* e.g. richdocuments
*
* @return string
*/
public function getId(): string {
return Application::APPNAME;
}

/**
* Return a readable name for the editor
*
* e.g. Collabora Online
*
* @return string
*/
public function getName(): string {
return $this->l10n->t('Nextcloud Office');
}

/**
* A list of mimetypes that should open the editor by default
*
* @return array

Check failure on line 119 in lib/DirectEditing/DirectEditor.php

View workflow job for this annotation

GitHub Actions / static-psalm-analysis

LessSpecificImplementedReturnType

lib/DirectEditing/DirectEditor.php:119:13: LessSpecificImplementedReturnType: The inherited return type 'array<array-key, string>' for OCP\DirectEditing\IEditor::getMimetypes is more specific than the implemented return type for OCA\Richdocuments\DirectEditing\DirectEditor::getmimetypes 'array<array-key, mixed>' (see https://psalm.dev/166)
*/
public function getMimetypes(): array {
return $this->mimetypes;
}

/**
* A list of mimetypes that can be opened in the editor optionally
*
* @return array

Check failure on line 128 in lib/DirectEditing/DirectEditor.php

View workflow job for this annotation

GitHub Actions / static-psalm-analysis

LessSpecificImplementedReturnType

lib/DirectEditing/DirectEditor.php:128:13: LessSpecificImplementedReturnType: The inherited return type 'array<array-key, string>' for OCP\DirectEditing\IEditor::getMimetypesOptional is more specific than the implemented return type for OCA\Richdocuments\DirectEditing\DirectEditor::getmimetypesoptional 'array<array-key, mixed>' (see https://psalm.dev/166)
*/
public function getMimetypesOptional(): array {
return [];
}

/**
* Return a list of file creation options to be presented to the user
*
* @return array of ACreateFromTemplate|ACreateEmpty

Check failure on line 137 in lib/DirectEditing/DirectEditor.php

View workflow job for this annotation

GitHub Actions / static-psalm-analysis

LessSpecificImplementedReturnType

lib/DirectEditing/DirectEditor.php:137:13: LessSpecificImplementedReturnType: The inherited return type 'array<array-key, OCP\DirectEditing\ACreateEmpty>' for OCP\DirectEditing\IEditor::getCreators is more specific than the implemented return type for OCA\Richdocuments\DirectEditing\DirectEditor::getcreators 'array<array-key, mixed>' (see https://psalm.dev/166)
*/
public function getCreators(): array {
return [
new GraphicsCreator($this->l10n),
new PresentationCreator($this->l10n),

Check failure on line 142 in lib/DirectEditing/DirectEditor.php

View workflow job for this annotation

GitHub Actions / static-psalm-analysis

TooFewArguments

lib/DirectEditing/DirectEditor.php:142:4: TooFewArguments: Too few arguments for OCA\Richdocuments\DirectEditing\PresentationCreator::__construct - expecting config to be passed (see https://psalm.dev/025)
new SpreadsheetCreator($this->l10n),

Check failure on line 143 in lib/DirectEditing/DirectEditor.php

View workflow job for this annotation

GitHub Actions / static-psalm-analysis

TooFewArguments

lib/DirectEditing/DirectEditor.php:143:4: TooFewArguments: Too few arguments for OCA\Richdocuments\DirectEditing\SpreadsheetCreator::__construct - expecting config to be passed (see https://psalm.dev/025)
new TextCreator($this->l10n),

Check failure on line 144 in lib/DirectEditing/DirectEditor.php

View workflow job for this annotation

GitHub Actions / static-psalm-analysis

TooFewArguments

lib/DirectEditing/DirectEditor.php:144:4: TooFewArguments: Too few arguments for OCA\Richdocuments\DirectEditing\TextCreator::__construct - expecting config to be passed (see https://psalm.dev/025)
];
}

/**
* Return if the view is able to securely view a file without downloading it to the browser
*
* @return bool
*/
public function isSecure(): bool {
return true;
}

/**
* Return a template response for displaying the editor
*
* open can only be called once when the client requests the editor with a one-time-use token
* For handling editing and later requests, editors need to impelement their own token handling and take care of invalidation
*
* This behavior is similar to the current direct editing implementation in collabora where we generate a one-time token and switch over to the regular wopi token for the actual editing/saving process
*
* @param IToken $token
* @return Response
*/
public function open(IToken $token): Response {
$token->useTokenScope();
try {
$folder = $this->rootFolder->getUserFolder($token->getUser());
$item = $token->getFile();

[$urlSrc, $token, $wopi] = $this->tokenManager->getToken($item->getId(), null, $token->getUser(), true);

Check failure on line 174 in lib/DirectEditing/DirectEditor.php

View workflow job for this annotation

GitHub Actions / static-psalm-analysis

UndefinedMethod

lib/DirectEditing/DirectEditor.php:174:52: UndefinedMethod: Method OCA\Richdocuments\TokenManager::getToken does not exist (see https://psalm.dev/022)

$params = [
'permissions' => $item->getPermissions(),
'title' => $item->getName(),
'fileId' => $wopi->getFileid() . '_' . $this->config->getSystemValue('instanceid'),
'token' => $wopi->getToken(),
'token_ttl' => $wopi->getExpiry(),
'urlsrc' => $urlSrc,
'path' => $folder->getRelativePath($item->getPath()),
'instanceId' => $this->config->getSystemValue('instanceid'),
'canonical_webroot' => $this->appConfig->getAppValue('canonical_webroot'),
'direct' => true,
];

$this->initialStateService->provideDocument($wopi);

Check failure on line 189 in lib/DirectEditing/DirectEditor.php

View workflow job for this annotation

GitHub Actions / static-psalm-analysis

UndefinedInterfaceMethod

lib/DirectEditing/DirectEditor.php:189:32: UndefinedInterfaceMethod: Method OCP\IInitialStateService::provideDocument does not exist (see https://psalm.dev/181)
$response = new TemplateResponse('richdocuments', 'documents', $params, 'base');
$this->applyPolicies($response);
return $response;
} catch (InvalidPathException|NotFoundException|NotPermittedException $e) {
$this->logger->error($e->getMessage());
}
return new NotFoundResponse();
}
}
55 changes: 55 additions & 0 deletions lib/DirectEditing/GraphicsCreator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php
/**
* @copyright Copyright (c) 2022 Raul Ferreira Fuentes <[email protected]>
*
* @author Raul Ferreira Fuentes <[email protected]>
*
* @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\Richdocuments\DirectEditing;

use OCP\DirectEditing\ACreateEmpty;
use OCP\IL10N;

class GraphicsCreator extends ACreateEmpty {

/**
* @var IL10N
*/
private $l10n;

public function __construct(IL10N $l10n) {
$this->l10n = $l10n;
}

public function getId(): string {
return 'richdocuments_graphics';
}

public function getName(): string {
return $this->l10n->t('diagram');
}

public function getExtension(): string {
return 'odg';
}

public function getMimetype(): string {
return 'application/vnd.oasis.opendocument.graphics';
}
}
59 changes: 59 additions & 0 deletions lib/DirectEditing/PresentationCreator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php
/**
* @copyright Copyright (c) 2022 Raul Ferreira Fuentes <[email protected]>
*
* @author Raul Ferreira Fuentes <[email protected]>
*
* @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\Richdocuments\DirectEditing;

use OCA\Richdocuments\AppInfo\Application;
use OCP\DirectEditing\ACreateEmpty;
use OCP\IConfig;
use OCP\IL10N;

class PresentationCreator extends ACreateEmpty {

/** @var IL10N */
private $l10n;
/** @var IConfig */
private $config;

public function __construct(IL10N $l10n, IConfig $config) {
$this->l10n = $l10n;
$this->config = $config;
}

public function getId(): string {
return 'richdocuments_presentation';
}

public function getName(): string {
return $this->l10n->t('presentation');
}

public function getExtension(): string {
$useOoxml = $this->config->getAppValue(Application::APPNAME, 'doc_format', '') === 'ooxml';
return $useOoxml ? 'pptx' : 'odp';
}

public function getMimetype(): string {
return 'application/vnd.oasis.opendocument.presentation';
}
}
59 changes: 59 additions & 0 deletions lib/DirectEditing/SpreadsheetCreator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php
/**
* @copyright Copyright (c) 2022 Raul Ferreira Fuentes <[email protected]>
*
* @author Raul Ferreira Fuentes <[email protected]>
*
* @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\Richdocuments\DirectEditing;

use OCA\Richdocuments\AppInfo\Application;
use OCP\DirectEditing\ACreateEmpty;
use OCP\IConfig;
use OCP\IL10N;

class SpreadsheetCreator extends ACreateEmpty {

/** @var IL10N */
private $l10n;
/** @var IConfig */
private $config;

public function __construct(IL10N $l10n, IConfig $config) {
$this->l10n = $l10n;
$this->config = $config;
}

public function getId(): string {
return 'richdocuments_spreadsheet';
}

public function getName(): string {
return $this->l10n->t('spreadsheet');
}

public function getExtension(): string {
$useOoxml = $this->config->getAppValue(Application::APPNAME, 'doc_format', '') === 'ooxml';
return $useOoxml ? 'xlsx' : 'ods';
}

public function getMimetype(): string {
return 'application/vnd.oasis.opendocument.spreadsheet';
}
}
Loading

0 comments on commit 9981fe3

Please sign in to comment.