setTimeSensitivity(self::TIME_INSENSITIVE); $this->setInterval(24 * 60 * 60); $this->previewRootPath = 'appdata_' . $this->config->getSystemValueString('instanceid') . '/preview/'; } #[Override] protected function run(mixed $argument): void { if ($this->appConfig->getValueBool('core', 'previewMovedDone')) { return; } $storage = $this->rootFolder->getMountPoint()->getStorage(); if ($storage === null) { $this->appConfig->setValueBool('core', 'previewMovedDone', true); return; } $cache = $storage->getCache(); $previewRootId = $cache->getId(rtrim($this->previewRootPath, '/')); if ($previewRootId === -1) { // No previews have ever been generated on this instance. $this->appConfig->setValueBool('core', 'previewMovedDone', true); return; } $startTime = time(); // Walk the preview folder tree via the `parent` column, which is indexed on // every supported database platform. // // Depth from the preview root tells us which structure a leaf folder holds: // - depth 1: legacy flat structure, e.g. preview//.png // - depth 8: hierarchical structure, e.g. preview/a/b/c/d/e/f/g//.png $foldersToVisit = [[$previewRootId, '', 0]]; while ($foldersToVisit !== []) { [$folderId, $folderName, $depth] = array_pop($foldersToVisit); // Collect the actual preview files here so migrateFileId() doesn't need to // list this folder's contents a second time. $previewEntries = []; foreach ($cache->getFolderContentsById($folderId) as $entry) { if ($entry->getMimeType() === FileInfo::MIMETYPE_FOLDER) { $foldersToVisit[] = [$entry->getId(), $entry->getName(), $depth + 1]; } else { $previewEntries[] = $entry; } } if ($previewEntries === [] || !ctype_digit($folderName)) { continue; } try { $this->migrationService->migrateFileId((int)$folderName, flatPath: $depth === 1, entries: $previewEntries); } catch (\Exception $e) { $this->logger->error('Failed to migrate preview with fileId: ' . $folderName, [ 'exception' => $e, ]); } // Stop if execution time is more than one hour. if (time() - $startTime > 3600) { return; } } $this->appConfig->setValueBool('core', 'previewMovedDone', true); } }