Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/richdocuments.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulius Härtl <jus@bitgrid.net>2021-02-24 18:53:03 +0300
committerJulius Härtl <jus@bitgrid.net>2022-01-14 18:06:54 +0300
commit0948ed5520dd13a22256c3fdb66b66f93d06960d (patch)
tree04e3904f3e8bbaf924db8b4a22136e418cf51755
parent325fcf125c15dabc7a995668a9fad1141fa212c9 (diff)
Use FileCreatedFromTemplateEvent to inject the already existing empty template files for Collabora
Signed-off-by: Julius Härtl <jus@bitgrid.net> Cleanup template loading Signed-off-by: Julius Härtl <jus@bitgrid.net> Fix template handling Signed-off-by: Julius Härtl <jus@bitgrid.net>
-rw-r--r--appinfo/info.xml3
-rw-r--r--emptyTemplates/odttemplate.odtbin642 -> 0 bytes
-rw-r--r--emptyTemplates/template.docx (renamed from emptyTemplates/docxtemplate.docx)bin790 -> 790 bytes
-rw-r--r--emptyTemplates/template.odg (renamed from emptyTemplates/odgtemplate.otg)bin8158 -> 8158 bytes
-rw-r--r--emptyTemplates/template.pptx (renamed from emptyTemplates/pptxtemplate.pptx)bin836 -> 836 bytes
-rw-r--r--emptyTemplates/template.xlsx (renamed from emptyTemplates/xlsxtemplate.xlsx)bin1409 -> 1409 bytes
-rw-r--r--lib/AppInfo/Application.php3
-rw-r--r--lib/Backgroundjobs/Cleanup.php49
-rw-r--r--lib/Controller/DocumentController.php11
-rw-r--r--lib/Listener/FileCreatedFromTemplateListener.php71
-rw-r--r--lib/Migration/Version50200Date20211220212457.php51
-rw-r--r--lib/Template/CollaboraTemplateProvider.php4
-rw-r--r--lib/TemplateManager.php151
13 files changed, 299 insertions, 44 deletions
diff --git a/appinfo/info.xml b/appinfo/info.xml
index 465480a7..23bfd2b0 100644
--- a/appinfo/info.xml
+++ b/appinfo/info.xml
@@ -6,7 +6,7 @@
<description><![CDATA[This application can connect to a Collabora Online (or other) server (WOPI-like Client). Nextcloud is the WOPI Host. Please read the documentation to learn more about that.
You can also edit your documents off-line with the Collabora Office app from the **[Android](https://play.google.com/store/apps/details?id=com.collabora.libreoffice)** and **[iOS](https://apps.apple.com/us/app/collabora-office/id1440482071)** store.]]></description>
- <version>5.0.1</version>
+ <version>5.0.2-dev.1</version>
<licence>agpl</licence>
<author>Collabora Productivity based on work of Frank Karlitschek, Victor Dubiniuk</author>
<types>
@@ -31,6 +31,7 @@ You can also edit your documents off-line with the Collabora Office app from the
</dependencies>
<background-jobs>
<job>OCA\Richdocuments\Backgroundjobs\ObtainCapabilities</job>
+ <job>OCA\Richdocuments\Backgroundjobs\Cleanup</job>
</background-jobs>
<commands>
<command>OCA\Richdocuments\Command\ActivateConfig</command>
diff --git a/emptyTemplates/odttemplate.odt b/emptyTemplates/odttemplate.odt
deleted file mode 100644
index d2a8dc27..00000000
--- a/emptyTemplates/odttemplate.odt
+++ /dev/null
Binary files differ
diff --git a/emptyTemplates/docxtemplate.docx b/emptyTemplates/template.docx
index 1b8fdf5a..1b8fdf5a 100644
--- a/emptyTemplates/docxtemplate.docx
+++ b/emptyTemplates/template.docx
Binary files differ
diff --git a/emptyTemplates/odgtemplate.otg b/emptyTemplates/template.odg
index f29cd812..f29cd812 100644
--- a/emptyTemplates/odgtemplate.otg
+++ b/emptyTemplates/template.odg
Binary files differ
diff --git a/emptyTemplates/pptxtemplate.pptx b/emptyTemplates/template.pptx
index e93a532d..e93a532d 100644
--- a/emptyTemplates/pptxtemplate.pptx
+++ b/emptyTemplates/template.pptx
Binary files differ
diff --git a/emptyTemplates/xlsxtemplate.xlsx b/emptyTemplates/template.xlsx
index 42e73eca..42e73eca 100644
--- a/emptyTemplates/xlsxtemplate.xlsx
+++ b/emptyTemplates/template.xlsx
Binary files differ
diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php
index 696fb4e6..a8af2239 100644
--- a/lib/AppInfo/Application.php
+++ b/lib/AppInfo/Application.php
@@ -31,6 +31,7 @@ use OCA\Files_Sharing\Listener\LoadAdditionalListener;
use OCA\Richdocuments\AppConfig;
use OCA\Richdocuments\Capabilities;
use OCA\Richdocuments\Middleware\WOPIMiddleware;
+use OCA\Richdocuments\Listener\FileCreatedFromTemplateListener;
use OCA\Richdocuments\PermissionManager;
use OCA\Richdocuments\Preview\MSExcel;
use OCA\Richdocuments\Preview\MSWord;
@@ -48,6 +49,7 @@ use OCP\AppFramework\Bootstrap\IBootContext;
use OCP\AppFramework\Bootstrap\IBootstrap;
use OCP\AppFramework\Bootstrap\IRegistrationContext;
use OCP\EventDispatcher\IEventDispatcher;
+use OCP\Files\Template\FileCreatedFromTemplateEvent;
use OCP\Files\Template\ITemplateManager;
use OCP\Files\Template\TemplateFileCreator;
use OCP\IConfig;
@@ -68,6 +70,7 @@ class Application extends App implements IBootstrap {
$context->registerTemplateProvider(CollaboraTemplateProvider::class);
$context->registerCapability(Capabilities::class);
$context->registerMiddleWare(WOPIMiddleware::class);
+ $context->registerEventListener(FileCreatedFromTemplateEvent::class, FileCreatedFromTemplateListener::class);
}
public function boot(IBootContext $context): void {
diff --git a/lib/Backgroundjobs/Cleanup.php b/lib/Backgroundjobs/Cleanup.php
new file mode 100644
index 00000000..e5adb55a
--- /dev/null
+++ b/lib/Backgroundjobs/Cleanup.php
@@ -0,0 +1,49 @@
+<?php
+/**
+ * @copyright Copyright (c) 2019, Roeland Jago Douma <roeland@famdouma.nl>
+ *
+ * @author Roeland Jago Douma <roeland@famdouma.nl>
+ *
+ * @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\Backgroundjobs;
+
+use OC\BackgroundJob\TimedJob;
+use OCA\Richdocuments\Service\CapabilitiesService;
+use OCP\DB\QueryBuilder\IQueryBuilder;
+use OCP\IDBConnection;
+
+class Cleanup extends TimedJob {
+
+ /** @var IDBConnection */
+ private $db;
+
+ public function __construct(IDBConnection $db) {
+ $this->db = $db;
+
+ $this->setInterval(60*60);
+ }
+
+ protected function run($argument) {
+ // Expire template mappings for file creation
+ $query = $this->db->getQueryBuilder();
+ $query->delete('richdocuments_template')
+ ->where($query->expr()->lte('timestamp', $query->createNamedParameter(time() - 60, IQueryBuilder::PARAM_INT)));
+ $query->executeStatement();
+ }
+}
diff --git a/lib/Controller/DocumentController.php b/lib/Controller/DocumentController.php
index 9f1f7cec..8e1932a2 100644
--- a/lib/Controller/DocumentController.php
+++ b/lib/Controller/DocumentController.php
@@ -11,6 +11,7 @@
namespace OCA\Richdocuments\Controller;
+use OCA\Richdocuments\AppInfo\Application;
use OCA\Richdocuments\Events\BeforeFederationRedirectEvent;
use OCA\Richdocuments\Service\FederationService;
use OCA\Richdocuments\Service\InitialStateService;
@@ -210,7 +211,14 @@ class DocumentController extends Controller {
return $response;
}
- list($urlSrc, $token, $wopi) = $this->tokenManager->getToken($item->getId());
+ $templateFile = $this->templateManager->getTemplateSource($item->getId());
+ if ($templateFile) {
+ list($urlSrc, $wopi) = $this->tokenManager->getTokenForTemplate($templateFile, $this->uid, $item->getId());
+ $token = $wopi->getToken();
+ } else {
+ list($urlSrc, $token, $wopi) = $this->tokenManager->getToken($item->getId());
+ }
+
$params = [
'permissions' => $item->getPermissions(),
'title' => $item->getName(),
@@ -575,6 +583,7 @@ class DocumentController extends Controller {
}
if (!$content){
+ // FIXME: see if this is used,
$content = file_get_contents(dirname(dirname(__DIR__)) . self::ODT_TEMPLATE_PATH);
}
diff --git a/lib/Listener/FileCreatedFromTemplateListener.php b/lib/Listener/FileCreatedFromTemplateListener.php
new file mode 100644
index 00000000..6cc4d472
--- /dev/null
+++ b/lib/Listener/FileCreatedFromTemplateListener.php
@@ -0,0 +1,71 @@
+<?php
+/*
+ * @copyright Copyright (c) 2021 Julius Härtl <jus@bitgrid.net>
+ *
+ * @author Julius Härtl <jus@bitgrid.net>
+ *
+ * @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\Richdocuments\Listener;
+
+
+use OCA\Richdocuments\AppInfo\Application;
+use OCA\Richdocuments\TemplateManager;
+use OCP\EventDispatcher\Event;
+use OCP\EventDispatcher\IEventListener;
+use OCP\Files\Template\FileCreatedFromTemplateEvent;
+use OCP\IConfig;
+
+class FileCreatedFromTemplateListener implements IEventListener {
+
+ /** @var TemplateManager */
+ private $templateManager;
+
+ public function __construct(
+ TemplateManager $templateManager
+ ) {
+ $this->templateManager = $templateManager;
+ }
+
+ public function handle(Event $event): void {
+ if (!($event instanceof FileCreatedFromTemplateEvent)) {
+ return;
+ }
+
+ $templateFile = $event->getTemplate();
+
+ // Empty template
+ if ($templateFile === null) {
+ $event->getTarget()->putContent($this->templateManager->getEmptyFileContent($event->getTarget()->getExtension()));
+ return;
+ }
+
+ if ($this->templateManager->isSupportedTemplateSource($templateFile->getExtension())) {
+ // Only use TemplateSource if supported filetype
+ $this->templateManager->setTemplateSource($event->getTarget()->getId(), $templateFile->getId());
+ }
+
+ // Avoid having the mimetype of the source file set
+ $event->getTarget()->getStorage()->getCache()->update($event->getTarget()->getId(), [
+ 'mimetype' => $event->getTarget()->getMimeType()
+ ]);
+ }
+}
diff --git a/lib/Migration/Version50200Date20211220212457.php b/lib/Migration/Version50200Date20211220212457.php
new file mode 100644
index 00000000..5eb408c1
--- /dev/null
+++ b/lib/Migration/Version50200Date20211220212457.php
@@ -0,0 +1,51 @@
+<?php
+
+declare(strict_types=1);
+
+namespace OCA\Richdocuments\Migration;
+
+use Closure;
+use OCP\DB\ISchemaWrapper;
+use OCP\Migration\IOutput;
+use OCP\Migration\SimpleMigrationStep;
+
+/**
+ * Auto-generated migration step: Please modify to your needs!
+ */
+class Version50200Date20211220212457 extends SimpleMigrationStep {
+ public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
+ /** @var ISchemaWrapper $schema */
+ $schema = $schemaClosure();
+
+ if (!$schema->hasTable('richdocuments_template')) {
+ $table = $schema->createTable('richdocuments_template');
+ $table->addColumn('id', 'bigint', [
+ 'autoincrement' => true,
+ 'notnull' => true,
+ 'length' => 20,
+ 'unsigned' => true,
+ ]);
+ $table->addColumn('userid', 'string', [
+ 'notnull' => false,
+ 'length' => 64,
+ ]);
+ $table->addColumn('fileid', 'bigint', [
+ 'notnull' => true,
+ 'length' => 20,
+ ]);
+ $table->addColumn('templateid', 'bigint', [
+ 'notnull' => true,
+ 'length' => 20,
+ ]);
+ $table->addColumn('timestamp', 'bigint', [
+ 'notnull' => true,
+ 'length' => 20,
+ 'unsigned' => true,
+ ]);
+ $table->setPrimaryKey(['id']);
+ $table->addUniqueIndex(['userid', 'fileid'], 'rd_t_user_file');
+ }
+
+ return $schema;
+ }
+}
diff --git a/lib/Template/CollaboraTemplateProvider.php b/lib/Template/CollaboraTemplateProvider.php
index 409ba70c..e7abad9d 100644
--- a/lib/Template/CollaboraTemplateProvider.php
+++ b/lib/Template/CollaboraTemplateProvider.php
@@ -91,8 +91,4 @@ class CollaboraTemplateProvider implements ICustomTemplateProvider {
public function getCustomTemplate(string $template): File {
return $this->templateManager->get((int)$template);
}
-
- public function createFromTemplate(File $template, File $target): void {
- // TODO: Implement createFromTemplate() method.
- }
}
diff --git a/lib/TemplateManager.php b/lib/TemplateManager.php
index 2974a9c6..1f4d1499 100644
--- a/lib/TemplateManager.php
+++ b/lib/TemplateManager.php
@@ -24,6 +24,8 @@ declare (strict_types = 1);
namespace OCA\Richdocuments;
+use OCA\Richdocuments\AppInfo\Application;
+use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\Files\File;
use OCP\Files\Folder;
use OCP\Files\IAppData;
@@ -31,17 +33,15 @@ use OCP\Files\IRootFolder;
use OCP\Files\Node;
use OCP\Files\NotFoundException;
use OCP\IConfig;
+use OCP\IDBConnection;
use OCP\IL10N;
-use OCP\IPreview;
use OCP\IURLGenerator;
-use OC\Files\AppData\Factory;
+use Psr\Log\LoggerInterface;
+use Throwable;
class TemplateManager {
/** @var string */
- protected $appName;
-
- /** @var string */
protected $userId;
/** @var IConfig */
@@ -56,6 +56,15 @@ class TemplateManager {
/** @var IL10N */
private $l;
+ /** @var IDBConnection */
+ private $db;
+
+ /** @var IAppData */
+ private $appData;
+
+ /** @var LoggerInterface */
+ private $logger;
+
/** Accepted templates mime types */
const MIMES_DOCUMENTS = [
'application/vnd.oasis.opendocument.text-template',
@@ -97,39 +106,27 @@ class TemplateManager {
'presentation' => 'pptx',
];
- /**
- * Template manager
- *
- * @param string $appName
- * @param string $userId
- * @param IConfig $config
- * @param Factory $appDataFactory
- * @param IURLGenerator $urlGenerator
- * @param IRootFolder $rootFolder
- * @param IL10N $l
- * @throws \OCP\Files\NotPermittedException
- */
- public function __construct($appName,
- $userId,
- IConfig $config,
- IAppData $appData,
- IURLGenerator $urlGenerator,
- IRootFolder $rootFolder,
- IL10N $l) {
- $this->appName = $appName;
- $this->userId = $userId;
- $this->config = $config;
- $this->rootFolder = $rootFolder;
- $this->urlGenerator = $urlGenerator;
-
-
+ public function __construct(
+ $userId,
+ IConfig $config,
+ IAppData $appData,
+ IURLGenerator $urlGenerator,
+ IRootFolder $rootFolder,
+ IL10N $l,
+ IDBConnection $connection,
+ LoggerInterface $logger
+ ) {
+ $this->userId = $userId;
+ $this->config = $config;
+ $this->rootFolder = $rootFolder;
+ $this->urlGenerator = $urlGenerator;
+ $this->db = $connection;
+ $this->logger = $logger;
$this->appData = $appData;
- $this->createAppDataFolders();
-
$this->l = $l;
}
- private function createAppDataFolders() {
+ private function ensureAppDataFolders() {
/*
* Init the appdata folder
* We need an actual folder for the fileid and previews.
@@ -200,7 +197,7 @@ class TemplateManager {
});
}
- private function getEmpty($type = null) {
+ public function getEmpty($type = null) {
$folder = $this->getEmptyTemplateDir();
$templateFiles = $folder->getDirectoryListing();
@@ -228,6 +225,7 @@ class TemplateManager {
* Remove empty_templates in appdata and recreate it from the apps templates
*/
public function updateEmptyTemplates() {
+ $this->ensureAppDataFolders();
try {
$folder = $this->getEmptyTemplateDir();
$folder->delete();
@@ -393,7 +391,7 @@ class TemplateManager {
}
// has the user manually set a directory as the default template dir ?
- $templateDirPath = $this->config->getUserValue($this->userId, $this->appName, 'templateFolder', false);
+ $templateDirPath = $this->config->getUserValue($this->userId, Application::APPNAME, 'templateFolder', false);
$userFolder = $this->rootFolder->getUserFolder($this->userId);
if ($templateDirPath !== false) {
@@ -418,6 +416,7 @@ class TemplateManager {
* @return Folder
*/
private function getSystemTemplateDir() {
+ $this->ensureAppDataFolders();
$path = 'appdata_' . $this->config->getSystemValue('instanceid', null) . '/richdocuments/templates';
return $this->rootFolder->get($path);
}
@@ -426,6 +425,7 @@ class TemplateManager {
* @return Folder
*/
private function getEmptyTemplateDir() {
+ $this->ensureAppDataFolders();
$path = 'appdata_' . $this->config->getSystemValue('instanceid', null) . '/richdocuments/empty_templates';
return $this->rootFolder->get($path);
}
@@ -437,7 +437,7 @@ class TemplateManager {
* @return array
*/
public function formatNodeReturn(File $template) {
- $ooxml = $this->config->getAppValue($this->appName, 'doc_format', '') === 'ooxml';
+ $ooxml = $this->config->getAppValue(Application::APPNAME, 'doc_format', '') === 'ooxml';
$documentType = $this->flipTypes()[$template->getMimeType()];
return [
'id' => $template->getId(),
@@ -466,7 +466,7 @@ class TemplateManager {
}
public function formatEmpty(File $template) {
- $ooxml = $this->config->getAppValue($this->appName, 'doc_format', '') === 'ooxml';
+ $ooxml = $this->config->getAppValue(Application::APPNAME, 'doc_format', '') === 'ooxml';
$documentType = $this->flipTypes()[$template->getMimeType()];
return [
'id' => $template->getId(),
@@ -490,4 +490,79 @@ class TemplateManager {
return true;
}
+
+ /**
+ * Return default content for empty files of a given filename by file extension
+ */
+ public function getEmptyFileContent(string $extension): string {
+ $supportedExtensions = ['odt', 'ods', 'odp', 'odg', 'docx', 'xlsx', 'pptx'];
+ $emptyPath = __DIR__ . '/../emptyTemplates/template.' . $extension;
+
+ if (in_array($extension, $supportedExtensions, true) && file_exists($emptyPath)) {
+ return file_get_contents($emptyPath);
+ }
+
+ return '';
+ }
+
+ public function isSupportedTemplateSource(string $extension): bool {
+ $supportedExtensions = ['ott', 'otg', 'otp', 'ots'];
+ return in_array($extension, $supportedExtensions, true);
+ }
+
+ public function setTemplateSource(int $fileId, int $templateId): void {
+ try {
+ $query = $this->db->getQueryBuilder();
+ $query->insert('richdocuments_template')
+ ->values([
+ 'userid' => $query->createNamedParameter($this->userId),
+ 'fileid' => $query->createNamedParameter($fileId, IQueryBuilder::PARAM_INT),
+ 'templateid' => $query->createNamedParameter($templateId, IQueryBuilder::PARAM_INT),
+ 'timestamp' => $query->createNamedParameter(time(), IQueryBuilder::PARAM_INT)
+ ]);
+ $query->executeStatement();
+ } catch (Throwable $e) {
+ $this->logger->warning('Could not store template source', ['exception' => $e]);
+ // Ignore failure and proceed with empty template
+ }
+ }
+
+ public function getTemplateSource(int $fileId): ?File {
+ $templateId = 0;
+ try {
+ $query = $this->db->getQueryBuilder();
+ $query->select('templateid')
+ ->from('richdocuments_template')
+ ->where($query->expr()->eq('userid', $query->createNamedParameter($this->userId)))
+ ->andWhere($query->expr()->eq('fileid', $query->createNamedParameter($fileId, IQueryBuilder::PARAM_INT)));
+ $result = $query->executeQuery();
+ $templateId = (int)$result->fetchOne();
+
+ $query->delete('richdocuments_template')
+ ->where($query->expr()->eq('userid', $query->createNamedParameter($this->userId)))
+ ->andWhere($query->expr()->eq('fileid', $query->createNamedParameter($fileId, IQueryBuilder::PARAM_INT)));
+ $query->executeStatement();
+ } catch (Throwable $e) {
+ // Ignore failure and proceed with empty template
+ $this->logger->warning('Could not retrieve template source', ['exception' => $e]);
+ return null;
+ }
+
+ if ($templateId !== 0) {
+ try {
+ $template = $this->get($templateId);
+ } catch (NotFoundException $e) {
+ $userFolder = $this->rootFolder->getUserFolder($this->userId);
+ try {
+ $template = $userFolder->getById($templateId);
+ } catch (NotFoundException $e) {
+ $this->logger->warning('Could not retrieve template source file', ['exception' => $e]);
+ return null;
+ }
+ }
+ return $template;
+ }
+
+ return null;
+ }
}