diff --git a/config/config.sample.php b/config/config.sample.php index 0a81543589..4b1ab2fce5 100755 --- a/config/config.sample.php +++ b/config/config.sample.php @@ -291,6 +291,9 @@ $CONFIG = array( */ 'cache_path' => '', +/* EXPERIMENTAL: option whether to include external storage in quota calculation, defaults to false */ +'quota_include_external_storage' => false, + /* * specifies how often the filesystem is checked for changes made outside owncloud * 0 -> never check the filesystem for outside changes, provides a performance increase when it's certain that no changes are made directly to the filesystem @@ -301,5 +304,4 @@ $CONFIG = array( /* If true, prevent owncloud from changing the cache due to changes in the filesystem for all storage */ 'filesystem_cache_readonly' => false, - ); diff --git a/lib/private/files/view.php b/lib/private/files/view.php index 71c4980db2..09b100d7cf 100644 --- a/lib/private/files/view.php +++ b/lib/private/files/view.php @@ -807,7 +807,8 @@ class View { * get the filesystem info * * @param string $path - * @param boolean $includeMountPoints whether to add mountpoint sizes, + * @param boolean|string $includeMountPoints true to add mountpoint sizes, + * 'ext' to add only ext storage mount point sizes. Defaults to true. * defaults to true * @return \OC\Files\FileInfo|false */ @@ -845,10 +846,15 @@ class View { if ($data and isset($data['fileid'])) { if ($includeMountPoints and $data['mimetype'] === 'httpd/unix-directory') { //add the sizes of other mountpoints to the folder + $extOnly = ($includeMountPoints === 'ext'); $mountPoints = Filesystem::getMountPoints($path); foreach ($mountPoints as $mountPoint) { $subStorage = Filesystem::getStorage($mountPoint); if ($subStorage) { + // exclude shared storage ? + if ($extOnly && $subStorage instanceof \OC\Files\Storage\Shared) { + continue; + } $subCache = $subStorage->getCache(''); $rootEntry = $subCache->get(''); $data['size'] += isset($rootEntry['size']) ? $rootEntry['size'] : 0; diff --git a/lib/private/helper.php b/lib/private/helper.php index 9ac07bbd3b..a054fc485a 100644 --- a/lib/private/helper.php +++ b/lib/private/helper.php @@ -936,6 +936,8 @@ class OC_Helper { */ public static function getStorageInfo($path, $rootInfo = null) { // return storage info without adding mount points + $includeExtStorage = \OC_Config::getValue('quota_include_external_storage', false); + if (is_null($rootInfo)) { $rootInfo = \OC\Files\Filesystem::getFileInfo($path, false); } @@ -944,8 +946,20 @@ class OC_Helper { $used = 0; } $quota = 0; - // TODO: need a better way to get total space from storage $storage = $rootInfo->getStorage(); + if ($includeExtStorage && $storage->instanceOfStorage('\OC\Files\Storage\Shared')) { + $includeExtStorage = false; + } + if ($includeExtStorage) { + $quota = OC_Util::getUserQuota(\OCP\User::getUser()); + if ($quota !== \OC\Files\SPACE_UNLIMITED) { + // always get free space / total space from root + mount points + $path = ''; + return self::getGlobalStorageInfo(); + } + } + + // TODO: need a better way to get total space from storage if ($storage->instanceOfStorage('\OC\Files\Storage\Wrapper\Quota')) { $quota = $storage->getQuota(); } @@ -967,4 +981,35 @@ class OC_Helper { return array('free' => $free, 'used' => $used, 'total' => $total, 'relative' => $relative); } + + /** + * Get storage info including all mount points and quota + * + * @return array + */ + private static function getGlobalStorageInfo() { + $quota = OC_Util::getUserQuota(\OCP\User::getUser()); + + $rootInfo = \OC\Files\Filesystem::getFileInfo('', 'ext'); + $used = $rootInfo['size']; + if ($used < 0) { + $used = 0; + } + + $total = $quota; + $free = $quota - $used; + + if ($total > 0) { + if ($quota > 0 && $total > $quota) { + $total = $quota; + } + // prevent division by zero or error codes (negative values) + $relative = round(($used / $total) * 10000) / 100; + } else { + $relative = 0; + } + + return array('free' => $free, 'used' => $used, 'total' => $total, 'relative' => $relative); + + } } diff --git a/tests/lib/helperstorage.php b/tests/lib/helperstorage.php index 010a54e3bb..4fdd9dd6b9 100644 --- a/tests/lib/helperstorage.php +++ b/tests/lib/helperstorage.php @@ -15,35 +15,58 @@ class Test_Helper_Storage extends PHPUnit_Framework_TestCase { public function setUp() { $this->user = 'user_' . uniqid(); - \OC\Files\Filesystem::tearDown(); - \OC\Files\Filesystem::init($this->user, '/' . $this->user . '/files'); + \OC_User::createUser($this->user, $this->user); + \OC\Files\Filesystem::tearDown(); + \OC_User::setUserId($this->user); + \OC\Files\Filesystem::init($this->user, '/' . $this->user . '/files'); + \OC\Files\Filesystem::clearMounts(); + + $this->storageMock = null; + } + + public function tearDown() { + $this->user = null; + + if ($this->storageMock) { + $this->storageMock->getCache()->clear(); + $this->storageMock = null; + } + \OC\Files\Filesystem::tearDown(); + + \OC_User::setUserId(''); + \OC_User::deleteUser($this->user); + \OC_Preferences::deleteUser($this->user); + } + + /** + * Returns a storage mock that returns the given value as + * free space + * + * @param int $freeSpace free space value + * @return \OC\Files\Storage\Storage + */ + private function getStorageMock($freeSpace = 12) { $this->storageMock = $this->getMock( '\OC\Files\Storage\Temporary', array('free_space'), array('') ); - \OC\Files\Filesystem::clearMounts(); $this->storageMock->expects($this->once()) ->method('free_space') ->will($this->returnValue(12)); - } - - public function tearDown() { - $this->user = null; - - $this->storageMock->getCache()->clear(); - \OC\Files\Filesystem::tearDown(); + return $this->storageMock; } /** * Test getting the storage info */ function testGetStorageInfo() { - \OC\Files\Filesystem::mount($this->storageMock, array(), '/' . $this->user . '/files'); - $this->storageMock->file_put_contents('test.txt', '01234'); + $homeStorage = $this->getStorageMock(12); + \OC\Files\Filesystem::mount($homeStorage, array(), '/' . $this->user . '/files'); + $homeStorage->file_put_contents('test.txt', '01234'); $storageInfo = \OC_Helper::getStorageInfo(''); $this->assertEquals(12, $storageInfo['free']); @@ -51,18 +74,96 @@ class Test_Helper_Storage extends PHPUnit_Framework_TestCase { $this->assertEquals(17, $storageInfo['total']); } + /** + * Test getting the storage info, ignoring extra mount points + */ + function testGetStorageInfoExcludingExtStorage() { + $homeStorage = $this->getStorageMock(12); + \OC\Files\Filesystem::mount($homeStorage, array(), '/' . $this->user . '/files'); + $homeStorage->file_put_contents('test.txt', '01234'); + + $extStorage = new \OC\Files\Storage\Temporary(array()); + $extStorage->file_put_contents('extfile.txt', 'abcdefghijklmnopq'); + $extStorage->getScanner()->scan(''); // update root size + + \OC\Files\Filesystem::mount($extStorage, array(), '/' . $this->user . '/files/ext'); + + $storageInfo = \OC_Helper::getStorageInfo(''); + $this->assertEquals(12, $storageInfo['free']); + $this->assertEquals(5, $storageInfo['used']); + $this->assertEquals(17, $storageInfo['total']); + } + + /** + * Test getting the storage info, including extra mount points + */ + function testGetStorageInfoIncludingExtStorage() { + $homeStorage = new \OC\Files\Storage\Temporary(array()); + \OC\Files\Filesystem::mount($homeStorage, array(), '/' . $this->user . '/files'); + $homeStorage->file_put_contents('test.txt', '01234'); + + $extStorage = new \OC\Files\Storage\Temporary(array()); + $extStorage->file_put_contents('extfile.txt', 'abcdefghijklmnopq'); + $extStorage->getScanner()->scan(''); // update root size + + \OC\Files\Filesystem::mount($extStorage, array(), '/' . $this->user . '/files/ext'); + + $oldConfig = \OC_Config::getValue('quota_include_external_storage', false); + \OC_Config::setValue('quota_include_external_storage', 'true'); + + $config = \OC::$server->getConfig(); + $userQuota = $config->setUserValue($this->user, 'files', 'quota', '25'); + + $storageInfo = \OC_Helper::getStorageInfo(''); + $this->assertEquals(3, $storageInfo['free']); + $this->assertEquals(22, $storageInfo['used']); + $this->assertEquals(25, $storageInfo['total']); + + \OC_Config::setValue('quota_include_external_storage', $oldConfig); + $userQuota = $config->setUserValue($this->user, 'files', 'quota', 'default'); + } + + /** + * Test getting the storage info excluding extra mount points + * when user has no quota set, even when quota ext storage option + * was set + */ + function testGetStorageInfoIncludingExtStorageWithNoUserQuota() { + $homeStorage = $this->getStorageMock(12); + \OC\Files\Filesystem::mount($homeStorage, array(), '/' . $this->user . '/files'); + $homeStorage->file_put_contents('test.txt', '01234'); + + $extStorage = new \OC\Files\Storage\Temporary(array()); + $extStorage->file_put_contents('extfile.txt', 'abcdefghijklmnopq'); + $extStorage->getScanner()->scan(''); // update root size + + \OC\Files\Filesystem::mount($extStorage, array(), '/' . $this->user . '/files/ext'); + + $oldConfig = \OC_Config::getValue('quota_include_external_storage', false); + \OC_Config::setValue('quota_include_external_storage', 'true'); + + $storageInfo = \OC_Helper::getStorageInfo(''); + $this->assertEquals(12, $storageInfo['free']); + $this->assertEquals(5, $storageInfo['used']); + $this->assertEquals(17, $storageInfo['total']); + + \OC_Config::setValue('quota_include_external_storage', $oldConfig); + } + + /** * Test getting the storage info with quota enabled */ function testGetStorageInfoWithQuota() { - $this->storageMock->file_put_contents('test.txt', '01234'); - $this->storageMock = new \OC\Files\Storage\Wrapper\Quota( + $homeStorage = $this->getStorageMock(12); + $homeStorage->file_put_contents('test.txt', '01234'); + $homeStorage = new \OC\Files\Storage\Wrapper\Quota( array( - 'storage' => $this->storageMock, + 'storage' => $homeStorage, 'quota' => 7 ) ); - \OC\Files\Filesystem::mount($this->storageMock, array(), '/' . $this->user . '/files'); + \OC\Files\Filesystem::mount($homeStorage, array(), '/' . $this->user . '/files'); $storageInfo = \OC_Helper::getStorageInfo(''); $this->assertEquals(2, $storageInfo['free']); @@ -74,14 +175,15 @@ class Test_Helper_Storage extends PHPUnit_Framework_TestCase { * Test getting the storage info when data exceeds quota */ function testGetStorageInfoWhenSizeExceedsQuota() { - $this->storageMock->file_put_contents('test.txt', '0123456789'); - $this->storageMock = new \OC\Files\Storage\Wrapper\Quota( + $homeStorage = $this->getStorageMock(12); + $homeStorage->file_put_contents('test.txt', '0123456789'); + $homeStorage = new \OC\Files\Storage\Wrapper\Quota( array( - 'storage' => $this->storageMock, + 'storage' => $homeStorage, 'quota' => 7 ) ); - \OC\Files\Filesystem::mount($this->storageMock, array(), '/' . $this->user . '/files'); + \OC\Files\Filesystem::mount($homeStorage, array(), '/' . $this->user . '/files'); $storageInfo = \OC_Helper::getStorageInfo(''); $this->assertEquals(0, $storageInfo['free']); @@ -95,14 +197,15 @@ class Test_Helper_Storage extends PHPUnit_Framework_TestCase { * free storage space is less than the quota */ function testGetStorageInfoWhenFreeSpaceLessThanQuota() { - $this->storageMock->file_put_contents('test.txt', '01234'); - $this->storageMock = new \OC\Files\Storage\Wrapper\Quota( + $homeStorage = $this->getStorageMock(12); + $homeStorage->file_put_contents('test.txt', '01234'); + $homeStorage = new \OC\Files\Storage\Wrapper\Quota( array( - 'storage' => $this->storageMock, + 'storage' => $homeStorage, 'quota' => 18 ) ); - \OC\Files\Filesystem::mount($this->storageMock, array(), '/' . $this->user . '/files'); + \OC\Files\Filesystem::mount($homeStorage, array(), '/' . $this->user . '/files'); $storageInfo = \OC_Helper::getStorageInfo(''); $this->assertEquals(12, $storageInfo['free']);