Signed-off-by: Louis Chemineau <louis@chmn.me>tags/v28.0.4rc1
@@ -24,6 +24,7 @@ | |||
*/ | |||
namespace OCA\Files_Versions\Command; | |||
use OCA\Files_Versions\Db\VersionsMapper; | |||
use OCP\Files\IRootFolder; | |||
use OCP\IUserBackend; | |||
use OCP\IUserManager; | |||
@@ -37,6 +38,7 @@ class CleanUp extends Command { | |||
public function __construct( | |||
protected IRootFolder $rootFolder, | |||
protected IUserManager $userManager, | |||
protected VersionsMapper $versionMapper, | |||
) { | |||
parent::__construct(); | |||
} | |||
@@ -119,6 +121,9 @@ class CleanUp extends Command { | |||
\OC_Util::tearDownFS(); | |||
\OC_Util::setupFS($user); | |||
$userHomeStorageId = $this->rootFolder->getUserFolder($user)->getStorage()->getCache()->getNumericStorageId(); | |||
$this->versionMapper->deleteAllVersionsForUser($userHomeStorageId, $path); | |||
$fullPath = '/' . $user . '/files_versions' . ($path ? '/' . $path : ''); | |||
if ($this->rootFolder->nodeExists($fullPath)) { | |||
$this->rootFolder->get($fullPath)->delete(); |
@@ -27,6 +27,7 @@ declare(strict_types=1); | |||
namespace OCA\Files_Versions\Db; | |||
use OCP\AppFramework\Db\QBMapper; | |||
use OCP\DB\QueryBuilder\IQueryBuilder; | |||
use OCP\IDBConnection; | |||
/** | |||
@@ -83,4 +84,38 @@ class VersionsMapper extends QBMapper { | |||
->where($qb->expr()->eq('file_id', $qb->createNamedParameter($fileId))) | |||
->executeStatement(); | |||
} | |||
public function deleteAllVersionsForUser(int $storageId, string $path = null): void { | |||
$fileIdsGenerator = $this->getFileIdsGenerator($storageId, $path); | |||
$versionEntitiesDeleteQuery = $this->db->getQueryBuilder(); | |||
$versionEntitiesDeleteQuery->delete($this->getTableName()) | |||
->where($versionEntitiesDeleteQuery->expr()->in('file_id', $versionEntitiesDeleteQuery->createParameter('file_ids'))); | |||
foreach ($fileIdsGenerator as $fileIds) { | |||
$versionEntitiesDeleteQuery->setParameter('file_ids', $fileIds, IQueryBuilder::PARAM_INT_ARRAY); | |||
$versionEntitiesDeleteQuery->executeStatement(); | |||
} | |||
} | |||
private function getFileIdsGenerator(int $storageId, ?string $path): \Generator { | |||
$offset = 0; | |||
do { | |||
$filesIdsSelect = $this->db->getQueryBuilder(); | |||
$filesIdsSelect->select('fileid') | |||
->from('filecache') | |||
->where($filesIdsSelect->expr()->eq('storage', $filesIdsSelect->createNamedParameter($storageId, IQueryBuilder::PARAM_STR))) | |||
->andWhere($filesIdsSelect->expr()->like('path', $filesIdsSelect->createNamedParameter('files' . ($path ? '/' . $this->db->escapeLikeParameter($path) : '') . '/%', IQueryBuilder::PARAM_STR))) | |||
->andWhere($filesIdsSelect->expr()->gt('fileid', $filesIdsSelect->createParameter('offset'))) | |||
->setMaxResults(1000) | |||
->orderBy('fileid', 'ASC'); | |||
$filesIdsSelect->setParameter('offset', $offset, IQueryBuilder::PARAM_INT); | |||
$result = $filesIdsSelect->executeQuery(); | |||
$fileIds = $result->fetchAll(\PDO::FETCH_COLUMN); | |||
$offset = end($fileIds); | |||
yield $fileIds; | |||
} while (!empty($fileIds)); | |||
} | |||
} |
@@ -27,7 +27,10 @@ namespace OCA\Files_Versions\Tests\Command; | |||
use OC\User\Manager; | |||
use OCA\Files_Versions\Command\CleanUp; | |||
use OCP\Files\Cache\ICache; | |||
use OCP\Files\Folder; | |||
use OCP\Files\IRootFolder; | |||
use OCP\Files\Storage\IStorage; | |||
use Test\TestCase; | |||
/** | |||
@@ -48,6 +51,9 @@ class CleanupTest extends TestCase { | |||
/** @var \PHPUnit\Framework\MockObject\MockObject | IRootFolder */ | |||
protected $rootFolder; | |||
/** @var \PHPUnit\Framework\MockObject\MockObject | VersionsMapper */ | |||
protected $versionMapper; | |||
protected function setUp(): void { | |||
parent::setUp(); | |||
@@ -55,9 +61,10 @@ class CleanupTest extends TestCase { | |||
->disableOriginalConstructor()->getMock(); | |||
$this->userManager = $this->getMockBuilder('OC\User\Manager') | |||
->disableOriginalConstructor()->getMock(); | |||
$this->versionMapper = $this->getMockBuilder('OCA\Files_Versions\Db\VersionsMapper') | |||
->disableOriginalConstructor()->getMock(); | |||
$this->cleanup = new CleanUp($this->rootFolder, $this->userManager); | |||
$this->cleanup = new CleanUp($this->rootFolder, $this->userManager, $this->versionMapper); | |||
} | |||
/** | |||
@@ -70,6 +77,21 @@ class CleanupTest extends TestCase { | |||
->with('/testUser/files_versions') | |||
->willReturn($nodeExists); | |||
$userFolder = $this->createMock(Folder::class); | |||
$userHomeStorage = $this->createMock(IStorage::class); | |||
$userHomeStorageCache = $this->createMock(ICache::class); | |||
$this->rootFolder->expects($this->once()) | |||
->method('getUserFolder') | |||
->willReturn($userFolder); | |||
$userFolder->expects($this->once()) | |||
->method('getStorage') | |||
->willReturn($userHomeStorage); | |||
$userHomeStorage->expects($this->once()) | |||
->method('getCache') | |||
->willReturn($userHomeStorageCache); | |||
$userHomeStorageCache->expects($this->once()) | |||
->method('getNumericStorageId') | |||
->willReturn(1); | |||
if ($nodeExists) { | |||
$this->rootFolder->expects($this->once()) | |||
@@ -104,7 +126,7 @@ class CleanupTest extends TestCase { | |||
$instance = $this->getMockBuilder('OCA\Files_Versions\Command\CleanUp') | |||
->setMethods(['deleteVersions']) | |||
->setConstructorArgs([$this->rootFolder, $this->userManager]) | |||
->setConstructorArgs([$this->rootFolder, $this->userManager, $this->versionMapper]) | |||
->getMock(); | |||
$instance->expects($this->exactly(count($userIds))) | |||
->method('deleteVersions') | |||
@@ -136,7 +158,7 @@ class CleanupTest extends TestCase { | |||
$instance = $this->getMockBuilder('OCA\Files_Versions\Command\CleanUp') | |||
->setMethods(['deleteVersions']) | |||
->setConstructorArgs([$this->rootFolder, $this->userManager]) | |||
->setConstructorArgs([$this->rootFolder, $this->userManager, $this->versionMapper]) | |||
->getMock(); | |||
$backend = $this->getMockBuilder(\OCP\UserInterface::class) |