diff --git a/apps/files_sharing/tests/Controller/ShareControllerTest.php b/apps/files_sharing/tests/Controller/ShareControllerTest.php
index 32fd0f09637b9..28d2622667304 100644
--- a/apps/files_sharing/tests/Controller/ShareControllerTest.php
+++ b/apps/files_sharing/tests/Controller/ShareControllerTest.php
@@ -384,6 +384,7 @@ public function testShowFileDropShare(): void {
$file->method('isReadable')->willReturn(true);
$file->method('isShareable')->willReturn(true);
$file->method('getId')->willReturn(1234);
+ $file->method('getMimetype')->willReturn('text/plain');
$file->method('getName')->willReturn($filename);
$accountName = $this->createMock(IAccountProperty::class);
diff --git a/build/psalm-baseline.xml b/build/psalm-baseline.xml
index 422d886658ad4..7d0d0c4eabe0e 100644
--- a/build/psalm-baseline.xml
+++ b/build/psalm-baseline.xml
@@ -4119,14 +4119,6 @@
-
-
-
-
-
-
-
-
diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php
index add490d2b0681..d1cb05b1b3f12 100644
--- a/lib/composer/composer/autoload_classmap.php
+++ b/lib/composer/composer/autoload_classmap.php
@@ -720,7 +720,6 @@
'OCP\\PreConditionNotMetException' => $baseDir . '/lib/public/PreConditionNotMetException.php',
'OCP\\Preview\\BeforePreviewFetchedEvent' => $baseDir . '/lib/public/Preview/BeforePreviewFetchedEvent.php',
'OCP\\Preview\\IMimeIconProvider' => $baseDir . '/lib/public/Preview/IMimeIconProvider.php',
- 'OCP\\Preview\\IProvider' => $baseDir . '/lib/public/Preview/IProvider.php',
'OCP\\Preview\\IProviderV2' => $baseDir . '/lib/public/Preview/IProviderV2.php',
'OCP\\Preview\\IVersionedPreviewFile' => $baseDir . '/lib/public/Preview/IVersionedPreviewFile.php',
'OCP\\Profile\\BeforeTemplateRenderedEvent' => $baseDir . '/lib/public/Profile/BeforeTemplateRenderedEvent.php',
@@ -1907,8 +1906,6 @@
'OC\\Preview\\Photoshop' => $baseDir . '/lib/private/Preview/Photoshop.php',
'OC\\Preview\\Postscript' => $baseDir . '/lib/private/Preview/Postscript.php',
'OC\\Preview\\PreviewService' => $baseDir . '/lib/private/Preview/PreviewService.php',
- 'OC\\Preview\\Provider' => $baseDir . '/lib/private/Preview/Provider.php',
- 'OC\\Preview\\ProviderV1Adapter' => $baseDir . '/lib/private/Preview/ProviderV1Adapter.php',
'OC\\Preview\\ProviderV2' => $baseDir . '/lib/private/Preview/ProviderV2.php',
'OC\\Preview\\SGI' => $baseDir . '/lib/private/Preview/SGI.php',
'OC\\Preview\\SVG' => $baseDir . '/lib/private/Preview/SVG.php',
diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php
index 6c6507f8b22a0..d1a85530aca2a 100644
--- a/lib/composer/composer/autoload_static.php
+++ b/lib/composer/composer/autoload_static.php
@@ -11,32 +11,32 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
);
public static $prefixLengthsPsr4 = array (
- 'O' =>
+ 'O' =>
array (
'OC\\Core\\' => 8,
'OC\\' => 3,
'OCP\\' => 4,
),
- 'N' =>
+ 'N' =>
array (
'NCU\\' => 4,
),
);
public static $prefixDirsPsr4 = array (
- 'OC\\Core\\' =>
+ 'OC\\Core\\' =>
array (
0 => __DIR__ . '/../../..' . '/core',
),
- 'OC\\' =>
+ 'OC\\' =>
array (
0 => __DIR__ . '/../../..' . '/lib/private',
),
- 'OCP\\' =>
+ 'OCP\\' =>
array (
0 => __DIR__ . '/../../..' . '/lib/public',
),
- 'NCU\\' =>
+ 'NCU\\' =>
array (
0 => __DIR__ . '/../../..' . '/lib/unstable',
),
@@ -761,7 +761,6 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OCP\\PreConditionNotMetException' => __DIR__ . '/../../..' . '/lib/public/PreConditionNotMetException.php',
'OCP\\Preview\\BeforePreviewFetchedEvent' => __DIR__ . '/../../..' . '/lib/public/Preview/BeforePreviewFetchedEvent.php',
'OCP\\Preview\\IMimeIconProvider' => __DIR__ . '/../../..' . '/lib/public/Preview/IMimeIconProvider.php',
- 'OCP\\Preview\\IProvider' => __DIR__ . '/../../..' . '/lib/public/Preview/IProvider.php',
'OCP\\Preview\\IProviderV2' => __DIR__ . '/../../..' . '/lib/public/Preview/IProviderV2.php',
'OCP\\Preview\\IVersionedPreviewFile' => __DIR__ . '/../../..' . '/lib/public/Preview/IVersionedPreviewFile.php',
'OCP\\Profile\\BeforeTemplateRenderedEvent' => __DIR__ . '/../../..' . '/lib/public/Profile/BeforeTemplateRenderedEvent.php',
@@ -1948,8 +1947,6 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
'OC\\Preview\\Photoshop' => __DIR__ . '/../../..' . '/lib/private/Preview/Photoshop.php',
'OC\\Preview\\Postscript' => __DIR__ . '/../../..' . '/lib/private/Preview/Postscript.php',
'OC\\Preview\\PreviewService' => __DIR__ . '/../../..' . '/lib/private/Preview/PreviewService.php',
- 'OC\\Preview\\Provider' => __DIR__ . '/../../..' . '/lib/private/Preview/Provider.php',
- 'OC\\Preview\\ProviderV1Adapter' => __DIR__ . '/../../..' . '/lib/private/Preview/ProviderV1Adapter.php',
'OC\\Preview\\ProviderV2' => __DIR__ . '/../../..' . '/lib/private/Preview/ProviderV2.php',
'OC\\Preview\\SGI' => __DIR__ . '/../../..' . '/lib/private/Preview/SGI.php',
'OC\\Preview\\SVG' => __DIR__ . '/../../..' . '/lib/private/Preview/SVG.php',
diff --git a/lib/private/Preview/Generator.php b/lib/private/Preview/Generator.php
index 82c4ec88363f2..8707c257e7b8a 100644
--- a/lib/private/Preview/Generator.php
+++ b/lib/private/Preview/Generator.php
@@ -22,7 +22,6 @@
use OCP\IPreview;
use OCP\IStreamImage;
use OCP\Preview\BeforePreviewFetchedEvent;
-use OCP\Preview\IProviderV2;
use OCP\Preview\IVersionedPreviewFile;
use Psr\Log\LoggerInterface;
@@ -322,7 +321,7 @@ private function generateProviderPreview(File $file, int $width, int $height, bo
foreach ($providers as $providerClosure) {
$provider = $this->helper->getProvider($providerClosure);
- if (!($provider instanceof IProviderV2)) {
+ if (!$provider) {
continue;
}
diff --git a/lib/private/Preview/GeneratorHelper.php b/lib/private/Preview/GeneratorHelper.php
index 7114a412e36ea..7849cb3ba38c7 100644
--- a/lib/private/Preview/GeneratorHelper.php
+++ b/lib/private/Preview/GeneratorHelper.php
@@ -7,38 +7,18 @@
namespace OC\Preview;
use OCP\Files\File;
-use OCP\Files\IRootFolder;
use OCP\Files\SimpleFS\ISimpleFile;
-use OCP\IConfig;
use OCP\IImage;
use OCP\Image as OCPImage;
-use OCP\Preview\IProvider;
+use OCP\IPreview;
use OCP\Preview\IProviderV2;
/**
* Very small wrapper class to make the generator fully unit testable
+ * @psalm-import-type ProviderClosure from IPreview
*/
class GeneratorHelper {
- /** @var IRootFolder */
- private $rootFolder;
-
- /** @var IConfig */
- private $config;
-
- public function __construct(IRootFolder $rootFolder, IConfig $config) {
- $this->rootFolder = $rootFolder;
- $this->config = $config;
- }
-
- /**
- * @param IProviderV2 $provider
- * @param File $file
- * @param int $maxWidth
- * @param int $maxHeight
- *
- * @return bool|IImage
- */
- public function getThumbnail(IProviderV2 $provider, File $file, $maxWidth, $maxHeight, bool $crop = false) {
+ public function getThumbnail(IProviderV2 $provider, File $file, int $maxWidth, int $maxHeight, bool $crop = false): IImage|false {
if ($provider instanceof Imaginary) {
return $provider->getCroppedThumbnail($file, $maxWidth, $maxHeight, $crop) ?? false;
}
@@ -52,14 +32,9 @@ public function getImage(ISimpleFile $maxPreview): IImage {
}
/**
- * @param callable $providerClosure
- * @return IProviderV2
+ * @param \Closure|string $providerClosure (string is only authorized in unit tests)
*/
- public function getProvider($providerClosure) {
- $provider = $providerClosure();
- if ($provider instanceof IProvider) {
- $provider = new ProviderV1Adapter($provider);
- }
- return $provider;
+ public function getProvider(\Closure|string $providerClosure): IProviderV2|false {
+ return $providerClosure();
}
}
diff --git a/lib/private/Preview/Provider.php b/lib/private/Preview/Provider.php
deleted file mode 100644
index 26f0ac09f084b..0000000000000
--- a/lib/private/Preview/Provider.php
+++ /dev/null
@@ -1,50 +0,0 @@
-options = $options;
- }
-
- /**
- * @return string Regex with the mimetypes that are supported by this provider
- */
- abstract public function getMimeType();
-
- /**
- * Check if a preview can be generated for $path
- *
- * @param \OCP\Files\FileInfo $file
- * @return bool
- */
- public function isAvailable(\OCP\Files\FileInfo $file) {
- return true;
- }
-
- /**
- * Generates thumbnail which fits in $maxX and $maxY and keeps the aspect ratio, for file at path $path
- *
- * @param string $path Path of file
- * @param int $maxX The maximum X size of the thumbnail. It can be smaller depending on the shape of the image
- * @param int $maxY The maximum Y size of the thumbnail. It can be smaller depending on the shape of the image
- * @param bool $scalingup Disable/Enable upscaling of previews
- * @param \OC\Files\View $fileview fileview object of user folder
- * @return bool|\OCP\IImage false if no preview was generated
- */
- abstract public function getThumbnail($path, $maxX, $maxY, $scalingup, $fileview);
-}
diff --git a/lib/private/Preview/ProviderV1Adapter.php b/lib/private/Preview/ProviderV1Adapter.php
deleted file mode 100644
index ba8826ef765c3..0000000000000
--- a/lib/private/Preview/ProviderV1Adapter.php
+++ /dev/null
@@ -1,45 +0,0 @@
-providerV1 = $providerV1;
- }
-
- public function getMimeType(): string {
- return (string)$this->providerV1->getMimeType();
- }
-
- public function isAvailable(FileInfo $file): bool {
- return (bool)$this->providerV1->isAvailable($file);
- }
-
- public function getThumbnail(File $file, int $maxX, int $maxY): ?IImage {
- [$view, $path] = $this->getViewAndPath($file);
- $thumbnail = $this->providerV1->getThumbnail($path, $maxX, $maxY, false, $view);
- return $thumbnail === false ? null: $thumbnail;
- }
-
- private function getViewAndPath(File $file) {
- $view = new View(dirname($file->getPath()));
- $path = $file->getName();
-
- return [$view, $path];
- }
-}
diff --git a/lib/private/PreviewManager.php b/lib/private/PreviewManager.php
index fb88409287260..2e99dee19b1db 100644
--- a/lib/private/PreviewManager.php
+++ b/lib/private/PreviewManager.php
@@ -7,13 +7,13 @@
*/
namespace OC;
+use Closure;
use OC\AppFramework\Bootstrap\Coordinator;
use OC\Preview\Db\PreviewMapper;
use OC\Preview\Generator;
use OC\Preview\GeneratorHelper;
use OC\Preview\IMagickSupport;
use OC\Preview\Storage\StorageFactory;
-use OCP\AppFramework\QueryException;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\File;
use OCP\Files\IRootFolder;
@@ -24,10 +24,14 @@
use OCP\IPreview;
use OCP\Preview\IProviderV2;
use Psr\Container\ContainerInterface;
+use Psr\Container\NotFoundExceptionInterface;
use Psr\Log\LoggerInterface;
use function array_key_exists;
+/**
+ * @psalm-import-type ProviderClosure from IPreview
+ */
class PreviewManager implements IPreview {
protected IConfig $config;
protected IRootFolder $rootFolder;
@@ -36,10 +40,14 @@ class PreviewManager implements IPreview {
private GeneratorHelper $helper;
protected bool $providerListDirty = false;
protected bool $registeredCoreProviders = false;
+ /**
+ * @var array> $providers
+ */
protected array $providers = [];
/** @var array mime type => support status */
protected array $mimeTypeSupportMap = [];
+ /** @var ?list> $defaultProviders */
protected ?array $defaultProviders = null;
protected ?string $userId;
private Coordinator $bootstrapCoordinator;
@@ -81,13 +89,10 @@ public function __construct(
* In order to improve lazy loading a closure can be registered which will be
* called in case preview providers are actually requested
*
- * $callable has to return an instance of \OCP\Preview\IProvider or \OCP\Preview\IProviderV2
- *
* @param string $mimeTypeRegex Regex with the mime types that are supported by this provider
- * @param \Closure $callable
- * @return void
+ * @param ProviderClosure $callable
*/
- public function registerProvider($mimeTypeRegex, \Closure $callable): void {
+ public function registerProvider(string $mimeTypeRegex, Closure $callable): void {
if (!$this->enablePreviews) {
return;
}
@@ -131,10 +136,7 @@ private function getGenerator(): Generator {
$this->generator = new Generator(
$this->config,
$this,
- new GeneratorHelper(
- $this->rootFolder,
- $this->config
- ),
+ new GeneratorHelper(),
$this->eventDispatcher,
$this->container->get(LoggerInterface::class),
$this->container->get(PreviewMapper::class),
@@ -146,11 +148,11 @@ private function getGenerator(): Generator {
public function getPreview(
File $file,
- $width = -1,
- $height = -1,
- $crop = false,
- $mode = IPreview::MODE_FILL,
- $mimeType = null,
+ int $width = -1,
+ int $height = -1,
+ bool $crop = false,
+ string $mode = IPreview::MODE_FILL,
+ ?string $mimeType = null,
bool $cacheResult = true,
): ISimpleFile {
$this->throwIfPreviewsDisabled($file, $mimeType);
@@ -168,26 +170,18 @@ public function getPreview(
/**
* Generates previews of a file
*
- * @param File $file
* @param 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)
* @since 19.0.0
*/
- public function generatePreviews(File $file, array $specifications, $mimeType = null) {
+ public function generatePreviews(File $file, array $specifications, ?string $mimeType = null): ISimpleFile {
$this->throwIfPreviewsDisabled($file, $mimeType);
return $this->getGenerator()->generatePreviews($file, $specifications, $mimeType);
}
- /**
- * returns true if the passed mime type is supported
- *
- * @param string $mimeType
- * @return boolean
- */
- public function isMimeSupported($mimeType = '*') {
+ public function isMimeSupported(string $mimeType = '*'): bool {
if (!$this->enablePreviews) {
return false;
}
@@ -209,9 +203,6 @@ public function isMimeSupported($mimeType = '*') {
return false;
}
- /**
- * Check if a preview can be generated for a file
- */
public function isAvailable(\OCP\Files\FileInfo $file, ?string $mimeType = null): bool {
if (!$this->enablePreviews) {
return false;
@@ -233,10 +224,9 @@ public function isAvailable(\OCP\Files\FileInfo $file, ?string $mimeType = null)
if (preg_match($supportedMimeType, $fileMimeType)) {
foreach ($providers as $providerClosure) {
$provider = $this->helper->getProvider($providerClosure);
- if (!($provider instanceof IProviderV2)) {
+ if (!$provider) {
continue;
}
-
if ($provider->isAvailable($file)) {
return true;
}
@@ -275,9 +265,9 @@ public function isAvailable(\OCP\Files\FileInfo $file, ?string $mimeType = null)
* - OC\Preview\SVG
* - OC\Preview\TIFF
*
- * @return array
+ * @return list>
*/
- protected function getEnabledDefaultProvider() {
+ protected function getEnabledDefaultProvider(): array {
if ($this->defaultProviders !== null) {
return $this->defaultProviders;
}
@@ -302,17 +292,16 @@ protected function getEnabledDefaultProvider() {
if (in_array(Preview\Image::class, $this->defaultProviders)) {
$this->defaultProviders = array_merge($this->defaultProviders, $imageProviders);
}
- $this->defaultProviders = array_unique($this->defaultProviders);
- return $this->defaultProviders;
+ $this->defaultProviders = array_values(array_unique($this->defaultProviders));
+ /** @var list> $providers */
+ $providers = $this->defaultProviders;
+ return $providers;
}
/**
* Register the default providers (if enabled)
- *
- * @param string $class
- * @param string $mimeType
*/
- protected function registerCoreProvider($class, $mimeType, $options = []) {
+ protected function registerCoreProvider(string $class, string $mimeType, array $options = []): void {
if (in_array(trim($class, '\\'), $this->getEnabledDefaultProvider())) {
$this->registerProvider($mimeType, function () use ($class, $options) {
return new $class($options);
@@ -323,7 +312,7 @@ protected function registerCoreProvider($class, $mimeType, $options = []) {
/**
* Register the default providers (if enabled)
*/
- protected function registerCoreProviders() {
+ protected function registerCoreProviders(): void {
if ($this->registeredCoreProviders) {
return;
}
@@ -440,11 +429,11 @@ private function registerBootstrapProviders(): void {
}
$this->loadedBootstrapProviders[$key] = null;
- $this->registerProvider($provider->getMimeTypeRegex(), function () use ($provider) {
+ $this->registerProvider($provider->getMimeTypeRegex(), function () use ($provider): IProviderV2|false {
try {
return $this->container->get($provider->getService());
- } catch (QueryException $e) {
- return null;
+ } catch (NotFoundExceptionInterface) {
+ return false;
}
});
}
diff --git a/lib/public/IPreview.php b/lib/public/IPreview.php
index 3c9eadd45774a..56c31430f4959 100644
--- a/lib/public/IPreview.php
+++ b/lib/public/IPreview.php
@@ -10,14 +10,20 @@
namespace OCP;
+use Closure;
+use OCP\AppFramework\Attribute\Consumable;
use OCP\Files\File;
+use OCP\Files\FileInfo;
use OCP\Files\NotFoundException;
use OCP\Files\SimpleFS\ISimpleFile;
+use OCP\Preview\IProviderV2;
/**
* This class provides functions to render and show thumbnails and previews of files
* @since 6.0.0
+ * @psalm-type ProviderClosure = Closure():(IProviderV2|false)
*/
+#[Consumable(since: '6.0.0')]
interface IPreview {
/**
* @since 11.0.0
@@ -33,31 +39,27 @@ interface IPreview {
* In order to improve lazy loading a closure can be registered which will be
* called in case preview providers are actually requested
*
- * $callable has to return an instance of \OCP\Preview\IProvider
- *
* @param string $mimeTypeRegex Regex with the mime types that are supported by this provider
- * @param \Closure $callable
- * @return void
+ * @param ProviderClosure $callable
* @since 8.1.0
* @see \OCP\AppFramework\Bootstrap\IRegistrationContext::registerPreviewProvider
*
* @deprecated 23.0.0 Register your provider via the IRegistrationContext when booting the app
*/
- public function registerProvider($mimeTypeRegex, \Closure $callable);
+ public function registerProvider(string $mimeTypeRegex, Closure $callable): void;
/**
* Get all providers
- * @return array
+ * @return array>
* @since 8.1.0
*/
- public function getProviders();
+ public function getProviders(): array;
/**
* Does the manager have any providers
- * @return bool
* @since 8.1.0
*/
- public function hasProviders();
+ public function hasProviders(): bool;
/**
* Returns a preview of a file
@@ -65,50 +67,42 @@ public function hasProviders();
* 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 IPreview::MODE_* $mode
* @param string $mimeType To force a given mimetype for the file (files_versions needs this)
- * @param bool $cacheResult Whether or not to cache the preview on the filesystem. Default to true. Can be useful to set to false to limit the amount of stored previews.
+ * @param bool $cacheResult Whether to cache the preview on the filesystem. Default to true. Can be useful to set to false to limit the amount of stored previews.
* @return ISimpleFile
* @throws NotFoundException
* @throws \InvalidArgumentException if the preview would be invalid (in case the original image is invalid)
* @since 11.0.0 - \InvalidArgumentException was added in 12.0.0
* @since 32.0.0 - getPreview($cacheResult) added the $cacheResult argument to the signature
*/
- public function getPreview(File $file, $width = -1, $height = -1, $crop = false, $mode = IPreview::MODE_FILL, $mimeType = null, bool $cacheResult = true);
+ 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;
/**
* Returns true if the passed mime type is supported
- * @param string $mimeType
- * @return boolean
+ * @param string $mimeType A glob
* @since 6.0.0
*/
- public function isMimeSupported($mimeType = '*');
+ public function isMimeSupported(string $mimeType = '*'): bool;
/**
* Check if a preview can be generated for a file
*
- * @param \OCP\Files\FileInfo $file
+ * @param FileInfo $file
* @param string|null $mimeType To force a given mimetype for the file
- * @return bool
* @since 8.0.0
* @since 32.0.0 - isAvailable($mimeType) added the $mimeType argument to the signature
*/
- public function isAvailable(\OCP\Files\FileInfo $file, ?string $mimeType = null);
+ public function isAvailable(FileInfo $file, ?string $mimeType = null): bool;
/**
* Generates previews of a file
*
- * @param File $file
* @param 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)
* @since 19.0.0
*/
- public function generatePreviews(File $file, array $specifications, $mimeType = null);
+ public function generatePreviews(File $file, array $specifications, ?string $mimeType = null): ISimpleFile;
}
diff --git a/lib/public/Preview/IProvider.php b/lib/public/Preview/IProvider.php
deleted file mode 100644
index b06acfbbe5d11..0000000000000
--- a/lib/public/Preview/IProvider.php
+++ /dev/null
@@ -1,44 +0,0 @@
-