diff --git a/lib/Db/BookmarkMapper.php b/lib/Db/BookmarkMapper.php
index 741065bc0..d309804ad 100644
--- a/lib/Db/BookmarkMapper.php
+++ b/lib/Db/BookmarkMapper.php
@@ -895,6 +895,10 @@ public function insert(Entity $entity): Bookmark {
return $entity;
} catch (Exception $e) {
if ($e->getReason() === Exception::REASON_UNIQUE_CONSTRAINT_VIOLATION) {
+ if ($this->db->inTransaction()) {
+ $this->db->commit();
+ $this->db->beginTransaction();
+ }
throw new AlreadyExistsError('A bookmark with this URL already exists');
}
throw $e;
diff --git a/lib/Service/HtmlExporter.php b/lib/Service/HtmlExporter.php
index 4e5cb2a4a..cd3f60036 100644
--- a/lib/Service/HtmlExporter.php
+++ b/lib/Service/HtmlExporter.php
@@ -70,7 +70,9 @@ public function exportFolder(string $userId, int $folderId): string {
Bookmarks';
- $file .= $this->serializeFolder($userId, $folderId, true);
+ $file .= "\n";
+ $file .= $this->serializeFolder($userId, $folderId);
+ $file .= "
\n";
return $file;
}
@@ -84,14 +86,15 @@ public function exportFolder(string $userId, int $folderId): string {
* @throws MultipleObjectsReturnedException
* @throws UnauthorizedAccessError
*/
- protected function serializeFolder(string $userId, int $id, bool $onlyContent = false): string {
- if ($onlyContent) {
- $output = '';
- } else {
- $folder = $this->folderMapper->find($id);
- $output = '
' . htmlspecialchars($folder->getTitle()) . '
' . "\n"
- . '';
+ protected function serializeFolder(string $userId, int $id, string $indent = ''): string {
+ $output = '';
+ $nextIndent = $indent . ' ';
+ $childFolders = $this->treeMapper->findChildren(TreeMapper::TYPE_FOLDER, $id);
+ foreach ($childFolders as $childFolder) {
+ $output .= $indent . '
' . htmlspecialchars($childFolder->getTitle()) . '
' . "\n";
+ $output .= $indent . '' . "\n" . $this->serializeFolder($userId, $childFolder->getId(), $nextIndent) . '
' . "\n";
}
+
$childBookmarks = $this->treeMapper->findChildren(TreeMapper::TYPE_BOOKMARK, $id);
foreach ($childBookmarks as $bookmark) {
// discards records with no URL. This should not happen but
@@ -105,25 +108,15 @@ protected function serializeFolder(string $userId, int $id, bool $onlyContent =
$tags = Util::sanitizeHTML(implode(',', $tags));
$title = trim($bookmark->getTitle());
$url = Util::sanitizeHTML($bookmark->getUrl());
- if ($title === '') {
- $title = $url;
- }
$title = Util::sanitizeHTML($title);
$description = Util::sanitizeHTML($bookmark->getDescription());
- $output .= '
- ' . $title . '' . "\n";
+ $output .= $indent . '
- ' . $title . '' . "\n";
if ($description !== '') {
$output .= '
- ' . $description . '
';
}
$output .= "\n";
}
-
- $childFolders = $this->treeMapper->findChildren(TreeMapper::TYPE_FOLDER, $id);
- foreach ($childFolders as $childFolder) {
- $output .= $this->serializeFolder($userId, $childFolder->getId());
- }
-
- $output .= '
';
return $output;
}
}
diff --git a/tests/HtmlImportExportTest.php b/tests/HtmlImportExportTest.php
index a011307a6..156f0ed72 100644
--- a/tests/HtmlImportExportTest.php
+++ b/tests/HtmlImportExportTest.php
@@ -131,7 +131,7 @@ public function testExport(...$bookmarks): void {
// Set up database
for ($i = 0; $i < 4; $i++) {
$f = new Db\Folder();
- $f->setTitle($i);
+ $f->setTitle(md5($i));
$f->setUserId($this->userId);
$f = $this->folderMapper->insert($f);
$this->treeMapper->move(Db\TreeMapper::TYPE_FOLDER, $f->getId(), $rootFolder->getId());
@@ -143,13 +143,32 @@ public function testExport(...$bookmarks): void {
$exported = $this->htmlExporter->exportFolder($this->userId, $rootFolder->getId());
- $rootFolders = $this->treeMapper->findChildren(Db\TreeMapper::TYPE_FOLDER, $rootFolder->getId());
- $this->assertCount(4, $rootFolders);
- foreach ($rootFolders as $rootFolder) {
- foreach ($this->treeMapper->findChildren(Db\TreeMapper::TYPE_BOOKMARK, $rootFolder->getId()) as $bookmark) {
+ $exportedRootFolders = $this->treeMapper->findChildren(Db\TreeMapper::TYPE_FOLDER, $rootFolder->getId());
+ $this->assertCount(4, $exportedRootFolders);
+ foreach ($exportedRootFolders as $exportedRootFolder) {
+ foreach ($this->treeMapper->findChildren(Db\TreeMapper::TYPE_BOOKMARK, $exportedRootFolder->getId()) as $bookmark) {
+ $this->assertStringContainsString($exportedRootFolder->getTitle(), $exported);
$this->assertStringContainsString($bookmark->getUrl(), $exported);
}
}
+
+ $f = new Db\Folder();
+ $f->setTitle('Testimport');
+ $f->setUserId($this->userId);
+ $f = $this->folderMapper->insert($f);
+ $this->htmlImporter->import($this->userId, $exported, $f->getId());
+ $importedRootFolders = $this->treeMapper->findChildren(Db\TreeMapper::TYPE_FOLDER, $f->getId());
+ foreach ($importedRootFolders as $i => $importedRootFolder) {
+ $exportedRootFolder = $exportedRootFolders[$i];
+ $this->assertEquals($importedRootFolder->getTitle(), $exportedRootFolder->getTitle());
+ $exportedBookmarks = $this->treeMapper->findChildren(Db\TreeMapper::TYPE_BOOKMARK, $exportedRootFolder->getId());
+ foreach ($this->treeMapper->findChildren(Db\TreeMapper::TYPE_BOOKMARK, $importedRootFolder->getId()) as $j => $bookmark) {
+ $this->assertEquals($bookmark->getUrl(), $exportedBookmarks[$j]->getUrl());
+ $this->assertEquals($bookmark->getTitle(), $exportedBookmarks[$j]->getTitle());
+ $this->assertEquals($bookmark->getDescription(), $exportedBookmarks[$j]->getDescription());
+ $this->assertEquals($this->tagMapper->findByBookmark($bookmark->getId()), $this->tagMapper->findByBookmark($exportedBookmarks[$j]->getId()));
+ }
+ }
}
public function importProvider(): array {
@@ -166,10 +185,10 @@ public function exportProvider(): array {
return Db\Bookmark::fromArray($props);
}, [
['url' => 'https://google.com/', 'title' => 'Google', 'description' => 'Search engine'],
- ['url' => 'https://nextcloud.com/', 'title' => 'Nextcloud', 'description' => ''],
+ ['url' => 'https://nextcloud.com/', 'title' => 'Nextcloud', 'description' => 'cloud cloud cloud'],
['url' => 'https://php.net/', 'title' => '', 'description' => ''],
- ['url' => 'https://de.wikipedia.org/wiki/%C3%9C', 'title' => '', 'description' => ''],
- ['url' => 'https://github.com/nextcloud/bookmarks/projects/1', 'title' => '', 'description' => ''],
+ ['url' => 'https://de.wikipedia.org/wiki/%C3%9C', 'title' => '', 'description' => 'Hello
'],
+ ['url' => 'https://github.com/nextcloud/bookmarks/projects/1', 'title' => '', 'description' => ''],
]),
];
}