diff options
Diffstat (limited to 'lib/private/Preview')
-rw-r--r-- | lib/private/Preview/Bundled.php | 1 | ||||
-rw-r--r-- | lib/private/Preview/Generator.php | 109 | ||||
-rw-r--r-- | lib/private/Preview/GeneratorHelper.php | 1 | ||||
-rw-r--r-- | lib/private/Preview/Imaginary.php | 1 | ||||
-rw-r--r-- | lib/private/Preview/Krita.php | 1 | ||||
-rw-r--r-- | lib/private/Preview/MimeIconProvider.php | 5 | ||||
-rw-r--r-- | lib/private/Preview/Movie.php | 15 | ||||
-rw-r--r-- | lib/private/Preview/SGI.php | 1 | ||||
-rw-r--r-- | lib/private/Preview/TGA.php | 1 | ||||
-rw-r--r-- | lib/private/Preview/Watcher.php | 3 | ||||
-rw-r--r-- | lib/private/Preview/WatcherConnector.php | 32 |
11 files changed, 90 insertions, 80 deletions
diff --git a/lib/private/Preview/Bundled.php b/lib/private/Preview/Bundled.php index 836dc4bd357..6100e8262a4 100644 --- a/lib/private/Preview/Bundled.php +++ b/lib/private/Preview/Bundled.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Preview/Generator.php b/lib/private/Preview/Generator.php index ef68c17b896..4a7341896ef 100644 --- a/lib/private/Preview/Generator.php +++ b/lib/private/Preview/Generator.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later @@ -11,6 +12,7 @@ use OCP\Files\IAppData; use OCP\Files\InvalidPathException; use OCP\Files\NotFoundException; use OCP\Files\NotPermittedException; +use OCP\Files\SimpleFS\InMemoryFile; use OCP\Files\SimpleFS\ISimpleFile; use OCP\Files\SimpleFS\ISimpleFolder; use OCP\IConfig; @@ -20,34 +22,20 @@ use OCP\IStreamImage; use OCP\Preview\BeforePreviewFetchedEvent; use OCP\Preview\IProviderV2; use OCP\Preview\IVersionedPreviewFile; +use Psr\Log\LoggerInterface; class Generator { public const SEMAPHORE_ID_ALL = 0x0a11; public const SEMAPHORE_ID_NEW = 0x07ea; - /** @var IPreview */ - private $previewManager; - /** @var IConfig */ - private $config; - /** @var IAppData */ - private $appData; - /** @var GeneratorHelper */ - private $helper; - /** @var IEventDispatcher */ - private $eventDispatcher; - public function __construct( - IConfig $config, - IPreview $previewManager, - IAppData $appData, - GeneratorHelper $helper, - IEventDispatcher $eventDispatcher, + private IConfig $config, + private IPreview $previewManager, + private IAppData $appData, + private GeneratorHelper $helper, + private IEventDispatcher $eventDispatcher, + private LoggerInterface $logger, ) { - $this->config = $config; - $this->previewManager = $previewManager; - $this->appData = $appData; - $this->helper = $helper; - $this->eventDispatcher = $eventDispatcher; } /** @@ -56,17 +44,19 @@ class Generator { * The cache is searched first and if nothing usable was found then a preview is * generated by one of the providers * - * @param File $file - * @param int $width - * @param int $height - * @param bool $crop - * @param string $mode - * @param string|null $mimeType * @return ISimpleFile * @throws NotFoundException * @throws \InvalidArgumentException if the preview would be invalid (in case the original image is invalid) */ - public function getPreview(File $file, $width = -1, $height = -1, $crop = false, $mode = IPreview::MODE_FILL, $mimeType = null) { + public function getPreview( + File $file, + int $width = -1, + int $height = -1, + bool $crop = false, + string $mode = IPreview::MODE_FILL, + ?string $mimeType = null, + bool $cacheResult = true, + ): ISimpleFile { $specification = [ 'width' => $width, 'height' => $height, @@ -83,23 +73,30 @@ class Generator { $mimeType, )); + $this->logger->debug('Requesting preview for {path} with width={width}, height={height}, crop={crop}, mode={mode}, mimeType={mimeType}', [ + 'path' => $file->getPath(), + 'width' => $width, + 'height' => $height, + 'crop' => $crop, + 'mode' => $mode, + 'mimeType' => $mimeType, + ]); + + // since we only ask for one preview, and the generate method return the last one it created, it returns the one we want - return $this->generatePreviews($file, [$specification], $mimeType); + return $this->generatePreviews($file, [$specification], $mimeType, $cacheResult); } /** * Generates previews of a file * - * @param File $file - * @param non-empty-array $specifications - * @param string $mimeType - * @return ISimpleFile the last preview that was generated * @throws NotFoundException * @throws \InvalidArgumentException if the preview would be invalid (in case the original image is invalid) */ - public function generatePreviews(File $file, array $specifications, $mimeType = null) { + public function generatePreviews(File $file, array $specifications, ?string $mimeType = null, bool $cacheResult = true): ISimpleFile { //Make sure that we can read the file if (!$file->isReadable()) { + $this->logger->warning('Cannot read file: {path}, skipping preview generation.', ['path' => $file->getPath()]); throw new NotFoundException('Cannot read file'); } @@ -121,6 +118,7 @@ class Generator { $maxPreviewImage = null; // only load the image when we need it if ($maxPreview->getSize() === 0) { $maxPreview->delete(); + $this->logger->error('Max preview generated for file {path} has size 0, deleting and throwing exception.', ['path' => $file->getPath()]); throw new NotFoundException('Max preview size 0, invalid!'); } @@ -167,7 +165,8 @@ class Generator { $maxPreviewImage = $this->helper->getImage($maxPreview); } - $preview = $this->generatePreview($previewFolder, $maxPreviewImage, $width, $height, $crop, $maxWidth, $maxHeight, $previewVersion); + $this->logger->debug('Cached preview not found for file {path}, generating a new preview.', ['path' => $file->getPath()]); + $preview = $this->generatePreview($previewFolder, $maxPreviewImage, $width, $height, $crop, $maxWidth, $maxHeight, $previewVersion, $cacheResult); // New file, augment our array $previewFiles[] = $preview; } @@ -335,6 +334,11 @@ class Generator { $previewConcurrency = $this->getNumConcurrentPreviews('preview_concurrency_new'); $sem = self::guardWithSemaphore(self::SEMAPHORE_ID_NEW, $previewConcurrency); try { + $this->logger->debug('Calling preview provider for {mimeType} with width={width}, height={height}', [ + 'mimeType' => $mimeType, + 'width' => $width, + 'height' => $height, + ]); $preview = $this->helper->getThumbnail($provider, $file, $width, $height); } finally { self::unguardWithSemaphore($sem); @@ -346,11 +350,10 @@ class Generator { $path = $this->generatePath($preview->width(), $preview->height(), $crop, $max, $preview->dataMimeType(), $prefix); try { - $file = $previewFolder->newFile($path); if ($preview instanceof IStreamImage) { - $file->putContent($preview->resource()); + return $previewFolder->newFile($path, $preview->resource()); } else { - $file->putContent($preview->data()); + return $previewFolder->newFile($path, $preview->data()); } } catch (NotPermittedException $e) { throw new NotFoundException(); @@ -485,19 +488,20 @@ class Generator { } /** - * @param ISimpleFolder $previewFolder - * @param ISimpleFile $maxPreview - * @param int $width - * @param int $height - * @param bool $crop - * @param int $maxWidth - * @param int $maxHeight - * @param string $prefix - * @return ISimpleFile * @throws NotFoundException * @throws \InvalidArgumentException if the preview would be invalid (in case the original image is invalid) */ - private function generatePreview(ISimpleFolder $previewFolder, IImage $maxPreview, $width, $height, $crop, $maxWidth, $maxHeight, $prefix) { + private function generatePreview( + ISimpleFolder $previewFolder, + IImage $maxPreview, + int $width, + int $height, + bool $crop, + int $maxWidth, + int $maxHeight, + string $prefix, + bool $cacheResult, + ): ISimpleFile { $preview = $maxPreview; if (!$preview->valid()) { throw new \InvalidArgumentException('Failed to generate preview, failed to load image'); @@ -534,12 +538,14 @@ class Generator { $path = $this->generatePath($width, $height, $crop, false, $preview->dataMimeType(), $prefix); try { - $file = $previewFolder->newFile($path); - $file->putContent($preview->data()); + if ($cacheResult) { + return $previewFolder->newFile($path, $preview->data()); + } else { + return new InMemoryFile($path, $preview->data()); + } } catch (NotPermittedException $e) { throw new NotFoundException(); } - return $file; } @@ -558,6 +564,7 @@ class Generator { $path = $this->generatePath($width, $height, $crop, false, $mimeType, $prefix); foreach ($files as $file) { if ($file->getName() === $path) { + $this->logger->debug('Found cached preview: {path}', ['path' => $path]); return $file; } } diff --git a/lib/private/Preview/GeneratorHelper.php b/lib/private/Preview/GeneratorHelper.php index 5f43c94b624..e914dcc2002 100644 --- a/lib/private/Preview/GeneratorHelper.php +++ b/lib/private/Preview/GeneratorHelper.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Preview/Imaginary.php b/lib/private/Preview/Imaginary.php index baa883f4bd9..d421da74ac8 100644 --- a/lib/private/Preview/Imaginary.php +++ b/lib/private/Preview/Imaginary.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Preview/Krita.php b/lib/private/Preview/Krita.php index 2e77c7befd2..e96fac993aa 100644 --- a/lib/private/Preview/Krita.php +++ b/lib/private/Preview/Krita.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Preview/MimeIconProvider.php b/lib/private/Preview/MimeIconProvider.php index 80545bd4063..d1963fe882b 100644 --- a/lib/private/Preview/MimeIconProvider.php +++ b/lib/private/Preview/MimeIconProvider.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later @@ -54,7 +55,7 @@ class MimeIconProvider implements IMimeIconProvider { return null; } - + private function searchfileName(string $fileName): ?string { // If the file exists in the current enabled legacy // custom theme, let's return it @@ -65,7 +66,7 @@ class MimeIconProvider implements IMimeIconProvider { return $this->urlGenerator->getAbsoluteURL($path); } } - + // Previously, we used to pass this through Theming // But it was only used to colour icons containing // 0082c9. Since with vue we moved to inline svg icons, diff --git a/lib/private/Preview/Movie.php b/lib/private/Preview/Movie.php index 46462dfa592..47895f999d8 100644 --- a/lib/private/Preview/Movie.php +++ b/lib/private/Preview/Movie.php @@ -54,10 +54,15 @@ class Movie extends ProviderV2 { $result = null; if ($this->useTempFile($file)) { - // try downloading 5 MB first as it's likely that the first frames are present there - // in some cases this doesn't work for example when the moov atom is at the - // end of the file, so if it fails we fall back to getting the full file - $sizeAttempts = [5242880, null]; + // Try downloading 5 MB first, as it's likely that the first frames are present there. + // In some cases this doesn't work, for example when the moov atom is at the + // end of the file, so if it fails we fall back to getting the full file. + // Unless the file is not local (e.g. S3) as we do not want to download the whole (e.g. 37Gb) file + if ($file->getStorage()->isLocal()) { + $sizeAttempts = [5242880, null]; + } else { + $sizeAttempts = [5242880]; + } } else { // size is irrelevant, only attempt once $sizeAttempts = [null]; @@ -161,8 +166,8 @@ class Movie extends ProviderV2 { $returnCode = -1; $output = ''; if (is_resource($proc)) { - $stdout = trim(stream_get_contents($pipes[1])); $stderr = trim(stream_get_contents($pipes[2])); + $stdout = trim(stream_get_contents($pipes[1])); $returnCode = proc_close($proc); $output = $stdout . $stderr; } diff --git a/lib/private/Preview/SGI.php b/lib/private/Preview/SGI.php index 06ea9c0c69a..78b1ea5828a 100644 --- a/lib/private/Preview/SGI.php +++ b/lib/private/Preview/SGI.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Preview/TGA.php b/lib/private/Preview/TGA.php index 62e5aadc2af..675907b4e49 100644 --- a/lib/private/Preview/TGA.php +++ b/lib/private/Preview/TGA.php @@ -1,4 +1,5 @@ <?php + /** * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later diff --git a/lib/private/Preview/Watcher.php b/lib/private/Preview/Watcher.php index abddd7b5acb..21f040d8342 100644 --- a/lib/private/Preview/Watcher.php +++ b/lib/private/Preview/Watcher.php @@ -8,6 +8,7 @@ declare(strict_types=1); */ namespace OC\Preview; +use OCP\Files\FileInfo; use OCP\Files\Folder; use OCP\Files\IAppData; use OCP\Files\Node; @@ -37,7 +38,7 @@ class Watcher { $this->deleteNode($node); } - protected function deleteNode(Node $node) { + protected function deleteNode(FileInfo $node) { // We only handle files if ($node instanceof Folder) { return; diff --git a/lib/private/Preview/WatcherConnector.php b/lib/private/Preview/WatcherConnector.php index ae2a136ca78..c34dd1dde4d 100644 --- a/lib/private/Preview/WatcherConnector.php +++ b/lib/private/Preview/WatcherConnector.php @@ -9,43 +9,33 @@ declare(strict_types=1); namespace OC\Preview; use OC\SystemConfig; +use OCA\Files_Versions\Events\VersionRestoredEvent; +use OCP\EventDispatcher\IEventDispatcher; use OCP\Files\IRootFolder; use OCP\Files\Node; class WatcherConnector { - /** @var IRootFolder */ - private $root; - - /** @var SystemConfig */ - private $config; - - /** - * WatcherConnector constructor. - * - * @param IRootFolder $root - * @param SystemConfig $config - */ - public function __construct(IRootFolder $root, - SystemConfig $config) { - $this->root = $root; - $this->config = $config; + public function __construct( + private IRootFolder $root, + private SystemConfig $config, + private IEventDispatcher $dispatcher, + ) { } - /** - * @return Watcher - */ private function getWatcher(): Watcher { return \OCP\Server::get(Watcher::class); } - public function connectWatcher() { + public function connectWatcher(): void { // Do not connect if we are not setup yet! if ($this->config->getValue('instanceid', null) !== null) { $this->root->listen('\OC\Files', 'postWrite', function (Node $node) { $this->getWatcher()->postWrite($node); }); - \OC_Hook::connect('\OCP\Versions', 'rollback', $this->getWatcher(), 'versionRollback'); + $this->dispatcher->addListener(VersionRestoredEvent::class, function (VersionRestoredEvent $event) { + $this->getWatcher()->versionRollback(['node' => $event->getVersion()->getSourceFile()]); + }); } } } |