Skip to content

Commit cda0403

Browse files
committed
fix(AttachmentService): keep files referenced by id in cleanupAttachments
Signed-off-by: Peter Birrer <peter.birrer@optonic.com>
1 parent e4c268e commit cda0403

2 files changed

Lines changed: 58 additions & 10 deletions

File tree

lib/Service/AttachmentService.php

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -352,10 +352,10 @@ public function createAttachmentFile(int $documentId, string $newFileName, strin
352352
$fileName = self::getUniqueFileName($saveDir, $newFileName);
353353
$newFile = $saveDir->newFile($fileName);
354354
return [
355-
'name' => $fileName,
355+
'name' => $newFile->getName(),
356356
'dirname' => $saveDir->getName(),
357357
'id' => $newFile->getId(),
358-
'documentId' => $newFile->getId(),
358+
'documentId' => $textFile->getId(),
359359
'mimetype' => $newFile->getMimetype(),
360360
];
361361
}
@@ -581,23 +581,44 @@ public function cleanupAttachments(int $fileId): int {
581581
// this only happens if the attachment dir was deleted by the user while editing the document
582582
return 0;
583583
}
584-
$attachmentsByName = [];
585-
foreach ($attachmentDir->getDirectoryListing() as $attNode) {
586-
$attachmentsByName[$attNode->getName()] = $attNode;
587-
}
588-
584+
$contentAttachmentFileIds = self::getAttachmentIdsFromContent($textFile->getContent());
589585
$contentAttachmentNames = self::getAttachmentNamesFromContent($textFile->getContent(), $fileId);
590586

591-
$toDelete = array_diff(array_keys($attachmentsByName), $contentAttachmentNames);
592-
foreach ($toDelete as $name) {
593-
$attachmentsByName[$name]->delete();
587+
$toDelete = array_filter($attachmentDir->getDirectoryListing(),
588+
function ($node) use ($contentAttachmentFileIds, $contentAttachmentNames) {
589+
return !in_array($node->getName(), $contentAttachmentNames) &&
590+
!in_array($node->getId(), $contentAttachmentFileIds);
591+
}
592+
);
593+
foreach ($toDelete as $node) {
594+
$node->delete();
594595
}
595596
return count($toDelete);
596597
}
597598
}
598599
return 0;
599600
}
600601

602+
/**
603+
* Get attachment file ids listed in the markdown file content
604+
*
605+
* @param string $content
606+
*
607+
* @return array
608+
*/
609+
public static function getAttachmentIdsFromContent(string $content): array {
610+
$matches = [];
611+
// matches [ANY_CONSIDERED_CORRECT_BY_PHP-MARKDOWN](ANY_URL/f/FILE_ID[ (preview)]) and captures FILE_ID
612+
preg_match_all(
613+
'/\[(?>[^\[\]]+|\[(?>[^\[\]]+|\[(?>[^\[\]]+|\[(?>[^\[\]]+|\[(?>[^\[\]]+|\[(?>[^\[\]]+|\[\])*\])*\])*\])*\])*\])*\]\(\S+\/f\/(\d+)(?: \(preview\))?\)/',
614+
$content,
615+
$matches,
616+
PREG_SET_ORDER
617+
);
618+
return array_map(static function (array $match) {
619+
return intval($match[1]);
620+
}, $matches);
621+
}
601622

602623
/**
603624
* Get attachment file names listed in the markdown file content

tests/unit/Service/AttachmentServiceTest.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,33 @@ public function testGetAttachmentNamesFromContent() {
4242
}
4343
}
4444

45+
public function testGetAttachmentIdsFromContent() {
46+
$urls = [
47+
'www.example.com',
48+
'http://example.com',
49+
'https://www.example.com/path/to/page',
50+
'http://sub.domain.co.uk/index.php',
51+
'https://1.2.3.4:8080/path',
52+
'http://localhost:3000/',
53+
'https://[2001:db8::1]/ipv6-check',
54+
];
55+
56+
$id = 1;
57+
$content = "some content\n";
58+
foreach (self::$attachmentNames as $name) {
59+
$linkText = preg_replace('/[[\]]/', '', $name);
60+
foreach ($urls as $url) {
61+
$addon = $id % 2 ? ' (preview)' : '';
62+
$content .= "[{$linkText}]({$url}/f/{$id}{$addon})\n";
63+
$id++;
64+
}
65+
}
66+
$content .= 'some content';
67+
68+
$computedIds = AttachmentService::getAttachmentIdsFromContent($content);
69+
$this->assertEquals(range(1, $id - 1), $computedIds);
70+
}
71+
4572
public function testGetUniqueFileName() {
4673
$fileNameList = [
4774
'foo.png',

0 commit comments

Comments
 (0)