diff --git a/apps/comments/appinfo/app.php b/apps/comments/appinfo/app.php
index b491b1d4d3f0..bbc292dc4a1f 100644
--- a/apps/comments/appinfo/app.php
+++ b/apps/comments/appinfo/app.php
@@ -54,7 +54,7 @@ function () {
$eventDispatcher->addListener(\OCP\Comments\CommentsEntityEvent::EVENT_ENTITY, function (\OCP\Comments\CommentsEntityEvent $event) {
$event->addEntityCollection('files', function ($name) {
- $nodes = \OC::$server->getUserFolder()->getById(\intval($name));
+ $nodes = \OC::$server->getUserFolder()->getById((int)$name, true);
return !empty($nodes);
});
});
diff --git a/apps/comments/lib/Activity/Listener.php b/apps/comments/lib/Activity/Listener.php
index a4ca3b4aa463..1781286713d9 100644
--- a/apps/comments/lib/Activity/Listener.php
+++ b/apps/comments/lib/Activity/Listener.php
@@ -86,10 +86,9 @@ public function commentEvent(CommentsEvent $event) {
foreach ($mounts as $mount) {
$owner = $mount->getUser()->getUID();
$ownerFolder = $this->rootFolder->getUserFolder($owner);
- $nodes = $ownerFolder->getById($event->getComment()->getObjectId());
- if (!empty($nodes)) {
- /** @var Node $node */
- $node = \array_shift($nodes);
+ $nodes = $ownerFolder->getById($event->getComment()->getObjectId(), true);
+ $node = $nodes[0] ?? null;
+ if ($node) {
$path = $node->getPath();
if (\strpos($path, '/' . $owner . '/files/') === 0) {
$path = \substr($path, \strlen('/' . $owner . '/files'));
diff --git a/apps/comments/tests/unit/ActivityListenerTest.php b/apps/comments/tests/unit/ActivityListenerTest.php
new file mode 100644
index 000000000000..6f81cc1da7d6
--- /dev/null
+++ b/apps/comments/tests/unit/ActivityListenerTest.php
@@ -0,0 +1,151 @@
+
+ *
+ * @copyright Copyright (c) 2018, ownCloud GmbH
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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, version 3,
+ * along with this program. If not, see
+ *
+ */
+
+namespace OCA\Comments\Tests\unit;
+
+use OCA\Comments\Activity\Listener;
+use OCP\Comments\CommentsEntityEvent;
+use Test\Traits\UserTrait;
+use OCP\IUserSession;
+use OCP\Activity\IManager;
+use OCP\App\IAppManager;
+use OCP\Files\Config\IMountProviderCollection;
+use OCP\Files\IRootFolder;
+use OCP\Files\Config\IUserMountCache;
+use OCP\Files\Config\ICachedMountInfo;
+use OCP\IUser;
+use OCP\Files\Folder;
+use OCP\Activity\IEvent;
+use OCA\Comments\Activity\Extension;
+use OCP\Comments\IComment;
+use OCP\Comments\CommentsEvent;
+
+/**
+ * Tests for the activity listener
+ *
+ * @group DB
+ */
+class ActivityListenerTest extends \Test\TestCase {
+ use UserTrait;
+
+ /**
+ * @var Listener
+ */
+ private $listener;
+
+ /**
+ * @var IUserMountCache
+ */
+ private $userMountCache;
+
+ /**
+ * @var IRootFolder
+ */
+ private $rootFolder;
+
+ /**
+ * @var IUserSession
+ */
+ private $userSession;
+
+ /**
+ * @var IManager
+ */
+ private $activityManager;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->activityManager = $this->createMock(IManager::class);
+ $this->userSession = $this->createMock(IUserSession::class);
+ $appManager = $this->createMock(IAppManager::class);
+ $appManager->method('isInstalled')->with('activity')->willReturn(true);
+
+ $this->userMountCache = $this->createMock(IUserMountCache::class);
+
+ $mountProviderCollection = $this->createMock(IMountProviderCollection::class);
+ $mountProviderCollection->method('getMountCache')->willReturn($this->userMountCache);
+
+ $this->rootFolder = $this->createMock(IRootFolder::class);
+
+ // needed for the one unmockable static method "Share::getUsersSharingFile"...
+ $this->createUser('user1');
+ $this->createUser('actor1');
+
+ $this->listener = new Listener(
+ $this->activityManager,
+ $this->userSession,
+ $appManager,
+ $mountProviderCollection,
+ $this->rootFolder
+ );
+ }
+
+ public function testActivityOnFilesComment() {
+ $user = $this->createMock(IUser::class);
+ $user->method('getUID')->willReturn('user1');
+
+ $actor = $this->createMock(IUser::class);
+ $actor->method('getUID')->willReturn('actor1');
+
+ $this->userSession->method('getUser')->willReturn($actor);
+
+ $cachedMountInfo = $this->createMock(ICachedMountInfo::class);
+ $cachedMountInfo->method('getUser')->willReturn($user);
+
+ $node = $this->createMock(Folder::class);
+ $node->method('getPath')->willReturn('/user1/files/folder');
+
+ $ownerFolder = $this->createMock(Folder::class);
+ $ownerFolder->method('getById')
+ ->with(123, true)
+ ->willReturn([$node]);
+
+ $this->rootFolder->method('getUserFolder')
+ ->with('user1')
+ ->willReturn($ownerFolder);
+
+ $this->userMountCache->method('getMountsForFileId')
+ ->with(123)
+ ->willReturn([$cachedMountInfo]);
+
+ $activityEvent = $this->createMock(IEvent::class);
+ $activityEvent->expects($this->once())->method('setApp')->with('comments')->willReturn($activityEvent);
+ $activityEvent->expects($this->once())->method('setType')->with('comments')->willReturn($activityEvent);
+ $activityEvent->expects($this->once())->method('setAuthor')->with('actor1')->willReturn($activityEvent);
+ $activityEvent->expects($this->once())->method('setObject')->with('files', 123)->willReturn($activityEvent);
+ $activityEvent->expects($this->once())->method('setMessage')->with(Extension::ADD_COMMENT_MESSAGE, [111])->willReturn($activityEvent);
+
+ $this->activityManager->method('generateEvent')
+ ->willReturn($activityEvent);
+ $this->activityManager->expects($this->once())
+ ->method('publish')
+ ->with($activityEvent);
+
+ $comment = $this->createMock(IComment::class);
+ $comment->method('getObjectType')->willReturn('files');
+ $comment->method('getObjectId')->willReturn(123);
+ $comment->method('getId')->willReturn(111);
+
+ $commentsEvent = new CommentsEvent(CommentsEvent::EVENT_ADD, $comment);
+ $this->listener->commentEvent($commentsEvent);
+ }
+}
diff --git a/apps/dav/lib/Connector/Sabre/FilesReportPlugin.php b/apps/dav/lib/Connector/Sabre/FilesReportPlugin.php
index 3ea18fabfb0d..e6512b376aaf 100644
--- a/apps/dav/lib/Connector/Sabre/FilesReportPlugin.php
+++ b/apps/dav/lib/Connector/Sabre/FilesReportPlugin.php
@@ -360,9 +360,9 @@ public function findNodesByFileIds($rootNode, $fileIds) {
$results = [];
foreach ($fileIds as $fileId) {
- $entry = $folder->getById($fileId);
+ $entries = $folder->getById($fileId, true);
+ $entry = $entries[0] ?? null;
if ($entry) {
- $entry = \current($entry);
$node = $this->makeSabreNode($entry);
if ($node) {
$results[] = $node;
diff --git a/apps/dav/lib/RootCollection.php b/apps/dav/lib/RootCollection.php
index faa8e3fba63d..43eb9b178c03 100644
--- a/apps/dav/lib/RootCollection.php
+++ b/apps/dav/lib/RootCollection.php
@@ -74,7 +74,7 @@ public function __construct() {
\OC::$server->getSystemTagObjectMapper(),
\OC::$server->getUserSession(),
\OC::$server->getGroupManager(),
- \OC::$server->getRootFolder()
+ \OC::$server->getLazyRootFolder()
);
$usersCardDavBackend = new CardDavBackend($db, $userPrincipalBackend, $groupPrincipalBackend, $dispatcher);
@@ -109,7 +109,7 @@ public function __construct() {
$systemTagRelationsCollection,
$uploadCollection,
$avatarCollection,
- new \OCA\DAV\Meta\RootCollection(\OC::$server->getRootFolder()),
+ new \OCA\DAV\Meta\RootCollection(\OC::$server->getLazyRootFolder()),
$queueCollection
];
diff --git a/apps/dav/lib/SystemTag/SystemTagsObjectTypeCollection.php b/apps/dav/lib/SystemTag/SystemTagsObjectTypeCollection.php
index fa44c0b2f47b..4ffd4aa20d14 100644
--- a/apps/dav/lib/SystemTag/SystemTagsObjectTypeCollection.php
+++ b/apps/dav/lib/SystemTag/SystemTagsObjectTypeCollection.php
@@ -139,7 +139,7 @@ public function childExists($name) {
if ($this->objectType === 'files') {
// make sure the object is reachable for the current user
$userId = $this->userSession->getUser()->getUID();
- $nodes = $this->fileRoot->getUserFolder($userId)->getById(\intval($name));
+ $nodes = $this->fileRoot->getUserFolder($userId)->getById((int)$name, true);
return !empty($nodes);
}
return true;
diff --git a/apps/federatedfilesharing/lib/FederatedShareProvider.php b/apps/federatedfilesharing/lib/FederatedShareProvider.php
index c6bea791e61a..01606ce5097a 100644
--- a/apps/federatedfilesharing/lib/FederatedShareProvider.php
+++ b/apps/federatedfilesharing/lib/FederatedShareProvider.php
@@ -886,7 +886,7 @@ private function getNode($userId, $id) {
throw new InvalidShare();
}
- $nodes = $userFolder->getById($id);
+ $nodes = $userFolder->getById($id, true);
if (empty($nodes)) {
throw new InvalidShare();
diff --git a/apps/federatedfilesharing/tests/FederatedShareProviderTest.php b/apps/federatedfilesharing/tests/FederatedShareProviderTest.php
index 8b0189c4be0c..ffb0fbd6574c 100644
--- a/apps/federatedfilesharing/tests/FederatedShareProviderTest.php
+++ b/apps/federatedfilesharing/tests/FederatedShareProviderTest.php
@@ -37,6 +37,8 @@
use OCP\IUserManager;
use OCP\Share\IManager;
use OCP\Share\IShare;
+use OCP\Files\Folder;
+use OCP\IUser;
/**
* Class FederatedShareProviderTest
@@ -188,6 +190,90 @@ public function testCreate() {
$this->assertEquals('token', $share->getToken());
}
+ public function testCreateLegacy() {
+ $share = $this->shareManager->newShare();
+
+ $node = $this->createMock('\OCP\Files\File');
+ $node->method('getId')->willReturn(42);
+ $node->method('getName')->willReturn('myFile');
+
+ $share->setSharedWith('user@server.com')
+ ->setShareOwner('shareOwner')
+ ->setPermissions(19)
+ ->setNode($node);
+
+ $this->tokenHandler->method('generateToken')->willReturn('token');
+
+ $shareWithAddress = new Address('user@server.com');
+ $ownerAddress = new Address('shareOwner@http://localhost/');
+ $sharedByAddress = new Address('sharedBy@http://localhost/');
+ $this->addressHandler->expects($this->any())->method('getLocalUserFederatedAddress')
+ ->will($this->onConsecutiveCalls($ownerAddress, $sharedByAddress, $ownerAddress));
+
+ $this->addressHandler->expects($this->any())->method('splitUserRemote')
+ ->willReturn(['user', 'server.com']);
+
+ $this->notifications->expects($this->once())
+ ->method('sendRemoteShare')
+ ->with(
+ $this->equalTo($shareWithAddress),
+ $this->equalTo($ownerAddress),
+ $this->equalTo($sharedByAddress),
+ $this->equalTo('token'),
+ $this->equalTo('myFile'),
+ $this->anything()
+ )->willReturn(true);
+
+ $folderOwner = $this->createMock(IUser::class);
+ $folderOwner->method('getUID')->willReturn('folderOwner');
+ $node = $this->createMock(Folder::class);
+ $node->method('getOwner')->willReturn($folderOwner);
+
+ $userFolder = $this->createMock(Folder::class);
+ $userFolder->method('getById')
+ ->with(42, true)
+ ->willReturn([$node]);
+ $this->rootFolder->expects($this->once())
+ ->method('getUserFolder')
+ ->with('shareOwner')
+ ->willReturn($userFolder);
+
+ $share = $this->provider->create($share);
+
+ $qb = $this->connection->getQueryBuilder();
+ $stmt = $qb->select('*')
+ ->from('share')
+ ->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
+ ->execute();
+
+ $data = $stmt->fetch();
+ $stmt->closeCursor();
+
+ $expected = [
+ 'share_type' => \OCP\Share::SHARE_TYPE_REMOTE,
+ 'share_with' => 'user@server.com',
+ 'uid_owner' => 'shareOwner',
+ 'uid_initiator' => null,
+ 'item_type' => 'file',
+ 'item_source' => 42,
+ 'file_source' => 42,
+ 'permissions' => 19,
+ 'accepted' => 0,
+ 'token' => 'token',
+ ];
+ $this->assertArraySubset($expected, $data);
+
+ $this->assertEquals($data['id'], $share->getId());
+ $this->assertEquals(\OCP\Share::SHARE_TYPE_REMOTE, $share->getShareType());
+ $this->assertEquals('user@server.com', $share->getSharedWith());
+ $this->assertEquals('shareOwner', $share->getSharedBy());
+ $this->assertEquals('folderOwner', $share->getShareOwner());
+ $this->assertEquals('file', $share->getNodeType());
+ $this->assertEquals(42, $share->getNodeId());
+ $this->assertEquals(19, $share->getPermissions());
+ $this->assertEquals('token', $share->getToken());
+ }
+
public function testCreateCouldNotFindServer() {
$share = $this->shareManager->newShare();
diff --git a/apps/files/lib/ActivityHelper.php b/apps/files/lib/ActivityHelper.php
index 20ac77cbc75a..c198c10353cb 100644
--- a/apps/files/lib/ActivityHelper.php
+++ b/apps/files/lib/ActivityHelper.php
@@ -59,10 +59,9 @@ public function getFavoriteFilePaths($user) {
$rootFolder = \OC::$server->getUserFolder($user);
$folders = $items = [];
foreach ($favorites as $favorite) {
- $nodes = $rootFolder->getById($favorite);
- if (!empty($nodes)) {
- /** @var \OCP\Files\Node $node */
- $node = \array_shift($nodes);
+ $nodes = $rootFolder->getById($favorite, true);
+ $node = $nodes[0] ?? null;
+ if ($node) {
$path = \substr($node->getPath(), \strlen($user . '/files/'));
$items[] = $path;
diff --git a/apps/files/tests/ActivityHelperTest.php b/apps/files/tests/ActivityHelperTest.php
new file mode 100644
index 000000000000..e2c04ea276e8
--- /dev/null
+++ b/apps/files/tests/ActivityHelperTest.php
@@ -0,0 +1,137 @@
+
+ *
+ * @copyright Copyright (c) 2018, ownCloud GmbH
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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, version 3,
+ * along with this program. If not, see
+ *
+ */
+
+use OCA\Files\ActivityHelper;
+use OCP\ITagManager;
+use OCP\ITags;
+use Test\Traits\UserTrait;
+
+/**
+ * Class ActivityHelperTest
+ *
+ * @group DB
+ */
+class ActivityHelperTest extends \Test\TestCase {
+ use UserTrait;
+
+ /**
+ * @var ITagManager
+ */
+ private $tagManager;
+
+ /**
+ * @var ITags
+ */
+ private $tags;
+
+ /**
+ * @var ActivityHelper
+ */
+ private $helper;
+
+ /**
+ * @var string
+ */
+ private $user;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->tags = $this->createMock(ITags::class);
+
+ $this->user = $this->getUniqueID('files_activityhelpertest_user_');
+
+ // because \OC::$server->getUserFolder()
+ $this->createUser($this->user);
+ $this->loginAsUser($this->user);
+
+ $this->tagManager = $this->createMock(ITagManager::class);
+ $this->tagManager->expects($this->once())
+ ->method('load')
+ ->with('files', [], false, $this->user)
+ ->willReturn($this->tags);
+
+ $this->helper = new ActivityHelper($this->tagManager);
+ }
+
+ /**
+ * @expectedException \RuntimeException
+ * @expectedExceptionMessage No favorites
+ */
+ public function testGetFavoriteFilePathsNoFavorites() {
+ $this->tags->method('getFavorites')->willReturn([]);
+ $this->helper->getFavoriteFilePaths($this->user);
+ }
+
+ /**
+ * @expectedException \RuntimeException
+ * @expectedExceptionMessage Too many favorites
+ */
+ public function testGetFavoriteFilePathsTooManyFavorites() {
+ $tooManyFavorites = [];
+ for ($i = 0; $i < ActivityHelper::FAVORITE_LIMIT + 1; $i++) {
+ $tooManyFavorites[] = [];
+ }
+
+ $this->tags->method('getFavorites')->willReturn($tooManyFavorites);
+
+ $this->helper->getFavoriteFilePaths($this->user);
+ }
+
+ public function testGetFavoriteFilePaths() {
+ $userFolder = \OC::$server->getUserFolder();
+ $fav1 = $userFolder->newFolder('fav1');
+ $fav2 = $userFolder->newFile('fav2.txt');
+ $userFolder->newFolder('nonfav1');
+ $userFolder->newFolder('nonfav2');
+
+ $favorites = [
+ $fav1->getId(),
+ $fav2->getId(),
+ $fav2->getId() + 999, // non-existing
+ ];
+
+ $this->tags->method('getFavorites')->willReturn($favorites);
+
+ $result = $this->helper->getFavoriteFilePaths($this->user);
+
+ $this->assertEquals(['/fav1', '/fav2.txt'], $result['items']);
+ $this->assertEquals(['/fav1'], $result['folders']);
+ }
+
+ /**
+ * @expectedException \RuntimeException
+ * @expectedExceptionMessage No favorites
+ */
+ public function testGetFavoriteFilePathsMissingFolder() {
+ $userFolder = \OC::$server->getUserFolder();
+ $aFolder = $userFolder->newFolder('x');
+
+ $favorites = [
+ // non-existing
+ $aFolder->getId() + 999,
+ ];
+
+ $this->tags->method('getFavorites')->willReturn($favorites);
+
+ $result = $this->helper->getFavoriteFilePaths($this->user);
+ }
+}
diff --git a/apps/files_sharing/lib/Controller/Share20OcsController.php b/apps/files_sharing/lib/Controller/Share20OcsController.php
index bde1320991ef..8d1ee1c7645a 100644
--- a/apps/files_sharing/lib/Controller/Share20OcsController.php
+++ b/apps/files_sharing/lib/Controller/Share20OcsController.php
@@ -166,14 +166,12 @@ protected function formatShare(IShare $share, $received = false) {
$userFolder = $this->rootFolder->getUserFolder($this->currentUser->getUID());
}
- $nodes = $userFolder->getById($share->getNodeId());
-
- if (empty($nodes)) {
+ $nodes = $userFolder->getById($share->getNodeId(), true);
+ $node = $nodes[0] ?? null;
+ if ($node === null) {
throw new NotFoundException();
}
- $node = $nodes[0];
-
$result['path'] = $userFolder->getRelativePath($node->getPath());
if ($node instanceof \OCP\Files\Folder) {
$result['item_type'] = 'folder';
@@ -912,8 +910,8 @@ public function notifyRecipients($itemSource, $shareType, $recipient) {
);
$userFolder = $this->rootFolder->getUserFolder($this->currentUser->getUID());
- $nodes = $userFolder->getById($itemSource);
- $node = $nodes[0];
+ $nodes = $userFolder->getById($itemSource, true);
+ $node = $nodes[0] ?? null;
$result = $mailNotification->sendInternalShareMail($node, $shareType, $recipientList);
// if we were able to send to at least one recipient, mark as sent
@@ -950,8 +948,8 @@ public function notifyRecipients($itemSource, $shareType, $recipient) {
*/
public function notifyRecipientsDisabled($itemSource, $shareType, $recipient) {
$userFolder = $this->rootFolder->getUserFolder($this->currentUser->getUID());
- $nodes = $userFolder->getById($itemSource);
- $node = $nodes[0];
+ $nodes = $userFolder->getById($itemSource, true);
+ $node = $nodes[0] ?? null;
$items = $this->shareManager->getSharedWith($recipient, $shareType, $node);
if (\count($items) > 0) {
diff --git a/apps/files_sharing/lib/SharedMount.php b/apps/files_sharing/lib/SharedMount.php
index 3923c58da4e1..059687095d97 100644
--- a/apps/files_sharing/lib/SharedMount.php
+++ b/apps/files_sharing/lib/SharedMount.php
@@ -193,13 +193,13 @@ public function isTargetAllowed($target) {
$fileId = (int)$targetStorage->getCache()->getId(\dirname($targetInternalPath));
}
- $targetNodes = \OC::$server->getRootFolder()->getById($fileId);
- if (empty($targetNodes)) {
+ $targetNodes = \OC::$server->getRootFolder()->getById($fileId, true);
+ $targetNode = $targetNodes[0] ?? null;
+ if ($targetNode === null) {
return false;
}
$shareManager = \OC::$server->getShareManager();
- $targetNode = $targetNodes[0];
// FIXME: make it stop earlier in '/$userId/files'
while ($targetNode !== null && $targetNode->getPath() !== '/') {
$shares = $shareManager->getSharesByPath($targetNode);
diff --git a/apps/systemtags/lib/Activity/Listener.php b/apps/systemtags/lib/Activity/Listener.php
index 112ab4a8fcf9..3cbd9223235a 100644
--- a/apps/systemtags/lib/Activity/Listener.php
+++ b/apps/systemtags/lib/Activity/Listener.php
@@ -159,16 +159,15 @@ public function mapperEvent(MapperEvent $event) {
foreach ($mounts as $mount) {
$owner = $mount->getUser()->getUID();
$ownerFolder = $this->rootFolder->getUserFolder($owner);
- $nodes = $ownerFolder->getById($event->getObjectId());
- if (!empty($nodes)) {
- /** @var Node $node */
- $node = \array_shift($nodes);
+ $nodes = $ownerFolder->getById($event->getObjectId(), true);
+ $node = $nodes[0] ?? null;
+ if ($node) {
$path = $node->getPath();
if (\strpos($path, '/' . $owner . '/files/') === 0) {
$path = \substr($path, \strlen('/' . $owner . '/files'));
}
// Get all users that have access to the mount point
- $users = \array_merge($users, Share::getUsersSharingFile($path, $owner, true, true));
+ $users = \array_merge($users, $this->getUsersSharingFile($path, $owner));
}
}
@@ -227,4 +226,8 @@ protected function prepareTagAsParameter(ISystemTag $tag) {
return '{{{' . $tag->getName() . '|||assignable}}}';
}
}
+
+ public function getUsersSharingFile($path, $owner) {
+ return Share::getUsersSharingFile($path, $owner, true, true);
+ }
}
diff --git a/apps/systemtags/tests/ListenerTest.php b/apps/systemtags/tests/ListenerTest.php
deleted file mode 100644
index aad3e3c4c2b7..000000000000
--- a/apps/systemtags/tests/ListenerTest.php
+++ /dev/null
@@ -1,84 +0,0 @@
-
- *
- * @copyright Copyright (c) 2018, ownCloud GmbH
- * @license AGPL-3.0
- *
- * This code is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License, version 3,
- * as published by the Free Software Foundation.
- *
- * 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, version 3,
- * along with this program. If not, see
- *
- */
-
-namespace OCA\SystemTags\Tests;
-
-use OC\SystemTag\SystemTag;
-use OCA\SystemTags\Activity\Listener;
-use OCP\Activity\IManager;
-use OCP\App\IAppManager;
-use OCP\Files\Config\IMountProviderCollection;
-use OCP\Files\IRootFolder;
-use OCP\IGroupManager;
-use OCP\IUserSession;
-use OCP\SystemTag\ISystemTagManager;
-use Test\TestCase;
-
-class ListenerTest extends TestCase {
- /** @var IGroupManager | \PHPUnit_Framework_MockObject_MockObject */
- private $groupManager;
- /** @var IManager | \PHPUnit_Framework_MockObject_MockObject */
- private $activityManager;
- /** @var IUserSession | \PHPUnit_Framework_MockObject_MockObject */
- private $userSession;
- /** @var ISystemTagManager | \PHPUnit_Framework_MockObject_MockObject */
- private $tagManager;
- /** @var IAppManager | \PHPUnit_Framework_MockObject_MockObject */
- private $appManager;
- /** @var IMountProviderCollection | \PHPUnit_Framework_MockObject_MockObject */
- private $mountCollection;
- /** @var IRootFolder | \PHPUnit_Framework_MockObject_MockObject */
- private $rootFolder;
- /** @var Listener */
- private $listener;
-
- public function setUp() {
- parent::setUp();
-
- $this->groupManager = $this->createMock(IGroupManager::class);
- $this->activityManager = $this->createMock(IManager::class);
- $this->userSession = $this->createMock(IUserSession::class);
- $this->tagManager = $this->createMock(ISystemTagManager::class);
- $this->appManager = $this->createMock(IAppManager::class);
- $this->mountCollection = $this->createMock(IMountProviderCollection::class);
- $this->rootFolder = $this->createMock(IRootFolder::class);
- $this->listener = new Listener($this->groupManager, $this->activityManager,
- $this->userSession, $this->tagManager, $this->appManager,
- $this->mountCollection, $this->rootFolder);
- }
-
- public function prepareTagAsParameterProvider() {
- return [
- [new SystemTag('1', 'visibleTag', true, true, true), "{{{visibleTag|||assignable}}}"],
- [new SystemTag('2', 'invisibleTag', false, false, false), "{{{invisibleTag|||invisible}}}"],
- [new SystemTag('3', 'restrictTag', true, false, false), "{{{restrictTag|||not-assignable}}}"],
- [new SystemTag('3', 'staticTag', true, true, false), "{{{staticTag|||not-editable}}}"],
- ];
- }
-
- /**
- * @dataProvider prepareTagAsParameterProvider
- */
- public function testPrepareTagAsParameter(SystemTag $tag, $expectedResult) {
- $result = $this->invokePrivate($this->listener, 'prepareTagAsParameter', [$tag]);
- $this->assertEquals($expectedResult, $result);
- }
-}
diff --git a/apps/systemtags/tests/ExtensionTest.php b/apps/systemtags/tests/unit/activity/ExtensionTest.php
similarity index 100%
rename from apps/systemtags/tests/ExtensionTest.php
rename to apps/systemtags/tests/unit/activity/ExtensionTest.php
diff --git a/apps/systemtags/tests/unit/activity/ListenerTest.php b/apps/systemtags/tests/unit/activity/ListenerTest.php
new file mode 100644
index 000000000000..1ecc2df62897
--- /dev/null
+++ b/apps/systemtags/tests/unit/activity/ListenerTest.php
@@ -0,0 +1,218 @@
+
+ *
+ * @copyright Copyright (c) 2018, ownCloud GmbH
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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, version 3,
+ * along with this program. If not, see
+ *
+ */
+
+namespace OCA\SystemTags\Tests\unit;
+
+use Test\Traits\UserTrait;
+use OCA\SystemTags\Activity\Listener;
+use OCA\SystemTags\Activity\Extension;
+use OCP\IUserSession;
+use OCP\Activity\IManager;
+use OCP\App\IAppManager;
+use OCP\Files\Config\IMountProviderCollection;
+use OCP\Files\IRootFolder;
+use OCP\Files\Config\IUserMountCache;
+use OCP\Files\Config\ICachedMountInfo;
+use OCP\IUser;
+use OCP\Files\Folder;
+use OCP\Activity\IEvent;
+use OCP\SystemTag\MapperEvent;
+use OCP\IGroupManager;
+use OCP\SystemTag\ISystemTagManager;
+use OCP\SystemTag\ISystemTag;
+use OC\SystemTag\SystemTag;
+
+/**
+ * Tests for the activity listener
+ *
+ * @group DB
+ */
+class ActivityListenerTest extends \Test\TestCase {
+ use UserTrait;
+
+ /**
+ * @var IGroupManager
+ */
+ private $groupManager;
+
+ /**
+ * @var ISystemTagManager
+ */
+ private $tagManager;
+
+ /**
+ * @var Listener
+ */
+ private $listener;
+
+ /**
+ * @var IUserMountCache
+ */
+ private $userMountCache;
+
+ /**
+ * @var IRootFolder
+ */
+ private $rootFolder;
+
+ /**
+ * @var IUserSession
+ */
+ private $userSession;
+
+ /**
+ * @var IManager
+ */
+ private $activityManager;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->groupManager = $this->createMock(IGroupManager::class);
+
+ $this->tagManager = $this->createMock(ISystemTagManager::class);
+ $this->activityManager = $this->createMock(IManager::class);
+ $this->userSession = $this->createMock(IUserSession::class);
+
+ $appManager = $this->createMock(IAppManager::class);
+ $appManager->method('isInstalled')->with('activity')->willReturn(true);
+
+ $this->userMountCache = $this->createMock(IUserMountCache::class);
+
+ $mountProviderCollection = $this->createMock(IMountProviderCollection::class);
+ $mountProviderCollection->method('getMountCache')->willReturn($this->userMountCache);
+
+ $this->rootFolder = $this->createMock(IRootFolder::class);
+
+ $this->listener = $this->getMockBuilder(Listener::class)
+ ->setConstructorArgs([
+ $this->groupManager,
+ $this->activityManager,
+ $this->userSession,
+ $this->tagManager,
+ $appManager,
+ $mountProviderCollection,
+ $this->rootFolder
+ ])
+ ->setMethods(['getUsersSharingFile'])
+ ->getMock();
+ }
+
+ public function providesEventTypes() {
+ return [
+ [MapperEvent::EVENT_ASSIGN, Extension::ASSIGN_TAG],
+ [MapperEvent::EVENT_UNASSIGN, Extension::UNASSIGN_TAG],
+ ];
+ }
+
+ /**
+ * @dataProvider providesEventTypes
+ */
+ public function testActivityOnMapperEvent($eventType, $extensionEvent) {
+ $user = $this->createMock(IUser::class);
+ $user->method('getUID')->willReturn('user1');
+
+ $actor = $this->createMock(IUser::class);
+ $actor->method('getUID')->willReturn('actor1');
+
+ $this->userSession->method('getUser')->willReturn($actor);
+
+ $tag1 = $this->createMock(ISystemTag::class);
+ $tag1->method('isUserVisible')->willReturn(true);
+ $tag1->method('isUserAssignable')->willReturn(true);
+ $tag1->method('isUserEditable')->willReturn(true);
+ $tag1->method('getName')->willReturn('tag1');
+
+ $tag2 = $this->createMock(ISystemTag::class);
+ $tag2->method('isUserVisible')->willReturn(true);
+ $tag2->method('isUserAssignable')->willReturn(false);
+ $tag2->method('isUserEditable')->willReturn(false);
+ $tag2->method('getName')->willReturn('tag2');
+
+ $invisibleTag = $this->createMock(ISystemTag::class);
+ $invisibleTag->method('isUserVisible')->willReturn(false);
+
+ $this->groupManager->method('isAdmin')->willReturn(false);
+
+ $this->tagManager->method('getTagsByIds')
+ ->with([111, 222, 333])
+ ->willReturn([$tag1, $tag2, $invisibleTag]);
+
+ $cachedMountInfo = $this->createMock(ICachedMountInfo::class);
+ $cachedMountInfo->method('getUser')->willReturn($user);
+
+ $node = $this->createMock(Folder::class);
+ $node->method('getPath')->willReturn('/user1/files/folder');
+
+ $ownerFolder = $this->createMock(Folder::class);
+ $ownerFolder->method('getById')
+ ->with(123, true)
+ ->willReturn([$node]);
+
+ $this->rootFolder->method('getUserFolder')
+ ->with('user1')
+ ->willReturn($ownerFolder);
+
+ $this->userMountCache->method('getMountsForFileId')
+ ->with(123)
+ ->willReturn([$cachedMountInfo]);
+
+ $this->listener->method('getUsersSharingFile')->willReturn(['user1' => '/folder']);
+
+ $activityEvent = $this->createMock(IEvent::class);
+ $activityEvent->expects($this->once())->method('setApp')->with('systemtags')->willReturn($activityEvent);
+ $activityEvent->expects($this->once())->method('setType')->with('systemtags')->willReturn($activityEvent);
+ $activityEvent->expects($this->once())->method('setAuthor')->with('actor1')->willReturn($activityEvent);
+ $activityEvent->expects($this->once())->method('setObject')->with('files', 123)->willReturn($activityEvent);
+ $activityEvent->expects($this->exactly(2))->method('setSubject')
+ ->withConsecutive(
+ [$extensionEvent, ['actor1', '/folder', '{{{tag1|||assignable}}}']],
+ [$extensionEvent, ['actor1', '/folder', '{{{tag2|||not-assignable}}}']]
+ )
+ ->willReturn($activityEvent);
+
+ $this->activityManager->method('generateEvent')
+ ->willReturn($activityEvent);
+ $this->activityManager->expects($this->exactly(2))
+ ->method('publish')
+ ->with($activityEvent);
+
+ $event = new MapperEvent($eventType, 'files', 123, [111, 222, 333]);
+ $this->listener->mapperEvent($event);
+ }
+
+ public function prepareTagAsParameterProvider() {
+ return [
+ [new SystemTag('1', 'visibleTag', true, true, true), "{{{visibleTag|||assignable}}}"],
+ [new SystemTag('2', 'invisibleTag', false, false, false), "{{{invisibleTag|||invisible}}}"],
+ [new SystemTag('3', 'restrictTag', true, false, false), "{{{restrictTag|||not-assignable}}}"],
+ [new SystemTag('3', 'staticTag', true, true, false), "{{{staticTag|||not-editable}}}"],
+ ];
+ }
+
+ /**
+ * @dataProvider prepareTagAsParameterProvider
+ */
+ public function testPrepareTagAsParameter(SystemTag $tag, $expectedResult) {
+ $result = $this->invokePrivate($this->listener, 'prepareTagAsParameter', [$tag]);
+ $this->assertEquals($expectedResult, $result);
+ }
+}
diff --git a/lib/private/Files/Config/CachedMountInfo.php b/lib/private/Files/Config/CachedMountInfo.php
index d2b3c78f393a..cc3074150142 100644
--- a/lib/private/Files/Config/CachedMountInfo.php
+++ b/lib/private/Files/Config/CachedMountInfo.php
@@ -91,12 +91,8 @@ public function getMountPointNode() {
// TODO injection etc
Filesystem::initMountPoints($this->getUser()->getUID());
$userNode = \OC::$server->getUserFolder($this->getUser()->getUID());
- $nodes = $userNode->getParent()->getById($this->getRootId());
- if (\count($nodes) > 0) {
- return $nodes[0];
- } else {
- return null;
- }
+ $nodes = $userNode->getParent()->getById($this->getRootId(), true);
+ return $nodes[0] ?? null;
}
/**
diff --git a/lib/private/Files/Meta/MetaFileIdNode.php b/lib/private/Files/Meta/MetaFileIdNode.php
index b04d344b247e..2f8407ea9fb5 100644
--- a/lib/private/Files/Meta/MetaFileIdNode.php
+++ b/lib/private/Files/Meta/MetaFileIdNode.php
@@ -34,8 +34,8 @@
*/
class MetaFileIdNode extends AbstractFolder {
- /** @var int */
- private $fileId;
+ /** @var \OCP\Files\Node */
+ private $node;
/** @var MetaRootNode */
private $parentNode;
/** @var IRootFolder */
@@ -45,12 +45,13 @@ class MetaFileIdNode extends AbstractFolder {
* MetaFileIdNode constructor.
*
* @param MetaRootNode $parentNode
- * @param int $fileId
+ * @param IRootFolder $root
+ * @param \OCP\Files\Node $node
*/
- public function __construct(MetaRootNode $parentNode, IRootFolder $root, $fileId) {
+ public function __construct(MetaRootNode $parentNode, IRootFolder $root, \OCP\Files\Node $node) {
$this->parentNode = $parentNode;
- $this->fileId = $fileId;
$this->root = $root;
+ $this->node = $node;
}
/**
@@ -79,7 +80,7 @@ public function isMounted() {
*/
public function getDirectoryListing() {
return [
- new MetaVersionCollection($this->fileId, $this->root)
+ new MetaVersionCollection($this->root, $this->node)
];
}
@@ -90,7 +91,7 @@ public function get($path) {
$pieces = \explode('/', $path);
if ($pieces[0] === 'v') {
\array_shift($pieces);
- $node = new MetaVersionCollection($this->fileId, $this->root);
+ $node = new MetaVersionCollection($this->root, $this->node);
if (empty($pieces)) {
return $node;
}
@@ -117,7 +118,7 @@ public function getPath() {
* @inheritdoc
*/
public function getInternalPath() {
- return "/meta/{$this->fileId}";
+ return "/meta/{$this->node->getId()}";
}
/**
@@ -166,6 +167,6 @@ public function getParent() {
* @inheritdoc
*/
public function getName() {
- return "{$this->fileId}";
+ return "{$this->node->getId()}";
}
}
diff --git a/lib/private/Files/Meta/MetaRootNode.php b/lib/private/Files/Meta/MetaRootNode.php
index 6a893652c115..930180f5d714 100644
--- a/lib/private/Files/Meta/MetaRootNode.php
+++ b/lib/private/Files/Meta/MetaRootNode.php
@@ -76,13 +76,13 @@ public function get($path) {
$pieces = \explode('/', $path);
$fileId = (int)$pieces[0];
- // check if file exists
- if (empty($this->rootFolder->getById($fileId))) {
+ $nodes = $this->rootFolder->getById($fileId, true);
+ if (empty($nodes)) {
throw new NotFoundException();
}
\array_shift($pieces);
- $node = new MetaFileIdNode($this, $this->rootFolder, $fileId);
+ $node = new MetaFileIdNode($this, $this->rootFolder, $nodes[0]);
if (empty($pieces)) {
return $node;
}
@@ -92,7 +92,7 @@ public function get($path) {
/**
* @inheritdoc
*/
- public function getById($id) {
+ public function getById($id, $first = false) {
return [
$this->get("$id")
];
diff --git a/lib/private/Files/Meta/MetaVersionCollection.php b/lib/private/Files/Meta/MetaVersionCollection.php
index 5e63c7d0f43e..fd3a238efa64 100644
--- a/lib/private/Files/Meta/MetaVersionCollection.php
+++ b/lib/private/Files/Meta/MetaVersionCollection.php
@@ -1,5 +1,6 @@
* @author Thomas Müller
*
* @copyright Copyright (c) 2018, ownCloud GmbH
@@ -24,7 +25,6 @@
use OC\Files\Node\AbstractFolder;
use OCP\Files\IRootFolder;
use OCP\Files\Storage\IVersionedStorage;
-use OC\Files\View;
use OCP\Files\NotFoundException;
use OCP\Files\Storage;
@@ -36,20 +36,20 @@
*/
class MetaVersionCollection extends AbstractFolder {
- /** @var int */
- private $fileId;
/** @var IRootFolder */
private $root;
+ /** @var \OCP\Files\Node */
+ private $node;
/**
* MetaVersionCollection constructor.
*
- * @param int $fileId
* @param IRootFolder $root
+ * @param \OCP\Files\Node $node
*/
- public function __construct($fileId, IRootFolder $root) {
- $this->fileId = $fileId;
+ public function __construct(IRootFolder $root, \OCP\Files\Node $node) {
$this->root = $root;
+ $this->node = $node;
}
/**
@@ -66,22 +66,19 @@ public function isShared() {
return false;
}
- /**
- * @inheritdoc
- */
public function getDirectoryListing() {
- $view = new View();
- $path = $view->getPath($this->fileId, false);
- /** @var Storage $storage */
- list($storage, $internalPath) = $view->resolvePath($path);
+ $node = $this->node;
+ $storage = $node->getStorage();
+ $internalPath = $node->getInternalPath();
+
if (!$storage->instanceOfStorage(IVersionedStorage::class)) {
return [];
}
/** @var IVersionedStorage | Storage $storage */
$versions = $storage->getVersions($internalPath);
- return \array_values(\array_map(function ($version) use ($storage, $internalPath, $view, $path) {
+ return \array_values(\array_map(function ($version) use ($storage, $node, $internalPath) {
if (!isset($version['mimetype'])) {
- $version['mimetype'] = $view->getMimeType($path);
+ $version['mimetype'] = $node->getMimetype();
}
return new MetaFileVersionNode($this, $this->root, $version, $storage, $internalPath);
@@ -97,10 +94,10 @@ public function get($path) {
throw new NotFoundException();
}
$versionId = $pieces[0];
- $view = new View();
- $path = $view->getPath($this->fileId);
- /** @var Storage $storage */
- list($storage, $internalPath) = $view->resolvePath($path);
+
+ $storage = $this->node->getStorage();
+ $internalPath = $this->node->getInternalPath();
+
if (!$storage->instanceOfStorage(IVersionedStorage::class)) {
throw new NotFoundException();
}
@@ -110,7 +107,7 @@ public function get($path) {
throw new NotFoundException();
}
if (!isset($version['mimetype'])) {
- $version['mimetype'] = $view->getMimeType($path);
+ $version['mimetype'] = $this->node->getMimetype();
}
return new MetaFileVersionNode($this, $this->root, $version, $storage, $internalPath);
}
@@ -119,7 +116,7 @@ public function get($path) {
* @inheritdoc
*/
public function getId() {
- return $this->fileId;
+ return $this->node->getId();
}
public function getName() {
@@ -127,6 +124,6 @@ public function getName() {
}
public function getPath() {
- return "/meta/{$this->fileId}/v";
+ return "/meta/{$this->getId()}/v";
}
}
diff --git a/lib/private/Files/Node/AbstractFolder.php b/lib/private/Files/Node/AbstractFolder.php
index fb6c3feea3a4..d652c026a2f6 100644
--- a/lib/private/Files/Node/AbstractFolder.php
+++ b/lib/private/Files/Node/AbstractFolder.php
@@ -112,7 +112,7 @@ public function searchByTag($tag, $userId) {
/**
* @inheritdoc
*/
- public function getById($id) {
+ public function getById($id, $first = false) {
throw new NotPermittedException();
}
diff --git a/lib/private/Files/Node/Folder.php b/lib/private/Files/Node/Folder.php
index adb9e56a1b4c..ca559a1f7e86 100644
--- a/lib/private/Files/Node/Folder.php
+++ b/lib/private/Files/Node/Folder.php
@@ -269,9 +269,11 @@ private function searchCommon($method, $args) {
/**
* @param int $id
+ * @param boolean $first only return the first node that is found
* @return \OC\Files\Node\Node[]
+ * @throws NotFoundException
*/
- public function getById($id) {
+ public function getById($id, $first = false) {
$mounts = $this->root->getMountsIn($this->path);
$mounts[] = $this->root->getMount($this->path);
// reverse the array so we start with the storage this view is in
@@ -290,6 +292,9 @@ public function getById($id) {
$fullPath = $mount->getMountPoint() . $internalPath;
if (($path = $this->getRelativePath($fullPath)) !== null) {
$nodes[] = $this->get($path);
+ if ($first) {
+ break;
+ }
}
}
}
diff --git a/lib/private/Files/Node/LazyRoot.php b/lib/private/Files/Node/LazyRoot.php
index 9e43f7e09b47..c9bf01f71525 100644
--- a/lib/private/Files/Node/LazyRoot.php
+++ b/lib/private/Files/Node/LazyRoot.php
@@ -417,7 +417,7 @@ public function searchByTag($tag, $userId) {
/**
* @inheritDoc
*/
- public function getById($id) {
+ public function getById($id, $first = false) {
return $this->__call(__FUNCTION__, \func_get_args());
}
diff --git a/lib/private/Files/Node/NonExistingFolder.php b/lib/private/Files/Node/NonExistingFolder.php
index c3634403fea6..032e5764312c 100644
--- a/lib/private/Files/Node/NonExistingFolder.php
+++ b/lib/private/Files/Node/NonExistingFolder.php
@@ -154,7 +154,7 @@ public function searchByTag($tag, $userId) {
throw new NotFoundException();
}
- public function getById($id) {
+ public function getById($id, $first = false) {
throw new NotFoundException();
}
diff --git a/lib/private/Files/Storage/Wrapper/Jail.php b/lib/private/Files/Storage/Wrapper/Jail.php
index f533cd8330f1..24d12774d8a0 100644
--- a/lib/private/Files/Storage/Wrapper/Jail.php
+++ b/lib/private/Files/Storage/Wrapper/Jail.php
@@ -26,6 +26,7 @@
use OC\Files\Cache\Wrapper\CacheJail;
use OCP\Files\Storage\IStorage;
+use OCP\Files\Storage\IVersionedStorage;
use OCP\Lock\ILockingProvider;
/**
@@ -33,7 +34,8 @@
*
* This restricts access to a subfolder of the wrapped storage with the subfolder becoming the root folder new storage
*/
-class Jail extends Wrapper {
+class Jail extends Wrapper /* implements IVersionedStorage */
+{
/**
* @var string
*/
@@ -497,4 +499,62 @@ public function moveFromStorage(\OCP\Files\Storage $sourceStorage, $sourceIntern
}
return $this->getWrapperStorage()->moveFromStorage($sourceStorage, $sourceInternalPath, $this->getSourcePath($targetInternalPath));
}
+
+ /**
+ * Get the content of a given version of a given file as stream resource
+ *
+ * @param string $internalPath
+ * @param string $versionId
+ * @return resource
+ * @since 10.0.9
+ */
+ public function getContentOfVersion($internalPath, $versionId) {
+ return $this->getWrapperStorage()->getContentOfVersion($this->getSourcePath($internalPath), $versionId);
+ }
+
+ /**
+ * Restore the given version of a given file
+ *
+ * @param string $internalPath
+ * @param string $versionId
+ * @return boolean
+ * @since 10.0.9
+ */
+ public function restoreVersion($internalPath, $versionId) {
+ return $this->getWrapperStorage()->restoreVersion($this->getSourcePath($internalPath), $versionId);
+ }
+
+ /**
+ * Tells the storage to explicitly create a version of a given file
+ *
+ * @param string $internalPath
+ * @return bool
+ * @since 10.0.9
+ */
+ public function saveVersion($internalPath) {
+ return $this->getWrapperStorage()->saveVersion($this->getSourcePath($internalPath));
+ }
+
+ /**
+ * List all versions for the given file
+ *
+ * @param string $internalPath
+ * @return array
+ * @since 10.0.9
+ */
+ public function getVersions($internalPath) {
+ return $this->getWrapperStorage()->getVersions($this->getSourcePath($internalPath));
+ }
+
+ /**
+ * Get one explicit version for the given file
+ *
+ * @param string $internalPath
+ * @param string $versionId
+ * @return array
+ * @since 10.0.9
+ */
+ public function getVersion($internalPath, $versionId) {
+ return $this->getWrapperStorage()->getVersion($this->getSourcePath($internalPath), $versionId);
+ }
}
diff --git a/lib/private/Share20/Share.php b/lib/private/Share20/Share.php
index 6f774f08f653..4fa7e4ccfe93 100644
--- a/lib/private/Share20/Share.php
+++ b/lib/private/Share20/Share.php
@@ -164,7 +164,7 @@ public function getNode() {
$userFolder = $this->rootFolder->getUserFolder($this->sharedBy);
}
- $nodes = $userFolder->getById($this->fileId);
+ $nodes = $userFolder->getById($this->fileId, true);
if (empty($nodes)) {
throw new NotFoundException();
}
diff --git a/lib/public/Files/Folder.php b/lib/public/Files/Folder.php
index 2dfa83a409ed..55f5211bc22d 100644
--- a/lib/public/Files/Folder.php
+++ b/lib/public/Files/Folder.php
@@ -145,10 +145,11 @@ public function searchByTag($tag, $userId);
* get a file or folder inside the folder by it's internal id
*
* @param int $id
+ * @param boolean $first only return the first node that is found
* @return \OCP\Files\Node[]
* @since 6.0.0
*/
- public function getById($id);
+ public function getById($id, $first = false);
/**
* Get the amount of free space inside the folder
diff --git a/tests/lib/Files/MetaFilesTest.php b/tests/lib/Files/MetaFilesTest.php
index 28bac72710ff..9db1638234dd 100644
--- a/tests/lib/Files/MetaFilesTest.php
+++ b/tests/lib/Files/MetaFilesTest.php
@@ -43,11 +43,36 @@
class MetaFilesTest extends TestCase {
use UserTrait;
+ /**
+ * @var string
+ */
+ private $userId;
+
+ protected function setUp() {
+ parent::setUp();
+
+ // workaround: re-setup versions hooks
+ Hooks::connectHooks();
+
+ $this->userId = $this->getUniqueID('meta-data-user-');
+ $this->createUser($this->userId);
+ $this->loginAsUser($this->userId);
+ }
+
protected function tearDown() {
self::logout();
parent::tearDown();
}
+ private function createFile() {
+ // create file
+ $file = $this->getUniqueID('file') . '.txt';
+ $fileName = "{$this->userId}/files/$file";
+ $view = new View();
+ $view->file_put_contents($fileName, '1234');
+ return $view->getFileInfo($fileName);
+ }
+
/**
* @throws \Exception
* @throws \OCP\Files\ForbiddenException
@@ -55,17 +80,11 @@ protected function tearDown() {
* @throws \OCP\Files\NotPermittedException
*/
public function testMetaInNodeAPI() {
- // workaround: re-setup versions hooks
- Hooks::connectHooks();
-
- // create user
- $userId = 'meta-data-user';
- $this->createUser($userId);
- $this->loginAsUser($userId);
+ $userId = $this->userId;
// create file
$file = $this->getUniqueID('file') . '.txt';
- $fileName = "$userId/files/$file";
+ $fileName = "{$this->userId}/files/$file";
$view = new View();
$view->file_put_contents($fileName, '1234');
$info = $view->getFileInfo($fileName);
@@ -124,4 +143,25 @@ public function testMetaInNodeAPI() {
$metaNodeOfFile->copy($fileName);
$this->assertEquals('1234', $target->getContent());
}
+
+ public function testMetaRootGetById() {
+ $info = $this->createFile();
+
+ $metaRoot = \OC::$server->getRootFolder();
+ $info2 = $metaRoot->getById($info->getId());
+
+ $this->assertEquals($info->getId(), $info2[0]->getId());
+ $this->assertEquals($info->getPath(), $info2[0]->getPath());
+ }
+
+ /**
+ * @expectedException OCP\Files\NotFoundException
+ */
+ public function testMetaRootGetNotFound() {
+ $info = $this->createFile();
+
+ $metaRoot = \OC::$server->getRootFolder();
+ // get non-existing
+ $metaRoot->get($info->getId() + 100);
+ }
}
diff --git a/tests/lib/Files/MetaVersionCollectionTest.php b/tests/lib/Files/MetaVersionCollectionTest.php
new file mode 100644
index 000000000000..0659d6057361
--- /dev/null
+++ b/tests/lib/Files/MetaVersionCollectionTest.php
@@ -0,0 +1,166 @@
+
+ *
+ * @copyright Copyright (c) 2018, ownCloud GmbH
+ * @license AGPL-3.0
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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, version 3,
+ * along with this program. If not, see
+ *
+ */
+
+namespace Test\Files;
+
+use Test\TestCase;
+use OCP\Files\Node;
+use OC\Files\Meta\MetaVersionCollection;
+use OCP\Files\IRootFolder;
+use OCP\Files\Storage\IStorage;
+use OCA\Files_Sharing\External\Storage;
+use OCP\Files\Storage\IVersionedStorage;
+use OC\Files\Meta\MetaFileVersionNode;
+
+/**
+ * Class MetaFilesTest
+ *
+ * @package Test\Files
+ */
+class MetaVersionCollectionTest extends TestCase {
+
+ /**
+ * @var Node
+ */
+ private $node;
+
+ /**
+ * @var IRootFolder
+ */
+ private $rootFolder;
+
+ /**
+ * @var MetaVersionCollection
+ */
+ private $collection;
+
+ /**
+ * @var IStorage|IVersionedStorage
+ */
+ private $storage;
+
+ protected function setUp() {
+ parent::setUp();
+
+ $this->rootFolder = $this->createMock(IRootFolder::class);
+ $this->node = $this->createMock(Node::class);
+ $this->storage = $this->createMock([IStorage::class, IVersionedStorage::class]);
+ $this->node->method('getStorage')->willReturn($this->storage);
+ $this->collection = new MetaVersionCollection($this->rootFolder, $this->node);
+ }
+
+ protected function tearDown() {
+ parent::tearDown();
+ }
+
+ public function testGetDirectoryListing() {
+ $this->node->method('getInternalPath')->willReturn('/abc');
+ $this->node->method('getMimetype')->willReturn('application/json');
+
+ $this->storage->method('instanceOfStorage')
+ ->with(IVersionedStorage::class)
+ ->willReturn(true);
+
+ $this->storage->expects($this->once())
+ ->method('getVersions')
+ ->with('/abc')
+ ->willReturn([
+ ['version' => '1014', 'timestamp' => 12345678],
+ ['version' => '1015', 'mimetype' => 'text/plain', 'timestamp' => 12345679],
+ ]);
+
+ $children = $this->collection->getDirectoryListing();
+
+ $this->assertCount(2, $children);
+ $this->assertInstanceOf(MetaFileVersionNode::class, $children[0]);
+ $this->assertEquals('1014', $children[0]->getName());
+ $this->assertEquals('application/json', $children[0]->getMimetype());
+ $this->assertEquals(12345678, $children[0]->getMtime());
+ $this->assertInstanceOf(MetaFileVersionNode::class, $children[1]);
+ $this->assertEquals('1015', $children[1]->getName());
+ $this->assertEquals('text/plain', $children[1]->getMimetype());
+ $this->assertEquals(12345679, $children[1]->getMtime());
+ }
+
+ public function testGetDirectoryListingNonVersionedStorage() {
+ $this->node->method('getInternalPath')->willReturn('/abc');
+ $this->node->method('getMimetype')->willReturn('application/json');
+
+ $this->storage->method('instanceOfStorage')
+ ->with(IVersionedStorage::class)
+ ->willReturn(false);
+
+ $this->storage->expects($this->never())
+ ->method('getVersions');
+
+ $children = $this->collection->getDirectoryListing();
+
+ $this->assertCount(0, $children);
+ }
+
+ public function testGet() {
+ $this->node->method('getInternalPath')->willReturn('/abc');
+ $this->node->method('getMimetype')->willReturn('application/json');
+
+ $this->storage->method('instanceOfStorage')
+ ->with(IVersionedStorage::class)
+ ->willReturn(true);
+
+ $this->storage->expects($this->once())
+ ->method('getVersion')
+ ->with('/abc', '1014')
+ ->willReturn(['version' => '1014', 'timestamp' => 12345678]);
+
+ $result = $this->collection->get('1014');
+
+ $this->assertInstanceOf(MetaFileVersionNode::class, $result);
+ $this->assertEquals('1014', $result->getName());
+ $this->assertEquals('application/json', $result->getMimetype());
+ $this->assertEquals(12345678, $result->getMtime());
+ }
+
+ /**
+ * @expectedException OCP\Files\NotFoundException
+ */
+ public function testGetNonVersionedStorageFails() {
+ $this->node->method('getInternalPath')->willReturn('/abc');
+ $this->node->method('getMimetype')->willReturn('application/json');
+
+ $this->storage->method('instanceOfStorage')
+ ->with(IVersionedStorage::class)
+ ->willReturn(false);
+
+ $this->storage->expects($this->never())
+ ->method('getVersion');
+
+ $this->collection->get('1014');
+ }
+
+ /**
+ * @expectedException OCP\Files\NotFoundException
+ */
+ public function testGetSubEntryFails() {
+ $this->storage->expects($this->never())
+ ->method('instanceOfStorage');
+
+ $this->collection->get('1014/1');
+ }
+}
diff --git a/tests/lib/Files/Storage/Wrapper/JailTest.php b/tests/lib/Files/Storage/Wrapper/JailTest.php
index 122953e9e54d..1b8f708155a5 100644
--- a/tests/lib/Files/Storage/Wrapper/JailTest.php
+++ b/tests/lib/Files/Storage/Wrapper/JailTest.php
@@ -8,6 +8,9 @@
namespace Test\Files\Storage\Wrapper;
+use OCP\Files\Storage\IStorage;
+use OCP\Files\Storage\IVersionedStorage;
+
class JailTest extends \Test\Files\Storage\Storage {
/**
@@ -48,4 +51,37 @@ public function testFilePutContentsRooted() {
$this->instance->file_put_contents('bar', 'asd');
$this->assertEquals('asd', $this->sourceStorage->file_get_contents('foo/bar'));
}
+
+ public function providesVersionMethods() {
+ return [
+ ['getContentOfVersion', 1014],
+ ['restoreVersion', 1014],
+ ['saveVersion'],
+ ['getVersions'],
+ ['getVersion', 1014],
+ ];
+ }
+
+ /**
+ * @dataProvider providesVersionMethods
+ */
+ public function testCallsSourceVersionMethods($method, $extraArg = null) {
+ $sourceStorage = $this->createMock([IStorage::class, IVersionedStorage::class]);
+ $instance = new \OC\Files\Storage\Wrapper\Jail([
+ 'storage' => $sourceStorage,
+ 'root' => 'foo'
+ ]);
+
+ $matcher = $sourceStorage->expects($this->once())
+ ->method($method);
+ // FIXME: normalize path...
+ if ($extraArg !== null) {
+ $matcher = $matcher->with('foo//bar', $extraArg);
+ } else {
+ $matcher = $matcher->with('foo//bar');
+ }
+ $matcher->willReturn('returnValue');
+
+ $this->assertEquals('returnValue', $instance->$method('/bar', $extraArg));
+ }
}