diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php index 2fa4df4d9e..0ff46de07d 100644 --- a/lib/composer/composer/autoload_classmap.php +++ b/lib/composer/composer/autoload_classmap.php @@ -107,6 +107,7 @@ return array( 'OCP\\Files\\FileNameTooLongException' => $baseDir . '/lib/public/Files/FileNameTooLongException.php', 'OCP\\Files\\Folder' => $baseDir . '/lib/public/Files/Folder.php', 'OCP\\Files\\ForbiddenException' => $baseDir . '/lib/public/Files/ForbiddenException.php', + 'OCP\\Files\\IAppData' => $baseDir . '/lib/public/Files/IAppData.php', 'OCP\\Files\\IHomeStorage' => $baseDir . '/lib/public/Files/IHomeStorage.php', 'OCP\\Files\\IMimeTypeDetector' => $baseDir . '/lib/public/Files/IMimeTypeDetector.php', 'OCP\\Files\\IMimeTypeLoader' => $baseDir . '/lib/public/Files/IMimeTypeLoader.php', @@ -123,6 +124,9 @@ return array( 'OCP\\Files\\NotPermittedException' => $baseDir . '/lib/public/Files/NotPermittedException.php', 'OCP\\Files\\ObjectStore\\IObjectStore' => $baseDir . '/lib/public/Files/ObjectStore/IObjectStore.php', 'OCP\\Files\\ReservedWordException' => $baseDir . '/lib/public/Files/ReservedWordException.php', + 'OCP\\Files\\SimpleFS\\ISimpleFile' => $baseDir . '/lib/public/Files/SimpleFS/ISimpleFile.php', + 'OCP\\Files\\SimpleFS\\ISimpleFolder' => $baseDir . '/lib/public/Files/SimpleFS/ISimpleFolder.php', + 'OCP\\Files\\SimpleFS\\ISimpleRoot' => $baseDir . '/lib/public/Files/SimpleFS/ISimpleRoot.php', 'OCP\\Files\\Storage' => $baseDir . '/lib/public/Files/Storage.php', 'OCP\\Files\\StorageAuthException' => $baseDir . '/lib/public/Files/StorageAuthException.php', 'OCP\\Files\\StorageBadConfigException' => $baseDir . '/lib/public/Files/StorageBadConfigException.php', @@ -459,6 +463,8 @@ return array( 'OC\\Encryption\\Manager' => $baseDir . '/lib/private/Encryption/Manager.php', 'OC\\Encryption\\Update' => $baseDir . '/lib/private/Encryption/Update.php', 'OC\\Encryption\\Util' => $baseDir . '/lib/private/Encryption/Util.php', + 'OC\\Files\\AppData\\AppData' => $baseDir . '/lib/private/Files/AppData/AppData.php', + 'OC\\Files\\AppData\\Factory' => $baseDir . '/lib/private/Files/AppData/Factory.php', 'OC\\Files\\Cache\\Cache' => $baseDir . '/lib/private/Files/Cache/Cache.php', 'OC\\Files\\Cache\\CacheEntry' => $baseDir . '/lib/private/Files/Cache/CacheEntry.php', 'OC\\Files\\Cache\\FailedCache' => $baseDir . '/lib/private/Files/Cache/FailedCache.php', @@ -500,6 +506,8 @@ return array( 'OC\\Files\\ObjectStore\\NoopScanner' => $baseDir . '/lib/private/Files/ObjectStore/NoopScanner.php', 'OC\\Files\\ObjectStore\\ObjectStoreStorage' => $baseDir . '/lib/private/Files/ObjectStore/ObjectStoreStorage.php', 'OC\\Files\\ObjectStore\\Swift' => $baseDir . '/lib/private/Files/ObjectStore/Swift.php', + 'OC\\Files\\SimpleFS\\SimpleFile' => $baseDir . '/lib/private/Files/SimpleFS/SimpleFile.php', + 'OC\\Files\\SimpleFS\\SimpleFolder' => $baseDir . '/lib/private/Files/SimpleFS/SimpleFolder.php', 'OC\\Files\\Storage\\Common' => $baseDir . '/lib/private/Files/Storage/Common.php', 'OC\\Files\\Storage\\CommonTest' => $baseDir . '/lib/private/Files/Storage/CommonTest.php', 'OC\\Files\\Storage\\DAV' => $baseDir . '/lib/private/Files/Storage/DAV.php', @@ -638,6 +646,8 @@ return array( 'OC\\Repair\\FillETags' => $baseDir . '/lib/private/Repair/FillETags.php', 'OC\\Repair\\InnoDB' => $baseDir . '/lib/private/Repair/InnoDB.php', 'OC\\Repair\\MoveUpdaterStepFile' => $baseDir . '/lib/private/Repair/MoveUpdaterStepFile.php', + 'OC\\Repair\\NC11\\MoveAvatars' => $baseDir . '/lib/private/Repair/NC11/MoveAvatars.php', + 'OC\\Repair\\NC11\\MoveAvatarsBackgroundJob' => $baseDir . '/lib/private/Repair/NC11/MoveAvatarBackgroundJob.php', 'OC\\Repair\\OldGroupMembershipShares' => $baseDir . '/lib/private/Repair/OldGroupMembershipShares.php', 'OC\\Repair\\Preview' => $baseDir . '/lib/private/Repair/Preview.php', 'OC\\Repair\\RemoveGetETagEntries' => $baseDir . '/lib/private/Repair/RemoveGetETagEntries.php', diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php index ad493bfb04..24058a22ed 100644 --- a/lib/composer/composer/autoload_static.php +++ b/lib/composer/composer/autoload_static.php @@ -137,6 +137,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OCP\\Files\\FileNameTooLongException' => __DIR__ . '/../../..' . '/lib/public/Files/FileNameTooLongException.php', 'OCP\\Files\\Folder' => __DIR__ . '/../../..' . '/lib/public/Files/Folder.php', 'OCP\\Files\\ForbiddenException' => __DIR__ . '/../../..' . '/lib/public/Files/ForbiddenException.php', + 'OCP\\Files\\IAppData' => __DIR__ . '/../../..' . '/lib/public/Files/IAppData.php', 'OCP\\Files\\IHomeStorage' => __DIR__ . '/../../..' . '/lib/public/Files/IHomeStorage.php', 'OCP\\Files\\IMimeTypeDetector' => __DIR__ . '/../../..' . '/lib/public/Files/IMimeTypeDetector.php', 'OCP\\Files\\IMimeTypeLoader' => __DIR__ . '/../../..' . '/lib/public/Files/IMimeTypeLoader.php', @@ -153,6 +154,9 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OCP\\Files\\NotPermittedException' => __DIR__ . '/../../..' . '/lib/public/Files/NotPermittedException.php', 'OCP\\Files\\ObjectStore\\IObjectStore' => __DIR__ . '/../../..' . '/lib/public/Files/ObjectStore/IObjectStore.php', 'OCP\\Files\\ReservedWordException' => __DIR__ . '/../../..' . '/lib/public/Files/ReservedWordException.php', + 'OCP\\Files\\SimpleFS\\ISimpleFile' => __DIR__ . '/../../..' . '/lib/public/Files/SimpleFS/ISimpleFile.php', + 'OCP\\Files\\SimpleFS\\ISimpleFolder' => __DIR__ . '/../../..' . '/lib/public/Files/SimpleFS/ISimpleFolder.php', + 'OCP\\Files\\SimpleFS\\ISimpleRoot' => __DIR__ . '/../../..' . '/lib/public/Files/SimpleFS/ISimpleRoot.php', 'OCP\\Files\\Storage' => __DIR__ . '/../../..' . '/lib/public/Files/Storage.php', 'OCP\\Files\\StorageAuthException' => __DIR__ . '/../../..' . '/lib/public/Files/StorageAuthException.php', 'OCP\\Files\\StorageBadConfigException' => __DIR__ . '/../../..' . '/lib/public/Files/StorageBadConfigException.php', @@ -489,6 +493,8 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OC\\Encryption\\Manager' => __DIR__ . '/../../..' . '/lib/private/Encryption/Manager.php', 'OC\\Encryption\\Update' => __DIR__ . '/../../..' . '/lib/private/Encryption/Update.php', 'OC\\Encryption\\Util' => __DIR__ . '/../../..' . '/lib/private/Encryption/Util.php', + 'OC\\Files\\AppData\\AppData' => __DIR__ . '/../../..' . '/lib/private/Files/AppData/AppData.php', + 'OC\\Files\\AppData\\Factory' => __DIR__ . '/../../..' . '/lib/private/Files/AppData/Factory.php', 'OC\\Files\\Cache\\Cache' => __DIR__ . '/../../..' . '/lib/private/Files/Cache/Cache.php', 'OC\\Files\\Cache\\CacheEntry' => __DIR__ . '/../../..' . '/lib/private/Files/Cache/CacheEntry.php', 'OC\\Files\\Cache\\FailedCache' => __DIR__ . '/../../..' . '/lib/private/Files/Cache/FailedCache.php', @@ -530,6 +536,8 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OC\\Files\\ObjectStore\\NoopScanner' => __DIR__ . '/../../..' . '/lib/private/Files/ObjectStore/NoopScanner.php', 'OC\\Files\\ObjectStore\\ObjectStoreStorage' => __DIR__ . '/../../..' . '/lib/private/Files/ObjectStore/ObjectStoreStorage.php', 'OC\\Files\\ObjectStore\\Swift' => __DIR__ . '/../../..' . '/lib/private/Files/ObjectStore/Swift.php', + 'OC\\Files\\SimpleFS\\SimpleFile' => __DIR__ . '/../../..' . '/lib/private/Files/SimpleFS/SimpleFile.php', + 'OC\\Files\\SimpleFS\\SimpleFolder' => __DIR__ . '/../../..' . '/lib/private/Files/SimpleFS/SimpleFolder.php', 'OC\\Files\\Storage\\Common' => __DIR__ . '/../../..' . '/lib/private/Files/Storage/Common.php', 'OC\\Files\\Storage\\CommonTest' => __DIR__ . '/../../..' . '/lib/private/Files/Storage/CommonTest.php', 'OC\\Files\\Storage\\DAV' => __DIR__ . '/../../..' . '/lib/private/Files/Storage/DAV.php', @@ -668,6 +676,8 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c 'OC\\Repair\\FillETags' => __DIR__ . '/../../..' . '/lib/private/Repair/FillETags.php', 'OC\\Repair\\InnoDB' => __DIR__ . '/../../..' . '/lib/private/Repair/InnoDB.php', 'OC\\Repair\\MoveUpdaterStepFile' => __DIR__ . '/../../..' . '/lib/private/Repair/MoveUpdaterStepFile.php', + 'OC\\Repair\\NC11\\MoveAvatars' => __DIR__ . '/../../..' . '/lib/private/Repair/NC11/MoveAvatars.php', + 'OC\\Repair\\NC11\\MoveAvatarsBackgroundJob' => __DIR__ . '/../../..' . '/lib/private/Repair/NC11/MoveAvatarBackgroundJob.php', 'OC\\Repair\\OldGroupMembershipShares' => __DIR__ . '/../../..' . '/lib/private/Repair/OldGroupMembershipShares.php', 'OC\\Repair\\Preview' => __DIR__ . '/../../..' . '/lib/private/Repair/Preview.php', 'OC\\Repair\\RemoveGetETagEntries' => __DIR__ . '/../../..' . '/lib/private/Repair/RemoveGetETagEntries.php', diff --git a/lib/private/AppFramework/DependencyInjection/DIContainer.php b/lib/private/AppFramework/DependencyInjection/DIContainer.php index 20351d1321..b6f8d8f458 100644 --- a/lib/private/AppFramework/DependencyInjection/DIContainer.php +++ b/lib/private/AppFramework/DependencyInjection/DIContainer.php @@ -46,6 +46,7 @@ use OC\AppFramework\Utility\SimpleContainer; use OC\Core\Middleware\TwoFactorMiddleware; use OCP\AppFramework\IApi; use OCP\AppFramework\IAppContainer; +use OCP\Files\IAppData; class DIContainer extends SimpleContainer implements IAppContainer { @@ -164,6 +165,10 @@ class DIContainer extends SimpleContainer implements IAppContainer { return $this->getServer()->getHTTPClientService(); }); + $this->registerService(IAppData::class, function (SimpleContainer $c) { + return $this->getServer()->getAppDataDir($c->query('AppName')); + }); + $this->registerService('OCP\\IGroupManager', function($c) { return $this->getServer()->getGroupManager(); }); diff --git a/lib/private/Avatar.php b/lib/private/Avatar.php index 9e8bd0136c..c3a068701d 100644 --- a/lib/private/Avatar.php +++ b/lib/private/Avatar.php @@ -29,10 +29,10 @@ namespace OC; use OC\User\User; -use OCP\Files\Folder; -use OCP\Files\File; use OCP\Files\NotFoundException; use OCP\Files\NotPermittedException; +use OCP\Files\SimpleFS\ISimpleFile; +use OCP\Files\SimpleFS\ISimpleFolder; use OCP\IAvatar; use OCP\IConfig; use OCP\IImage; @@ -45,7 +45,7 @@ use OCP\ILogger; */ class Avatar implements IAvatar { - /** @var Folder */ + /** @var ISimpleFolder */ private $folder; /** @var IL10N */ private $l; @@ -59,13 +59,13 @@ class Avatar implements IAvatar { /** * constructor * - * @param Folder $folder The folder where the avatars are + * @param ISimpleFolder $folder The folder where the avatars are * @param IL10N $l * @param User $user * @param ILogger $logger * @param IConfig $config */ - public function __construct(Folder $folder, + public function __construct(ISimpleFolder $folder, IL10N $l, $user, ILogger $logger, @@ -98,7 +98,8 @@ class Avatar implements IAvatar { * @return bool */ public function exists() { - return $this->folder->nodeExists('avatar.jpg') || $this->folder->nodeExists('avatar.png'); + + return $this->folder->fileExists('avatar.jpg') || $this->folder->fileExists('avatar.png'); } /** @@ -170,15 +171,15 @@ class Avatar implements IAvatar { } try { - $file = $this->folder->get($path); + $file = $this->folder->getFile($path); } catch (NotFoundException $e) { if ($size <= 0) { throw new NotFoundException; } $avatar = new OC_Image(); - /** @var File $file */ - $file = $this->folder->get('avatar.' . $ext); + /** @var ISimpleFile $file */ + $file = $this->folder->getFile('avatar.' . $ext); $avatar->loadFromData($file->getContent()); if ($size !== -1) { $avatar->resize($size); @@ -201,9 +202,9 @@ class Avatar implements IAvatar { * @throws NotFoundException */ private function getExtension() { - if ($this->folder->nodeExists('avatar.jpg')) { + if ($this->folder->fileExists('avatar.jpg')) { return 'jpg'; - } elseif ($this->folder->nodeExists('avatar.png')) { + } elseif ($this->folder->fileExists('avatar.png')) { return 'png'; } throw new NotFoundException; diff --git a/lib/private/AvatarManager.php b/lib/private/AvatarManager.php index df3247b8f0..b8c6c2a1eb 100644 --- a/lib/private/AvatarManager.php +++ b/lib/private/AvatarManager.php @@ -27,13 +27,12 @@ namespace OC; -use OCP\Files\Folder; +use OCP\Files\IAppData; use OCP\Files\NotFoundException; use OCP\IAvatarManager; use OCP\IConfig; use OCP\ILogger; use OCP\IUserManager; -use OCP\Files\IRootFolder; use OCP\IL10N; /** @@ -44,8 +43,8 @@ class AvatarManager implements IAvatarManager { /** @var IUserManager */ private $userManager; - /** @var IRootFolder */ - private $rootFolder; + /** @var IAppData */ + private $appData; /** @var IL10N */ private $l; @@ -60,19 +59,19 @@ class AvatarManager implements IAvatarManager { * AvatarManager constructor. * * @param IUserManager $userManager - * @param IRootFolder $rootFolder + * @param IAppData $appData * @param IL10N $l * @param ILogger $logger * @param IConfig $config */ public function __construct( IUserManager $userManager, - IRootFolder $rootFolder, + IAppData $appData, IL10N $l, ILogger $logger, IConfig $config) { $this->userManager = $userManager; - $this->rootFolder = $rootFolder; + $this->appData = $appData; $this->l = $l; $this->logger = $logger; $this->config = $config; @@ -95,20 +94,12 @@ class AvatarManager implements IAvatarManager { // sanitize userID - fixes casing issue (needed for the filesystem stuff that is done below) $userId = $user->getUID(); - /* - * Fix for #22119 - * Basically we do not want to copy the skeleton folder. - * - * For unit test purposes this is ignored when run in PHPUnit. - */ - if(!defined('PHPUNIT_RUN')) { - \OC\Files\Filesystem::initMountPoints($userId); + try { + $folder = $this->appData->getFolder($userId); + } catch (NotFoundException $e) { + $folder = $this->appData->newFolder($userId); } - $dir = '/' . $userId; - /** @var Folder $folder */ - $folder = $this->rootFolder->get($dir); - return new Avatar($folder, $this->l, $user, $this->logger, $this->config); } } diff --git a/lib/private/Files/AppData/AppData.php b/lib/private/Files/AppData/AppData.php new file mode 100644 index 0000000000..270e834b8e --- /dev/null +++ b/lib/private/Files/AppData/AppData.php @@ -0,0 +1,131 @@ + + * + * @author Roeland Jago Douma + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * 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 + * along with this program. If not, see . + * + */ + +namespace OC\Files\AppData; + +use OC\Files\SimpleFS\SimpleFolder; +use OCP\Files\IAppData; +use OCP\Files\IRootFolder; +use OCP\Files\Folder; +use OC\SystemConfig; +use OCP\Files\Node; +use OCP\Files\NotFoundException; +use OCP\Files\NotPermittedException; + +class AppData implements IAppData { + + /** @var IRootFolder */ + private $rootFolder; + + /** @var SystemConfig */ + private $config; + + /** @var string */ + private $appId; + + /** @var Folder */ + private $folder; + + /** + * AppData constructor. + * + * @param IRootFolder $rootFolder + * @param SystemConfig $systemConfig + * @param string $appId + */ + public function __construct(IRootFolder $rootFolder, + SystemConfig $systemConfig, + $appId) { + + $this->rootFolder = $rootFolder; + $this->config = $systemConfig; + $this->appId = $appId; + } + + /** + * @return Folder + * @throws \RuntimeException + */ + private function getAppDataFolder() { + if ($this->folder === null) { + $instanceId = $this->config->getValue('instanceid', null); + if ($instanceId === null) { + throw new \RuntimeException('no instance id!'); + } + + $name = 'appdata_' . $instanceId; + + try { + $appDataFolder = $this->rootFolder->get($name); + } catch (NotFoundException $e) { + try { + $appDataFolder = $this->rootFolder->newFolder($name); + } catch (NotPermittedException $e) { + throw new \RuntimeException('Could not get appdata folder'); + } + } + + try { + $appDataFolder = $appDataFolder->get($this->appId); + } catch (NotFoundException $e) { + try { + $appDataFolder = $appDataFolder->newFolder($this->appId); + } catch (NotPermittedException $e) { + throw new \RuntimeException('Could not get appdata folder for ' . $this->appId); + } + } + + $this->folder = $appDataFolder; + } + + return $this->folder; + } + + public function getFolder($name) { + $node = $this->getAppDataFolder()->get($name); + + /** @var Folder $node */ + return new SimpleFolder($node); + } + + public function newFolder($name) { + $folder = $this->getAppDataFolder()->newFolder($name); + + return new SimpleFolder($folder); + } + + public function getDirectoryListing() { + $listing = $this->getAppDataFolder()->getDirectoryListing(); + + $fileListing = array_map(function(Node $folder) { + if ($folder instanceof Folder) { + return new SimpleFolder($folder); + } + return null; + }, $listing); + + $fileListing = array_filter($fileListing); + + return array_values($fileListing); + } +} diff --git a/lib/private/Files/AppData/Factory.php b/lib/private/Files/AppData/Factory.php new file mode 100644 index 0000000000..85c7573379 --- /dev/null +++ b/lib/private/Files/AppData/Factory.php @@ -0,0 +1,50 @@ + + * + * @author Roeland Jago Douma + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * 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 + * along with this program. If not, see . + * + */ +namespace OC\Files\AppData; + +use OC\SystemConfig; +use OCP\Files\IRootFolder; + +class Factory { + + /** @var IRootFolder */ + private $rootFolder; + + /** @var SystemConfig */ + private $config; + + public function __construct(IRootFolder $rootFolder, + SystemConfig $systemConfig) { + + $this->rootFolder = $rootFolder; + $this->config = $systemConfig; + } + + /** + * @param string $appId + * @return AppData + */ + public function get($appId) { + return new AppData($this->rootFolder, $this->config, $appId); + } +} diff --git a/lib/private/Files/SimpleFS/SimpleFile.php b/lib/private/Files/SimpleFS/SimpleFile.php new file mode 100644 index 0000000000..5eadfd98b6 --- /dev/null +++ b/lib/private/Files/SimpleFS/SimpleFile.php @@ -0,0 +1,115 @@ + + * + * @author Roeland Jago Douma + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * 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 + * along with this program. If not, see . + * + */ +namespace OC\Files\SimpleFS; + +use OCP\Files\File; +use OCP\Files\NotPermittedException; +use OCP\Files\SimpleFS\ISimpleFile; + +class SimpleFile implements ISimpleFile { + + /** @var File $file */ + private $file; + + /** + * File constructor. + * + * @param File $file + */ + public function __construct(File $file) { + $this->file = $file; + } + + /** + * Get the name + * + * @return string + */ + public function getName() { + return $this->file->getName(); + } + + /** + * Get the size in bytes + * + * @return int + */ + public function getSize() { + return $this->file->getSize(); + } + + /** + * Get the ETag + * + * @return string + */ + public function getETag() { + return $this->file->getEtag(); + } + + /** + * Get the last modification time + * + * @return int + */ + public function getMTime() { + return $this->file->getMTime(); + } + + /** + * Get the content + * + * @return string + */ + public function getContent() { + return $this->file->getContent(); + } + + /** + * Overwrite the file + * + * @param string $data + * @throws NotPermittedException + */ + public function putContent($data) { + $this->file->putContent($data); + } + + /** + * Delete the file + * + * @throws NotPermittedException + */ + public function delete() { + $this->file->delete(); + } + + /** + * Get the MimeType + * + * @return string + */ + public function getMimeType() { + return $this->file->getMimeType(); + } +} diff --git a/lib/private/Files/SimpleFS/SimpleFolder.php b/lib/private/Files/SimpleFS/SimpleFolder.php new file mode 100644 index 0000000000..5b55fe0f15 --- /dev/null +++ b/lib/private/Files/SimpleFS/SimpleFolder.php @@ -0,0 +1,87 @@ + + * + * @author Roeland Jago Douma + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * 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 + * along with this program. If not, see . + * + */ +namespace OC\Files\SimpleFS; + +use OCP\Files\File; +use OCP\Files\Folder; +use OCP\Files\Node; +use OCP\Files\NotFoundException; +use OCP\Files\SimpleFS\ISimpleFolder; + +class SimpleFolder implements ISimpleFolder { + + /** @var Folder */ + private $folder; + + /** + * Folder constructor. + * + * @param Folder $folder + */ + public function __construct(Folder $folder) { + $this->folder = $folder; + } + + public function getName() { + return $this->folder->getName(); + } + + public function getDirectoryListing() { + $listing = $this->folder->getDirectoryListing(); + + $fileListing = array_map(function(Node $file) { + if ($file instanceof File) { + return new SimpleFile($file); + } + return null; + }, $listing); + + $fileListing = array_filter($fileListing); + + return array_values($fileListing); + } + + public function delete() { + $this->folder->delete(); + } + + public function fileExists($name) { + return $this->folder->nodeExists($name); + } + + public function getFile($name) { + $file = $this->folder->get($name); + + if (!($file instanceof File)) { + throw new NotFoundException(); + } + + return new SimpleFile($file); + } + + public function newFile($name) { + $file = $this->folder->newFile($name); + + return new SimpleFile($file); + } +} diff --git a/lib/private/Repair.php b/lib/private/Repair.php index bf441d03c3..2ba118b9c3 100644 --- a/lib/private/Repair.php +++ b/lib/private/Repair.php @@ -36,6 +36,7 @@ use OC\Repair\CleanTags; use OC\Repair\Collation; use OC\Repair\DropOldJobs; use OC\Repair\MoveUpdaterStepFile; +use OC\Repair\NC11\MoveAvatars; use OC\Repair\OldGroupMembershipShares; use OC\Repair\RemoveGetETagEntries; use OC\Repair\RemoveOldShares; @@ -149,6 +150,10 @@ class Repair implements IOutput{ \OC::$server->getGroupManager() ), new MoveUpdaterStepFile(\OC::$server->getConfig()), + new MoveAvatars( + \OC::$server->getJobList(), + \OC::$server->getSystemConfig() + ), ]; } diff --git a/lib/private/Repair/NC11/MoveAvatarBackgroundJob.php b/lib/private/Repair/NC11/MoveAvatarBackgroundJob.php new file mode 100644 index 0000000000..993235146c --- /dev/null +++ b/lib/private/Repair/NC11/MoveAvatarBackgroundJob.php @@ -0,0 +1,104 @@ + + * + * @author Roeland Jago Douma + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * 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 + * along with this program. If not, see . + * + */ +namespace OC\Repair\NC11; + +use OC\BackgroundJob\QueuedJob; +use OCP\Files\File; +use OCP\Files\Folder; +use OCP\Files\IAppData; +use OCP\Files\IRootFolder; +use OCP\Files\NotFoundException; +use OCP\ILogger; +use OCP\IUser; +use OCP\IUserManager; + +class MoveAvatarsBackgroundJob extends QueuedJob { + + /** @var IUserManager */ + private $userManager; + + /** @var IRootFolder */ + private $rootFolder; + + /** @var IAppData */ + private $appData; + + /** @var ILogger */ + private $logger; + + /** + * MoveAvatars constructor. + */ + public function __construct() { + $this->userManager = \OC::$server->getUserManager(); + $this->rootFolder = \OC::$server->getRootFolder(); + $this->logger = \OC::$server->getLogger(); + $this->appData = \OC::$server->getAppDataDir('avatar'); + } + + public function run($arguments) { + $this->logger->info('Started migrating avatars to AppData folder'); + $this->moveAvatars(); + $this->logger->info('All avatars migrated to AppData folder'); + } + + private function moveAvatars() { + $counter = 0; + $this->userManager->callForAllUsers(function (IUser $user) use ($counter) { + if ($user->getLastLogin() !== 0) { + $uid = $user->getUID(); + + \OC\Files\Filesystem::initMountPoints($uid); + /** @var Folder $userFolder */ + $userFolder = $this->rootFolder->get($uid); + + try { + $userData = $this->appData->getFolder($uid); + } catch (NotFoundException $e) { + $userData = $this->appData->newFolder($uid); + } + + + $regex = '/^avatar\.([0-9]+\.)?(jpg|png)$/'; + $avatars = $userFolder->getDirectoryListing(); + + foreach ($avatars as $avatar) { + /** @var File $avatar */ + if (preg_match($regex, $avatar->getName())) { + /* + * This is not the most effective but it is the most abstract way + * to handle this. Avatars should be small anyways. + */ + $newAvatar = $userData->newFile($avatar->getName()); + $newAvatar->putContent($avatar->getContent()); + $avatar->delete(); + } + } + } + $counter++; + if ($counter % 100) { + $this->logger->info('{amount} avatars migrated', ['amount' => $counter]); + } + }); + } +} diff --git a/lib/private/Repair/NC11/MoveAvatars.php b/lib/private/Repair/NC11/MoveAvatars.php new file mode 100644 index 0000000000..44402b1be4 --- /dev/null +++ b/lib/private/Repair/NC11/MoveAvatars.php @@ -0,0 +1,64 @@ + + * + * @author Roeland Jago Douma + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * 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 + * along with this program. If not, see . + * + */ +namespace OC\Repair\NC11; + +use OC\SystemConfig; +use OCP\BackgroundJob\IJobList; +use OCP\Migration\IOutput; +use OCP\Migration\IRepairStep; + +class MoveAvatars implements IRepairStep { + + /** @var IJobList */ + private $jobList; + + /** @var SystemConfig */ + private $systemConfig; + + /** + * MoveAvatars constructor. + * + * @param IJobList $jobList + * @param SystemConfig $systemConfig + */ + public function __construct(IJobList $jobList, + SystemConfig $systemConfig) { + $this->jobList = $jobList; + $this->systemConfig = $systemConfig; + } + + /** + * @return string + */ + public function getName() { + return 'Add mover avatar background job'; + } + + public function run(IOutput $output) { + if ($this->systemConfig->getValue('enable_avatars', true) === false) { + $output->info('Avatars are disabled'); + } else { + $this->jobList->add(MoveAvatarsBackgroundJob::class); + } + } +} diff --git a/lib/private/Server.php b/lib/private/Server.php index 494387ab6c..b49e94b554 100644 --- a/lib/private/Server.php +++ b/lib/private/Server.php @@ -359,7 +359,7 @@ class Server extends ServerContainer implements IServerContainer { $this->registerService('AvatarManager', function (Server $c) { return new AvatarManager( $c->getUserManager(), - $c->getRootFolder(), + $c->getAppDataDir('avatar'), $c->getL10N('lib'), $c->getLogger(), $c->getConfig() @@ -742,6 +742,12 @@ class Server extends ServerContainer implements IServerContainer { ); return $manager; }); + $this->registerService(\OC\Files\AppData\Factory::class, function (Server $c) { + return new \OC\Files\AppData\Factory( + $c->getRootFolder(), + $c->getSystemConfig() + ); + }); } /** @@ -876,6 +882,7 @@ class Server extends ServerContainer implements IServerContainer { * Returns an app-specific view in ownClouds data directory * * @return \OCP\Files\Folder + * @deprecated since 9.2.0 use IAppData */ public function getAppFolder() { $dir = '/' . \OC_App::getCurrentApp(); @@ -1456,4 +1463,13 @@ class Server extends ServerContainer implements IServerContainer { public function getSettingsManager() { return $this->query('SettingsManager'); } + + /** + * @return \OCP\Files\IAppData + */ + public function getAppDataDir($app) { + /** @var \OC\Files\AppData\Factory $factory */ + $factory = $this->query(\OC\Files\AppData\Factory::class); + return $factory->get($app); + } } diff --git a/lib/private/legacy/util.php b/lib/private/legacy/util.php index cb52949779..b8f3a93ba5 100644 --- a/lib/private/legacy/util.php +++ b/lib/private/legacy/util.php @@ -311,10 +311,20 @@ class OC_Util { * * @param String $userId * @param \OCP\Files\Folder $userDirectory + * @throws \RuntimeException */ public static function copySkeleton($userId, \OCP\Files\Folder $userDirectory) { - $skeletonDirectory = \OCP\Config::getSystemValue('skeletondirectory', \OC::$SERVERROOT . '/core/skeleton'); + $skeletonDirectory = \OC::$server->getConfig()->getSystemValue('skeletondirectory', \OC::$SERVERROOT . '/core/skeleton'); + $instanceId = \OC::$server->getConfig()->getSystemValue('instanceid', ''); + + if ($instanceId === null) { + throw new \RuntimeException('no instance id!'); + } + $appdata = 'appdata_' . $instanceId; + if ($userId === $appdata) { + throw new \RuntimeException('username is reserved name: ' . $appdata); + } if (!empty($skeletonDirectory)) { \OCP\Util::writeLog( diff --git a/lib/public/AppFramework/Http/FileDisplayResponse.php b/lib/public/AppFramework/Http/FileDisplayResponse.php index 22171e2b37..03a6fbec2d 100644 --- a/lib/public/AppFramework/Http/FileDisplayResponse.php +++ b/lib/public/AppFramework/Http/FileDisplayResponse.php @@ -23,7 +23,6 @@ namespace OCP\AppFramework\Http; use OCP\AppFramework\Http; -use OCP\Files\File; /** * Class FileDisplayResponse @@ -33,18 +32,18 @@ use OCP\Files\File; */ class FileDisplayResponse extends Response implements ICallbackResponse { - /** @var File */ + /** @var \OCP\Files\File|\OCP\Files\SimpleFS\ISimpleFile */ private $file; /** * FileDisplayResponse constructor. * - * @param File $file + * @param \OCP\Files\File|\OCP\Files\SimpleFS\ISimpleFile $file * @param int $statusCode * @param array $headers * @since 9.2.0 */ - public function __construct(File $file, $statusCode=Http::STATUS_OK, + public function __construct($file, $statusCode=Http::STATUS_OK, $headers=[]) { $this->file = $file; $this->setStatus($statusCode); diff --git a/lib/public/Files/IAppData.php b/lib/public/Files/IAppData.php new file mode 100644 index 0000000000..92e54fee36 --- /dev/null +++ b/lib/public/Files/IAppData.php @@ -0,0 +1,36 @@ + + * + * @author Roeland Jago Douma + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * 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 + * along with this program. If not, see . + * + */ +namespace OCP\Files; + +use OCP\Files\SimpleFS\ISimpleRoot; + +/** + * Interface IAppData + * + * @package OCP\Files + * @since 9.2.0 + * @internal This interface is experimental and might change for NC12 + */ +interface IAppData extends ISimpleRoot { + +} diff --git a/lib/public/Files/SimpleFS/ISimpleFile.php b/lib/public/Files/SimpleFS/ISimpleFile.php new file mode 100644 index 0000000000..efd682e785 --- /dev/null +++ b/lib/public/Files/SimpleFS/ISimpleFile.php @@ -0,0 +1,100 @@ + + * + * @author Roeland Jago Douma + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * 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 + * along with this program. If not, see . + * + */ +namespace OCP\Files\SimpleFS; + +use OCP\Files\NotPermittedException; + +/** + * Interface ISimpleFile + * + * @package OCP\Files\SimpleFS + * @since 9.2.0 + * @internal This interface is experimental and might change for NC12 + */ +interface ISimpleFile { + + /** + * Get the name + * + * @return string + * @since 9.2.0 + */ + public function getName(); + + /** + * Get the size in bytes + * + * @return int + * @since 9.2.0 + */ + public function getSize(); + + /** + * Get the ETag + * + * @return string + * @since 9.2.0 + */ + public function getETag(); + + /** + * Get the last modification time + * + * @return int + * @since 9.2.0 + */ + public function getMTime(); + + /** + * Get the content + * + * @return string + * @since 9.2.0 + */ + public function getContent(); + + /** + * Overwrite the file + * + * @param string $data + * @throws NotPermittedException + * @since 9.2.0 + */ + public function putContent($data); + + /** + * Delete the file + * + * @throws NotPermittedException + * @since 9.2.0 + */ + public function delete(); + + /** + * Get the MimeType + * + * @return string + * @since 9.2.0 + */ + public function getMimeType(); +} diff --git a/lib/public/Files/SimpleFS/ISimpleFolder.php b/lib/public/Files/SimpleFS/ISimpleFolder.php new file mode 100644 index 0000000000..406bb63115 --- /dev/null +++ b/lib/public/Files/SimpleFS/ISimpleFolder.php @@ -0,0 +1,88 @@ + + * + * @author Roeland Jago Douma + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * 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 + * along with this program. If not, see . + * + */ +namespace OCP\Files\SimpleFS; + +use OCP\Files\NotFoundException; +use OCP\Files\NotPermittedException; + +/** + * Interface ISimpleFolder + * + * @package OCP\Files\SimpleFS + * @since 9.2.0 + * @internal This interface is experimental and might change for NC12 + */ +interface ISimpleFolder { + /** + * Get all the files in a folder + * + * @return ISimpleFile[] + * @since 9.2.0 + */ + public function getDirectoryListing(); + + /** + * Check if a file with $name exists + * + * @param string $name + * @return bool + * @since 9.2.0 + */ + public function fileExists($name); + + /** + * Get the file named $name from the folder + * + * @param string $name + * @return ISimpleFile + * @throws NotFoundException + * @since 9.2.0 + */ + public function getFile($name); + + /** + * Creates a new file with $name in the folder + * + * @param string $name + * @return ISimpleFile + * @throws NotPermittedException + * @since 9.2.0 + */ + public function newFile($name); + + /** + * Remove the folder and all the files in it + * + * @throws NotPermittedException + * @since 9.2.0 + */ + public function delete(); + + /** + * Get the folder name + * + * @return string + * @since 9.2.0 + */ + public function getName(); +} diff --git a/lib/public/Files/SimpleFS/ISimpleRoot.php b/lib/public/Files/SimpleFS/ISimpleRoot.php new file mode 100644 index 0000000000..c2f9d4ff05 --- /dev/null +++ b/lib/public/Files/SimpleFS/ISimpleRoot.php @@ -0,0 +1,67 @@ + + * + * @author Roeland Jago Douma + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * 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 + * along with this program. If not, see . + * + */ +namespace OCP\Files\SimpleFS; + +use OCP\Files\NotFoundException; +use OCP\Files\NotPermittedException; + +/** + * Interface ISimpleRoot + * + * @package OCP\Files\SimpleFS + * @since 9.2.0 + * @internal This interface is experimental and might change for NC12 + */ +interface ISimpleRoot { + /** + * Get the folder with name $name + * + * @param string $name + * @return ISimpleFolder + * @throws NotFoundException + * @throws \RuntimeException + * @since 9.2.0 + */ + public function getFolder($name); + + /** + * Get all the Folders + * + * @return ISimpleFolder[] + * @throws NotFoundException + * @throws \RuntimeException + * @since 9.2.0 + */ + public function getDirectoryListing(); + + /** + * Create a new folder named $name + * + * @param string $name + * @return ISimpleFolder + * @throws NotPermittedException + * @throws \RuntimeException + * @since 9.2.0 + */ + public function newFolder($name); +} diff --git a/lib/public/IServerContainer.php b/lib/public/IServerContainer.php index b736af2899..354e39bd8f 100644 --- a/lib/public/IServerContainer.php +++ b/lib/public/IServerContainer.php @@ -115,6 +115,7 @@ interface IServerContainer { * * @return \OCP\Files\Folder * @since 6.0.0 + * @deprecated since 9.2.0 use IAppData */ public function getAppFolder(); diff --git a/tests/lib/AvatarManagerTest.php b/tests/lib/AvatarManagerTest.php index 0ad998af6d..8ccc51d12e 100644 --- a/tests/lib/AvatarManagerTest.php +++ b/tests/lib/AvatarManagerTest.php @@ -26,8 +26,8 @@ namespace Test; use OC\Avatar; use OC\AvatarManager; -use OCP\Files\Folder; -use OCP\Files\IRootFolder; +use OCP\Files\IAppData; +use OCP\Files\SimpleFS\ISimpleFolder; use OCP\IConfig; use OCP\IL10N; use OCP\ILogger; @@ -40,8 +40,8 @@ use OCP\IUserManager; class AvatarManagerTest extends \Test\TestCase { /** @var IUserManager|\PHPUnit_Framework_MockObject_MockObject */ private $userManager; - /** @var IRootFolder|\PHPUnit_Framework_MockObject_MockObject */ - private $rootFolder; + /** @var IAppData|\PHPUnit_Framework_MockObject_MockObject */ + private $appData; /** @var IL10N|\PHPUnit_Framework_MockObject_MockObject */ private $l10n; /** @var ILogger|\PHPUnit_Framework_MockObject_MockObject */ @@ -55,14 +55,14 @@ class AvatarManagerTest extends \Test\TestCase { parent::setUp(); $this->userManager = $this->createMock(IUserManager::class); - $this->rootFolder = $this->createMock(IRootFolder::class); + $this->appData = $this->createMock(IAppData::class); $this->l10n = $this->createMock(IL10N::class); $this->logger = $this->createMock(ILogger::class); $this->config = $this->createMock(IConfig::class); $this->avatarManager = new AvatarManager( $this->userManager, - $this->rootFolder, + $this->appData, $this->l10n, $this->logger, $this->config @@ -94,11 +94,11 @@ class AvatarManagerTest extends \Test\TestCase { ->method('get') ->with('valid-user') ->willReturn($user); - $folder = $this->createMock(Folder::class); - $this->rootFolder + $folder = $this->createMock(ISimpleFolder::class); + $this->appData ->expects($this->once()) - ->method('get') - ->with('/valid-user') + ->method('getFolder') + ->with('valid-user') ->willReturn($folder); $expected = new Avatar($folder, $this->l10n, $user, $this->logger, $this->config);; diff --git a/tests/lib/AvatarTest.php b/tests/lib/AvatarTest.php index 7f012c895f..cea3f9bed1 100644 --- a/tests/lib/AvatarTest.php +++ b/tests/lib/AvatarTest.php @@ -8,6 +8,8 @@ namespace Test; +use OC\Files\SimpleFS\SimpleFolder; +use OC\User\User; use OCP\Files\File; use OCP\Files\Folder; use OCP\IConfig; @@ -30,11 +32,11 @@ class AvatarTest extends \Test\TestCase { public function setUp() { parent::setUp(); - $this->folder = $this->createMock(Folder::class); + $this->folder = $this->createMock(SimpleFolder::class); /** @var \OCP\IL10N | \PHPUnit_Framework_MockObject_MockObject $l */ $l = $this->createMock(IL10N::class); $l->method('t')->will($this->returnArgument(0)); - $this->user = $this->getMockBuilder('OC\User\User')->disableOriginalConstructor()->getMock(); + $this->user = $this->createMock(User::class); $this->config = $this->createMock(IConfig::class); $this->avatar = new \OC\Avatar( @@ -51,7 +53,7 @@ class AvatarTest extends \Test\TestCase { } public function testGetAvatarSizeMatch() { - $this->folder->method('nodeExists') + $this->folder->method('fileExists') ->will($this->returnValueMap([ ['avatar.jpg', true], ['avatar.128.jpg', true], @@ -61,13 +63,13 @@ class AvatarTest extends \Test\TestCase { $file = $this->createMock(File::class); $file->method('getContent')->willReturn($expected->data()); - $this->folder->method('get')->with('avatar.128.jpg')->willReturn($file); + $this->folder->method('getFile')->with('avatar.128.jpg')->willReturn($file); $this->assertEquals($expected->data(), $this->avatar->get(128)->data()); } public function testGetAvatarSizeMinusOne() { - $this->folder->method('nodeExists') + $this->folder->method('fileExists') ->will($this->returnValueMap([ ['avatar.jpg', true], ])); @@ -76,13 +78,13 @@ class AvatarTest extends \Test\TestCase { $file = $this->createMock(File::class); $file->method('getContent')->willReturn($expected->data()); - $this->folder->method('get')->with('avatar.jpg')->willReturn($file); + $this->folder->method('getFile')->with('avatar.jpg')->willReturn($file); $this->assertEquals($expected->data(), $this->avatar->get(-1)->data()); } public function testGetAvatarNoSizeMatch() { - $this->folder->method('nodeExists') + $this->folder->method('fileExists') ->will($this->returnValueMap([ ['avatar.png', true], ['avatar.32.png', false], @@ -95,7 +97,7 @@ class AvatarTest extends \Test\TestCase { $file = $this->createMock(File::class); $file->method('getContent')->willReturn($expected->data()); - $this->folder->method('get') + $this->folder->method('getFile') ->will($this->returnCallback( function($path) use ($file) { if ($path === 'avatar.png') { @@ -126,7 +128,7 @@ class AvatarTest extends \Test\TestCase { } public function testExiststJPG() { - $this->folder->method('nodeExists') + $this->folder->method('fileExists') ->will($this->returnValueMap([ ['avatar.jpg', true], ['avatar.png', false], @@ -135,7 +137,7 @@ class AvatarTest extends \Test\TestCase { } public function testExistsPNG() { - $this->folder->method('nodeExists') + $this->folder->method('fileExists') ->will($this->returnValueMap([ ['avatar.jpg', false], ['avatar.png', true], diff --git a/tests/lib/Files/AppData/AppDataTest.php b/tests/lib/Files/AppData/AppDataTest.php new file mode 100644 index 0000000000..3247ce7ba9 --- /dev/null +++ b/tests/lib/Files/AppData/AppDataTest.php @@ -0,0 +1,121 @@ + + * + * @author Roeland Jago Douma + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * 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 + * along with this program. If not, see . + * + */ +namespace Test\Files\AppData; + +use OC\Files\AppData\AppData; +use OC\SystemConfig; +use OCP\Files\File; +use OCP\Files\Folder; +use OCP\Files\IAppData; +use OCP\Files\IRootFolder; +use OCP\Files\Node; +use OCP\Files\SimpleFS\ISimpleFolder; + +class AppDataTest extends \Test\TestCase { + /** @var IRootFolder|\PHPUnit_Framework_MockObject_MockObject */ + private $rootFolder; + + /** @var SystemConfig|\PHPUnit_Framework_MockObject_MockObject */ + private $systemConfig; + + /** @var IAppData */ + private $appData; + + public function setUp() { + parent::setUp(); + + $this->rootFolder = $this->createMock(IRootFolder::class); + $this->systemConfig = $this->createMock(SystemConfig::class); + $this->appData = new AppData($this->rootFolder, $this->systemConfig, 'myApp'); + + $this->systemConfig->expects($this->any()) + ->method('getValue') + ->with('instanceid', null) + ->willReturn('iid'); + } + + private function setupAppFolder() { + $dataFolder = $this->createMock(Folder::class); + $appFolder = $this->createMock(Folder::class); + + $this->rootFolder->expects($this->once()) + ->method('get') + ->with($this->equalTo('appdata_iid')) + ->willReturn($dataFolder); + $dataFolder->expects($this->once()) + ->method('get') + ->with($this->equalTo('myApp')) + ->willReturn($appFolder); + + return [$dataFolder, $appFolder]; + } + + public function testGetFolder() { + $folders = $this->setupAppFolder(); + $appFolder = $folders[1]; + + $folder = $this->createMock(Folder::class); + + $appFolder->expects($this->once()) + ->method('get') + ->with($this->equalTo('folder')) + ->willReturn($folder); + + $result = $this->appData->getFolder('folder'); + $this->assertInstanceOf(ISimpleFolder::class, $result); + } + + public function testNewFolder() { + $folders = $this->setupAppFolder(); + $appFolder = $folders[1]; + + $folder = $this->createMock(Folder::class); + + $appFolder->expects($this->once()) + ->method('newFolder') + ->with($this->equalTo('folder')) + ->willReturn($folder); + + $result = $this->appData->newFolder('folder'); + $this->assertInstanceOf(ISimpleFolder::class, $result); + } + + public function testGetDirectoryListing() { + $folders = $this->setupAppFolder(); + $appFolder = $folders[1]; + + $file = $this->createMock(File::class); + $folder = $this->createMock(Folder::class); + $node = $this->createMock(Node::class); + + $appFolder->expects($this->once()) + ->method('getDirectoryListing') + ->willReturn([$file, $folder, $node]); + + $result = $this->appData->getDirectoryListing(); + + $this->assertCount(1, $result); + $this->assertInstanceOf(ISimpleFolder::class, $result[0]); + } + +} diff --git a/tests/lib/Files/AppData/FactoryTest.php b/tests/lib/Files/AppData/FactoryTest.php new file mode 100644 index 0000000000..75999c8c7d --- /dev/null +++ b/tests/lib/Files/AppData/FactoryTest.php @@ -0,0 +1,55 @@ + + * + * @author Roeland Jago Douma + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * 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 + * along with this program. If not, see . + * + */ +namespace Test\Files\AppData; + +use OC\Files\AppData\Factory; +use OC\SystemConfig; +use OCP\Files\IRootFolder; + +class FactoryTest extends \Test\TestCase { + /** @var IRootFolder|\PHPUnit_Framework_MockObject_MockObject */ + private $rootFolder; + + /** @var SystemConfig|\PHPUnit_Framework_MockObject_MockObject */ + private $systemConfig; + + /** @var Factory */ + private $factory; + + public function setUp() { + parent::setUp(); + + $this->rootFolder = $this->createMock(IRootFolder::class); + $this->systemConfig = $this->createMock(SystemConfig::class); + $this->factory = new Factory($this->rootFolder, $this->systemConfig); + } + + public function testGet() { + $this->rootFolder->expects($this->never()) + ->method($this->anything()); + $this->systemConfig->expects($this->never()) + ->method($this->anything()); + + $this->factory->get('foo'); + } +} diff --git a/tests/lib/Files/SimpleFS/SimpleFileTest.php b/tests/lib/Files/SimpleFS/SimpleFileTest.php new file mode 100644 index 0000000000..4e623eafa2 --- /dev/null +++ b/tests/lib/Files/SimpleFS/SimpleFileTest.php @@ -0,0 +1,104 @@ + + * + * @author Roeland Jago Douma + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * 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 + * along with this program. If not, see . + * + */ +namespace Test\File\SimpleFS; + +use OC\Files\SimpleFS\SimpleFile; +use OCP\Files\File; + +class SimpleFileTest extends \Test\TestCase { + /** @var File|\PHPUnit_Framework_MockObject_MockObject */ + private $file; + + /** @var SimpleFile */ + private $simpleFile; + + public function setUp() { + parent::setUp(); + + $this->file = $this->createMock(File::class); + $this->simpleFile = new SimpleFile($this->file); + } + + public function testGetName() { + $this->file->expects($this->once()) + ->method('getName') + ->willReturn('myname'); + + $this->assertEquals('myname', $this->simpleFile->getName()); + } + + public function testGetSize() { + $this->file->expects($this->once()) + ->method('getSize') + ->willReturn(42); + + $this->assertEquals(42, $this->simpleFile->getSize()); + } + + public function testGetETag() { + $this->file->expects($this->once()) + ->method('getETag') + ->willReturn('etag'); + + $this->assertEquals('etag', $this->simpleFile->getETag()); + } + + public function testGetMTime() { + $this->file->expects($this->once()) + ->method('getMTime') + ->willReturn(101); + + $this->assertEquals(101, $this->simpleFile->getMTime()); + } + + public function testGetContent() { + $this->file->expects($this->once()) + ->method('getContent') + ->willReturn('foo'); + + $this->assertEquals('foo', $this->simpleFile->getContent()); + } + + public function testPutContent() { + $this->file->expects($this->once()) + ->method('putContent') + ->with($this->equalTo('bar')); + + $this->simpleFile->putContent('bar'); + } + + public function testDelete() { + $this->file->expects($this->once()) + ->method('delete'); + + $this->simpleFile->delete(); + } + + public function testGetMimeType() { + $this->file->expects($this->once()) + ->method('getMimeType') + ->willReturn('app/awesome'); + + $this->assertEquals('app/awesome', $this->simpleFile->getMimeType()); + } +} diff --git a/tests/lib/Files/SimpleFS/SimpleFolderTest.php b/tests/lib/Files/SimpleFS/SimpleFolderTest.php new file mode 100644 index 0000000000..d86c705d88 --- /dev/null +++ b/tests/lib/Files/SimpleFS/SimpleFolderTest.php @@ -0,0 +1,138 @@ + + * + * @author Roeland Jago Douma + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * 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 + * along with this program. If not, see . + * + */ +namespace Test\File\SimpleFS; + +use OC\Files\SimpleFS\SimpleFolder; +use OCP\Files\File; +use OCP\Files\Folder; +use OCP\Files\Node; +use OCP\Files\NotFoundException; +use OCP\Files\SimpleFS\ISimpleFile; + +class SimpleFolderTest extends \Test\TestCase { + /** @var Folder|\PHPUnit_Framework_MockObject_MockObject */ + private $folder; + + /** @var SimpleFolder */ + private $simpleFolder; + + public function setUp() { + parent::setUp(); + + $this->folder = $this->createMock(Folder::class); + $this->simpleFolder = new SimpleFolder($this->folder); + } + + public function testGetName() { + $this->folder->expects($this->once()) + ->method('getName') + ->willReturn('myname'); + + $this->assertEquals('myname', $this->simpleFolder->getName()); + } + + public function testDelete() { + $this->folder->expects($this->once()) + ->method('delete'); + + $this->simpleFolder->delete(); + } + + public function dataFileExists() { + return [ + [true], + [false], + ]; + } + + /** + * @dataProvider dataFileExists + * @param bool $exists + */ + public function testFileExists($exists) { + $this->folder->expects($this->once()) + ->method('nodeExists') + ->with($this->equalTo('file')) + ->willReturn($exists); + + $this->assertEquals($exists, $this->simpleFolder->fileExists('file')); + } + + public function dataGetFile() { + return [ + [File::class, false], + [Folder::class, true], + [Node::class, true], + ]; + } + + /** + * @dataProvider dataGetFile + * @param string $class + * @param bool $exception + */ + public function testGetFile($class, $exception) { + $node = $this->createMock($class); + + $this->folder->expects($this->once()) + ->method('get') + ->with($this->equalTo('file')) + ->willReturn($node); + + try { + $result = $this->simpleFolder->getFile('file'); + $this->assertFalse($exception); + $this->assertInstanceOf(ISimpleFile::class, $result); + } catch (NotFoundException $e) { + $this->assertTrue($exception); + } + } + + public function testNewFile() { + $file = $this->createMock(File::class); + + $this->folder->expects($this->once()) + ->method('newFile') + ->with($this->equalTo('file')) + ->willReturn($file); + + $result = $this->simpleFolder->newFile('file'); + $this->assertInstanceOf(ISimpleFile::class, $result); + } + + public function testGetDirectoryListing() { + $file = $this->createMock(File::class); + $folder = $this->createMock(Folder::class); + $node = $this->createMock(Node::class); + + $this->folder->expects($this->once()) + ->method('getDirectoryListing') + ->willReturn([$file, $folder, $node]); + + $result = $this->simpleFolder->getDirectoryListing(); + + $this->assertCount(1, $result); + $this->assertInstanceOf(ISimpleFile::class, $result[0]); + } + +} diff --git a/version.php b/version.php index 01a822708e..96725a6bb4 100644 --- a/version.php +++ b/version.php @@ -25,7 +25,7 @@ // We only can count up. The 4. digit is only for the internal patchlevel to trigger DB upgrades // between betas, final and RCs. This is _not_ the public version number. Reset minor/patchlevel // when updating major/minor version number. -$OC_Version = array(9, 2, 0, 3); +$OC_Version = array(9, 2, 0, 4); // The human readable string $OC_VersionString = '11.0 alpha';