diff --git a/apps/files_versions/lib/Storage.php b/apps/files_versions/lib/Storage.php index 374b5f412ae4d..a6674ab244bff 100644 --- a/apps/files_versions/lib/Storage.php +++ b/apps/files_versions/lib/Storage.php @@ -37,8 +37,12 @@ * along with this program. If not, see * */ + namespace OCA\Files_Versions; +use OC\Files\Search\SearchBinaryOperator; +use OC\Files\Search\SearchComparison; +use OC\Files\Search\SearchQuery; use OC_User; use OC\Files\Filesystem; use OC\Files\View; @@ -46,11 +50,16 @@ use OCA\Files_Versions\Command\Expire; use OCA\Files_Versions\Events\CreateVersionEvent; use OCA\Files_Versions\Versions\IVersionManager; +use OCP\Files\FileInfo; +use OCP\Files\Folder; +use OCP\Files\IRootFolder; +use OCP\Files\Node; use OCP\Command\IBus; use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\IMimeTypeDetector; -use OCP\Files\IRootFolder; use OCP\Files\NotFoundException; +use OCP\Files\Search\ISearchBinaryOperator; +use OCP\Files\Search\ISearchComparison; use OCP\Files\StorageNotAvailableException; use OCP\IURLGenerator; use OCP\IUser; @@ -495,38 +504,54 @@ public static function getVersions($uid, $filename, $userFullPath = '') { /** * Expire versions that older than max version retention time + * * @param string $uid */ public static function expireOlderThanMaxForUser($uid) { + /** @var IRootFolder $root */ + $root = \OC::$server->get(IRootFolder::class); + try { + /** @var Folder $versionsRoot */ + $versionsRoot = $root->get('/' . $uid . '/files_versions'); + } catch (NotFoundException $e) { + return; + } + $expiration = self::getExpiration(); $threshold = $expiration->getMaxAgeAsTimestamp(); - $versions = self::getAllVersions($uid); - if (!$threshold || empty($versions['all'])) { + if (!$threshold) { return; } - $toDelete = []; - foreach (array_reverse($versions['all']) as $key => $version) { - if ((int)$version['version'] < $threshold) { - $toDelete[$key] = $version; - } else { - //Versions are sorted by time - nothing mo to iterate. - break; - } - } + $allVersions = $versionsRoot->search(new SearchQuery( + new SearchBinaryOperator(ISearchBinaryOperator::OPERATOR_NOT, [ + new SearchComparison(ISearchComparison::COMPARE_EQUAL, 'mimetype', FileInfo::MIMETYPE_FOLDER), + ]), + 0, + 0, + [] + )); - $view = new View('/' . $uid . '/files_versions'); - if (!empty($toDelete)) { - foreach ($toDelete as $version) { - \OC_Hook::emit('\OCP\Versions', 'preDelete', ['path' => $version['path'].'.v'.$version['version'], 'trigger' => self::DELETE_TRIGGER_RETENTION_CONSTRAINT]); - self::deleteVersion($view, $version['path'] . '.v' . $version['version']); - \OC_Hook::emit('\OCP\Versions', 'delete', ['path' => $version['path'].'.v'.$version['version'], 'trigger' => self::DELETE_TRIGGER_RETENTION_CONSTRAINT]); + /** @var Node[] $versions */ + $versions = array_filter($allVersions, function (Node $info) use ($threshold) { + $versionsBegin = strrpos($info->getName(), '.v'); + if ($versionsBegin === false) { + return false; } + $version = (int)substr($info->getName(), $versionsBegin + 2); + return $version < $threshold; + }); + + foreach ($versions as $version) { + \OC_Hook::emit('\OCP\Versions', 'preDelete', ['path' => $version->getInternalPath(), 'trigger' => self::DELETE_TRIGGER_RETENTION_CONSTRAINT]); + $version->delete(); + \OC_Hook::emit('\OCP\Versions', 'delete', ['path' => $version->getInternalPath(), 'trigger' => self::DELETE_TRIGGER_RETENTION_CONSTRAINT]); } } /** * translate a timestamp into a string like "5 days ago" + * * @param int $timestamp * @return string for example "5 days ago" */