From 0b37d5aea3c1bf4a30dece3ab7dfe838f50d36f2 Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Thu, 12 Mar 2015 10:48:52 +0100 Subject: [PATCH] Move default provider registration to preview manager --- lib/private/preview.php | 215 +++++---------------------------- lib/private/previewmanager.php | 170 +++++++++++++++++++++++++- lib/public/ipreview.php | 12 ++ 3 files changed, 214 insertions(+), 183 deletions(-) diff --git a/lib/private/preview.php b/lib/private/preview.php index f55cf280b3..ced76c14d1 100644 --- a/lib/private/preview.php +++ b/lib/private/preview.php @@ -50,11 +50,6 @@ class Preview { */ private $preview; - //preview providers - static private $providers = array(); - static private $registeredProviders = array(); - static private $enabledProviders = array(); - /** * @var \OCP\Files\FileInfo */ @@ -95,11 +90,7 @@ class Preview { $this->preview = null; //check if there are preview backends - if (empty(self::$providers)) { - self::initProviders(); - } - - if (empty(self::$providers) && \OC::$server->getConfig()->getSystemValue('enable_previews', true)) { + if (!\OC::$server->getPreviewManager()->hasProviders() && \OC::$server->getConfig()->getSystemValue('enable_previews', true)) { \OC_Log::write('core', 'No preview providers exist', \OC_Log::ERROR); throw new \Exception('No preview providers'); } @@ -510,37 +501,45 @@ class Preview { if (is_null($this->preview)) { $preview = null; - foreach (self::getProviders() as $supportedMimeType => $provider) { + $previewProviders = \OC::$server->getPreviewManager()->getProviders(); + foreach ($previewProviders as $supportedMimeType => $providers) { if (!preg_match($supportedMimeType, $this->mimeType)) { continue; } - \OC_Log::write('core', 'Generating preview for "' . $file . '" with "' . get_class($provider) . '"', \OC_Log::DEBUG); + foreach ($providers as $closure) { + $provider = $closure(); + if (!($provider instanceof \OC\Preview\Provider)) { + continue; + } - /** @var $provider Provider */ - $preview = $provider->getThumbnail($file, $maxX, $maxY, $scalingUp, $this->fileView); + \OC_Log::write('core', 'Generating preview for "' . $file . '" with "' . get_class($provider) . '"', \OC_Log::DEBUG); - if (!($preview instanceof \OC_Image)) { - continue; + /** @var $provider Provider */ + $preview = $provider->getThumbnail($file, $maxX, $maxY, $scalingUp, $this->fileView); + + if (!($preview instanceof \OC_Image)) { + continue; + } + + $this->preview = $preview; + $this->resizeAndCrop(); + + $previewPath = $this->getPreviewPath($fileId); + $cachePath = $this->buildCachePath($fileId); + + if ($this->userView->is_dir($this->getThumbnailsFolder() . '/') === false) { + $this->userView->mkdir($this->getThumbnailsFolder() . '/'); + } + + if ($this->userView->is_dir($previewPath) === false) { + $this->userView->mkdir($previewPath); + } + + $this->userView->file_put_contents($cachePath, $preview->data()); + + break 2; } - - $this->preview = $preview; - $this->resizeAndCrop(); - - $previewPath = $this->getPreviewPath($fileId); - $cachePath = $this->buildCachePath($fileId); - - if ($this->userView->is_dir($this->getThumbnailsFolder() . '/') === false) { - $this->userView->mkdir($this->getThumbnailsFolder() . '/'); - } - - if ($this->userView->is_dir($previewPath) === false) { - $this->userView->mkdir($previewPath); - } - - $this->userView->file_put_contents($cachePath, $preview->data()); - - break; } } @@ -685,154 +684,6 @@ class Preview { } } - /** - * register a new preview provider to be used - * @param string $class - * @param array $options - */ - public static function registerProvider($class, $options = array()) { - /** - * Only register providers that have been explicitly enabled - * - * The following providers are enabled by default: - * - OC\Preview\Image - * - OC\Preview\MP3 - * - OC\Preview\TXT - * - OC\Preview\MarkDown - * - * The following providers are disabled by default due to performance or privacy concerns: - * - OC\Preview\MSOfficeDoc - * - OC\Preview\MSOffice2003 - * - OC\Preview\MSOffice2007 - * - OC\Preview\OpenDocument - * - OC\Preview\StarOffice - * - OC\Preview\SVG - * - OC\Preview\Movie - * - OC\Preview\PDF - * - OC\Preview\TIFF - * - OC\Preview\Illustrator - * - OC\Preview\Postscript - * - OC\Preview\Photoshop - * - OC\Preview\Font - */ - if(empty(self::$enabledProviders)) { - self::$enabledProviders = \OC::$server->getConfig()->getSystemValue('enabledPreviewProviders', array( - 'OC\Preview\Image', - 'OC\Preview\MP3', - 'OC\Preview\TXT', - 'OC\Preview\MarkDown', - )); - } - - if(in_array($class, self::$enabledProviders)) { - self::$registeredProviders[] = array('class' => $class, 'options' => $options); - } - } - - /** - * create instances of all the registered preview providers - * @return void - */ - private static function initProviders() { - if (!\OC::$server->getConfig()->getSystemValue('enable_previews', true)) { - self::$providers = array(); - return; - } - - if (!empty(self::$providers)) { - return; - } - - self::registerCoreProviders(); - foreach (self::$registeredProviders as $provider) { - $class = $provider['class']; - $options = $provider['options']; - - /** @var $object Provider */ - $object = new $class($options); - self::$providers[$object->getMimeType()] = $object; - } - - $keys = array_map('strlen', array_keys(self::$providers)); - array_multisort($keys, SORT_DESC, self::$providers); - } - - protected static function getProviders() { - if (empty(self::$providers)) { - self::initProviders(); - } - - return self::$providers; - } - - protected static function registerCoreProviders() { - self::registerProvider('OC\Preview\TXT'); - self::registerProvider('OC\Preview\MarkDown'); - self::registerProvider('OC\Preview\Image'); - self::registerProvider('OC\Preview\MP3'); - - // SVG, Office and Bitmap require imagick - if (extension_loaded('imagick')) { - $checkImagick = new \Imagick(); - - $imagickProviders = array( - 'SVG' => 'OC\Preview\SVG', - 'TIFF' => 'OC\Preview\TIFF', - 'PDF' => 'OC\Preview\PDF', - 'AI' => 'OC\Preview\Illustrator', - 'PSD' => 'OC\Preview\Photoshop', - 'EPS' => 'OC\Preview\Postscript', - 'TTF' => 'OC\Preview\Font', - ); - - foreach ($imagickProviders as $queryFormat => $provider) { - if (count($checkImagick->queryFormats($queryFormat)) === 1) { - self::registerProvider($provider); - } - } - - if (count($checkImagick->queryFormats('PDF')) === 1) { - // Office previews are currently not supported on Windows - if (!\OC_Util::runningOnWindows() && \OC_Helper::is_function_enabled('shell_exec')) { - $officeFound = is_string(\OC::$server->getConfig()->getSystemValue('preview_libreoffice_path', null)); - - if (!$officeFound) { - //let's see if there is libreoffice or openoffice on this machine - $whichLibreOffice = shell_exec('command -v libreoffice'); - $officeFound = !empty($whichLibreOffice); - if (!$officeFound) { - $whichOpenOffice = shell_exec('command -v openoffice'); - $officeFound = !empty($whichOpenOffice); - } - } - - if ($officeFound) { - self::registerProvider('OC\Preview\MSOfficeDoc'); - self::registerProvider('OC\Preview\MSOffice2003'); - self::registerProvider('OC\Preview\MSOffice2007'); - self::registerProvider('OC\Preview\OpenDocument'); - self::registerProvider('OC\Preview\StarOffice'); - } - } - } - } - - // Video requires avconv or ffmpeg and is therefor - // currently not supported on Windows. - if (!\OC_Util::runningOnWindows()) { - $avconvBinary = \OC_Helper::findBinaryPath('avconv'); - $ffmpegBinary = ($avconvBinary) ? null : \OC_Helper::findBinaryPath('ffmpeg'); - - if ($avconvBinary || $ffmpegBinary) { - // FIXME // a bit hacky but didn't want to use subclasses - \OC\Preview\Movie::$avconvBinary = $avconvBinary; - \OC\Preview\Movie::$ffmpegBinary = $ffmpegBinary; - - self::registerProvider('OC\Preview\Movie'); - } - } - } - /** * @param array $args */ diff --git a/lib/private/previewmanager.php b/lib/private/previewmanager.php index 29c205e730..e017923297 100644 --- a/lib/private/previewmanager.php +++ b/lib/private/previewmanager.php @@ -15,6 +15,13 @@ class PreviewManager implements IPreview { /** @var array */ protected $providers = []; + /** + * Constructor + */ + public function __construct() { + $this->registerCoreProviders(); + } + /** * In order to improve lazy loading a closure can be registered which will be * called in case preview providers are actually requested @@ -26,12 +33,35 @@ class PreviewManager implements IPreview { * @return void */ public function registerProvider($mimeTypeRegex, \Closure $callable) { + if (!\OC::$server->getConfig()->getSystemValue('enable_previews', true)) { + return; + } + if (!isset($this->providers[$mimeTypeRegex])) { $this->providers[$mimeTypeRegex] = []; } $this->providers[$mimeTypeRegex][] = $callable; } + /** + * Get all providers + * @return array + */ + public function getProviders() { + $keys = array_map('strlen', array_keys($this->providers)); + array_multisort($keys, SORT_DESC, $this->providers); + + return $this->providers; + } + + /** + * Does the manager have any providers + * @return bool + */ + public function hasProviders() { + return !empty($this->providers); + } + /** * return a preview of a file * @@ -84,7 +114,12 @@ class PreviewManager implements IPreview { foreach ($this->providers as $supportedMimeType => $providers) { if (preg_match($supportedMimeType, $file->getMimetype())) { - foreach ($providers as $provider) { + foreach ($providers as $closure) { + $provider = $closure(); + if (!($provider instanceof \OC\Preview\Provider)) { + continue; + } + /** @var $provider \OC\Preview\Provider */ if ($provider->isAvailable($file)) { return true; @@ -94,4 +129,137 @@ class PreviewManager implements IPreview { } return false; } + + /** @var array */ + protected $defaultProviders; + + /** + * List of enabled default providers + * + * The following providers are enabled by default: + * - OC\Preview\Image + * - OC\Preview\MP3 + * - OC\Preview\TXT + * - OC\Preview\MarkDown + * + * The following providers are disabled by default due to performance or privacy concerns: + * - OC\Preview\MSOfficeDoc + * - OC\Preview\MSOffice2003 + * - OC\Preview\MSOffice2007 + * - OC\Preview\OpenDocument + * - OC\Preview\StarOffice + * - OC\Preview\SVG + * - OC\Preview\Movie + * - OC\Preview\PDF + * - OC\Preview\TIFF + * - OC\Preview\Illustrator + * - OC\Preview\Postscript + * - OC\Preview\Photoshop + * - OC\Preview\Font + * + * @return array + */ + protected function getEnabledDefaultProvider() { + if ($this->defaultProviders !== null) { + return $this->defaultProviders; + } + + $this->defaultProviders = \OC::$server->getConfig()->getSystemValue('enabledPreviewProviders', [ + 'OC\Preview\Image', + 'OC\Preview\MP3', + 'OC\Preview\TXT', + 'OC\Preview\MarkDown', + ]); + return $this->defaultProviders; + } + + /** + * Register the default providers (if enabled) + * + * @param string $class + * @param string $mimeType + */ + protected function registerCoreProvider($class, $mimeType) { + if (in_array(trim($class, '\\'), $this->getEnabledDefaultProvider())) { + $this->registerProvider($mimeType, function () use ($class) { + return new $class([]); + }); + } + } + + /** + * Register the default providers (if enabled) + */ + protected function registerCoreProviders() { + $this->registerCoreProvider('OC\Preview\TXT', '/text\/plain/'); + $this->registerCoreProvider('OC\Preview\MarkDown', '/text\/(x-)?markdown/'); + $this->registerCoreProvider('OC\Preview\Image', '/image\/(?!tiff$)(?!svg.*).*/'); + $this->registerCoreProvider('OC\Preview\MP3', '/audio\/mpeg/'); + + // SVG, Office and Bitmap require imagick + if (extension_loaded('imagick')) { + $checkImagick = new \Imagick(); + + $imagickProviders = [ + 'SVG' => ['mimetype' => '/image\/svg\+xml/', 'class' => '\OC\Preview\SVG'], + 'TIFF' => ['mimetype' => '/image\/tiff/', 'class' => '\OC\Preview\TIFF'], + 'PDF' => ['mimetype' => '/application\/pdf/', 'class' => '\OC\Preview\PDF'], + 'AI' => ['mimetype' => '/application\/illustrator/', 'class' => '\OC\Preview\Illustrator'], + 'PSD' => ['mimetype' => '/application\/x-photoshop/', 'class' => '\OC\Preview\Photoshop'], + 'EPS' => ['mimetype' => '/application\/postscript/', 'class' => '\OC\Preview\Postscript'], + 'TTF' => ['mimetype' => '/application\/(?:font-sfnt|x-font$)/', 'class' => '\OC\Preview\Font'], + ]; + + foreach ($imagickProviders as $queryFormat => $provider) { + $class = $provider['class']; + if (!in_array(trim($class, '\\'), $this->getEnabledDefaultProvider())) { + continue; + } + + if (count($checkImagick->queryFormats($queryFormat)) === 1) { + $this->registerCoreProvider($class, $provider['mimetype']); + } + } + + if (count($checkImagick->queryFormats('PDF')) === 1) { + // Office previews are currently not supported on Windows + if (!\OC_Util::runningOnWindows() && \OC_Helper::is_function_enabled('shell_exec')) { + $officeFound = is_string(\OC::$server->getConfig()->getSystemValue('preview_libreoffice_path', null)); + + if (!$officeFound) { + //let's see if there is libreoffice or openoffice on this machine + $whichLibreOffice = shell_exec('command -v libreoffice'); + $officeFound = !empty($whichLibreOffice); + if (!$officeFound) { + $whichOpenOffice = shell_exec('command -v openoffice'); + $officeFound = !empty($whichOpenOffice); + } + } + + if ($officeFound) { + $this->registerCoreProvider('\OC\Preview\MSOfficeDoc', '/application\/msword/'); + $this->registerCoreProvider('\OC\Preview\MSOffice2003', '/application\/vnd.ms-.*/'); + $this->registerCoreProvider('\OC\Preview\MSOffice2007', '/application\/vnd.openxmlformats-officedocument.*/'); + $this->registerCoreProvider('\OC\Preview\OpenDocument', '/application\/vnd.oasis.opendocument.*/'); + $this->registerCoreProvider('\OC\Preview\StarOffice', '/application\/vnd.sun.xml.*/'); + } + } + } + } + + // Video requires avconv or ffmpeg and is therefor + // currently not supported on Windows. + if (in_array('OC\Preview\Movie', $this->getEnabledDefaultProvider()) && !\OC_Util::runningOnWindows()) { + $avconvBinary = \OC_Helper::findBinaryPath('avconv'); + $ffmpegBinary = ($avconvBinary) ? null : \OC_Helper::findBinaryPath('ffmpeg'); + + if ($avconvBinary || $ffmpegBinary) { + // FIXME // a bit hacky but didn't want to use subclasses + \OC\Preview\Movie::$avconvBinary = $avconvBinary; + \OC\Preview\Movie::$ffmpegBinary = $ffmpegBinary; + + $this->registerCoreProvider('\OC\Preview\Movie', '/video\/.*/'); + } + } + } } diff --git a/lib/public/ipreview.php b/lib/public/ipreview.php index 9ebe2e2d1c..4a45fa2908 100644 --- a/lib/public/ipreview.php +++ b/lib/public/ipreview.php @@ -49,6 +49,18 @@ interface IPreview { */ public function registerProvider($mimeTypeRegex, \Closure $callable); + /** + * Get all providers + * @return array + */ + public function getProviders(); + + /** + * Does the manager have any providers + * @return bool + */ + public function hasProviders(); + /** * Return a preview of a file * @param string $file The path to the file where you want a thumbnail from