1 Commits

Author SHA1 Message Date
Sebastian f39dd75ae5 fix: folder deletion while in trash
Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
2026-08-07 20:45:29 -04:00
2 changed files with 40 additions and 23 deletions
Generated
+14 -14
View File
@@ -8,21 +8,21 @@
"packages": [ "packages": [
{ {
"name": "guzzlehttp/guzzle", "name": "guzzlehttp/guzzle",
"version": "7.15.3", "version": "7.15.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/guzzle/guzzle.git", "url": "https://github.com/guzzle/guzzle.git",
"reference": "ae311b8f045ea93ce7b1c9cdb7cec06c53f944bc" "reference": "61443dfb33c62f308ee8add20f45b4d6e4bf8d2f"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/ae311b8f045ea93ce7b1c9cdb7cec06c53f944bc", "url": "https://api.github.com/repos/guzzle/guzzle/zipball/61443dfb33c62f308ee8add20f45b4d6e4bf8d2f",
"reference": "ae311b8f045ea93ce7b1c9cdb7cec06c53f944bc", "reference": "61443dfb33c62f308ee8add20f45b4d6e4bf8d2f",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"ext-json": "*", "ext-json": "*",
"guzzlehttp/promises": "^2.5.2", "guzzlehttp/promises": "^2.5.1",
"guzzlehttp/psr7": "^2.13", "guzzlehttp/psr7": "^2.13",
"php": "^7.2.5 || ^8.0", "php": "^7.2.5 || ^8.0",
"psr/http-client": "^1.0", "psr/http-client": "^1.0",
@@ -116,7 +116,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/guzzle/guzzle/issues", "issues": "https://github.com/guzzle/guzzle/issues",
"source": "https://github.com/guzzle/guzzle/tree/7.15.3" "source": "https://github.com/guzzle/guzzle/tree/7.15.1"
}, },
"funding": [ "funding": [
{ {
@@ -132,20 +132,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2026-08-05T19:48:21+00:00" "time": "2026-07-18T11:23:11+00:00"
}, },
{ {
"name": "guzzlehttp/promises", "name": "guzzlehttp/promises",
"version": "2.5.2", "version": "2.5.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/guzzle/promises.git", "url": "https://github.com/guzzle/promises.git",
"reference": "2823687acff28b2dbe67b2508a6b300e2c3fa4ce" "reference": "9ad1e4fc607446a055b95870c7f668e93b5cff29"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/guzzle/promises/zipball/2823687acff28b2dbe67b2508a6b300e2c3fa4ce", "url": "https://api.github.com/repos/guzzle/promises/zipball/9ad1e4fc607446a055b95870c7f668e93b5cff29",
"reference": "2823687acff28b2dbe67b2508a6b300e2c3fa4ce", "reference": "9ad1e4fc607446a055b95870c7f668e93b5cff29",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -200,7 +200,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/guzzle/promises/issues", "issues": "https://github.com/guzzle/promises/issues",
"source": "https://github.com/guzzle/promises/tree/2.5.2" "source": "https://github.com/guzzle/promises/tree/2.5.1"
}, },
"funding": [ "funding": [
{ {
@@ -216,7 +216,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2026-08-05T19:30:54+00:00" "time": "2026-07-08T15:48:39+00:00"
}, },
{ {
"name": "guzzlehttp/psr7", "name": "guzzlehttp/psr7",
@@ -2556,5 +2556,5 @@
"platform-overrides": { "platform-overrides": {
"php": "8.3" "php": "8.3"
}, },
"plugin-api-version": "2.9.0" "plugin-api-version": "2.6.0"
} }
+26 -9
View File
@@ -484,17 +484,34 @@ class Service implements ServiceBaseInterface, ServiceMutableInterface, ServiceC
} }
} }
// we need to determine if the folder being deleted is already in the trash if ($deleteMode === 'soft') {
if (str_starts_with((string) $target->collection(), (string) $deleteTargetIdentifier?->collection())) { $targetMailbox = $this->mailService->collectionFetch((string) $target->collection());
// if so, we should hard delete instead of moving to avoid duplicates in the trash if ($targetMailbox === null) {
$deleteMode = 'hard'; throw new \RuntimeException('Collection not found for delete operation');
} }
$result = match ($deleteMode) { $targetIdentifier = (string) $target->collection();
'soft' => $this->collectionMove($deleteTargetIdentifier, $target), $trashIdentifier = (string) $deleteTargetIdentifier->collection();
'hard' => $this->mailService->collectionDestroy($target->collection(), $force), $parentIdentifier = isset($targetMailbox['parentId'])
}; ? (string) $targetMailbox['parentId']
return $result; : null;
// JMAP mailbox IDs are opaque, so containment must be determined
// from parentId rather than by comparing ID prefixes.
if ($targetIdentifier === $trashIdentifier || $parentIdentifier === $trashIdentifier) {
$deleteMode = 'hard';
}
}
if ($deleteMode === 'soft') {
return $this->collectionMove($deleteTargetIdentifier, $target);
}
if ($this->mailService->collectionDestroy((string) $target->collection(), $force) === null) {
throw new \RuntimeException("Failed to delete collection: {$target->collection()}");
}
return true;
} }
public function collectionMove(CollectionIdentifier $target, CollectionIdentifier $source): CollectionBaseInterface public function collectionMove(CollectionIdentifier $target, CollectionIdentifier $source): CollectionBaseInterface