|
33 | 33 | use Icewind\Streams\CountWrapper; |
34 | 34 | use Icewind\Streams\IteratorDirectory; |
35 | 35 | use OC\Files\Cache\CacheEntry; |
| 36 | +use OC\Files\Storage\PolyFill\CopyDirectory; |
| 37 | +use OCP\Files\Cache\ICacheEntry; |
| 38 | +use OCP\Files\FileInfo; |
36 | 39 | use OCP\Files\NotFoundException; |
37 | 40 | use OCP\Files\ObjectStore\IObjectStore; |
38 | 41 |
|
39 | 42 | class ObjectStoreStorage extends \OC\Files\Storage\Common { |
| 43 | + use CopyDirectory; |
| 44 | + |
40 | 45 | /** |
41 | 46 | * @var \OCP\Files\ObjectStore\IObjectStore $objectStore |
42 | 47 | */ |
@@ -319,7 +324,7 @@ public function fopen($path, $mode) { |
319 | 324 | } else { |
320 | 325 | return false; |
321 | 326 | } |
322 | | - // no break |
| 327 | + // no break |
323 | 328 | case 'w': |
324 | 329 | case 'wb': |
325 | 330 | case 'w+': |
@@ -474,7 +479,7 @@ public function writeStream(string $path, $stream, int $size = null): int { |
474 | 479 | if ($size === null) { |
475 | 480 | $countStream = CountWrapper::wrap($stream, function ($writtenSize) use ($fileId, &$size) { |
476 | 481 | $this->getCache()->update($fileId, [ |
477 | | - 'size' => $writtenSize |
| 482 | + 'size' => $writtenSize, |
478 | 483 | ]); |
479 | 484 | $size = $writtenSize; |
480 | 485 | }); |
@@ -523,4 +528,59 @@ public function writeStream(string $path, $stream, int $size = null): int { |
523 | 528 | public function getObjectStore(): IObjectStore { |
524 | 529 | return $this->objectStore; |
525 | 530 | } |
| 531 | + |
| 532 | + public function copy($path1, $path2) { |
| 533 | + $path1 = $this->normalizePath($path1); |
| 534 | + $path2 = $this->normalizePath($path2); |
| 535 | + |
| 536 | + $cache = $this->getCache(); |
| 537 | + $sourceEntry = $cache->get($path1); |
| 538 | + if (!$sourceEntry) { |
| 539 | + throw new NotFoundException('Source object not found'); |
| 540 | + } |
| 541 | + |
| 542 | + $this->copyInner($sourceEntry, $path2); |
| 543 | + |
| 544 | + return true; |
| 545 | + } |
| 546 | + |
| 547 | + private function copyInner(ICacheEntry $sourceEntry, string $to) { |
| 548 | + $cache = $this->getCache(); |
| 549 | + |
| 550 | + if ($sourceEntry->getMimeType() === FileInfo::MIMETYPE_FOLDER) { |
| 551 | + if ($cache->inCache($to)) { |
| 552 | + $cache->remove($to); |
| 553 | + } |
| 554 | + $this->mkdir($to); |
| 555 | + |
| 556 | + foreach ($cache->getFolderContentsById($sourceEntry->getId()) as $child) { |
| 557 | + $this->copyInner($child, $to . '/' . $child->getName()); |
| 558 | + } |
| 559 | + } else { |
| 560 | + $this->copyFile($sourceEntry, $to); |
| 561 | + } |
| 562 | + } |
| 563 | + |
| 564 | + private function copyFile(ICacheEntry $sourceEntry, string $to) { |
| 565 | + $cache = $this->getCache(); |
| 566 | + |
| 567 | + $sourceUrn = $this->getURN($sourceEntry->getId()); |
| 568 | + |
| 569 | + $cache->copyFromCache($cache, $sourceEntry, $to); |
| 570 | + $targetEntry = $cache->get($to); |
| 571 | + |
| 572 | + if (!$targetEntry) { |
| 573 | + throw new \Exception('Target not in cache after copy'); |
| 574 | + } |
| 575 | + |
| 576 | + $targetUrn = $this->getURN($targetEntry->getId()); |
| 577 | + |
| 578 | + try { |
| 579 | + $this->objectStore->copyObject($sourceUrn, $targetUrn); |
| 580 | + } catch (\Exception $e) { |
| 581 | + $cache->remove($to); |
| 582 | + |
| 583 | + throw $e; |
| 584 | + } |
| 585 | + } |
526 | 586 | } |
0 commit comments