Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement direct editing API #2405

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 <raul@nextcloud.com>
*
* @author Raul Ferreira Fuentes <raul@nextcloud.com>
*
* @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)
Raudius marked this conversation as resolved.
Show resolved Hide resolved
];
}

/**
* 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 <raul@nextcloud.com>
*
* @author Raul Ferreira Fuentes <raul@nextcloud.com>
*
* @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 <raul@nextcloud.com>
*
* @author Raul Ferreira Fuentes <raul@nextcloud.com>
*
* @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 <raul@nextcloud.com>
*
* @author Raul Ferreira Fuentes <raul@nextcloud.com>
*
* @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
Loading