Merge pull request #14857 from owncloud/preview-provider-registration-in-manager

Preview provider registration in manager
This commit is contained in:
Thomas Müller 2015-03-20 16:34:22 +01:00
commit afa8872955
19 changed files with 556 additions and 275 deletions

View File

@ -170,6 +170,7 @@ class ShareController extends Controller {
$shareTmpl['filename'] = $file;
$shareTmpl['directory_path'] = $linkItem['file_target'];
$shareTmpl['mimetype'] = Filesystem::getMimeType($originalSharePath);
$shareTmpl['previewSupported'] = \OC::$server->getPreviewManager()->isMimeSupported($shareTmpl['mimetype']);
$shareTmpl['dirToken'] = $linkItem['token'];
$shareTmpl['sharingToken'] = $token;
$shareTmpl['server2serversharing'] = Helper::isOutgoingServer2serverShareEnabled();

View File

@ -19,11 +19,10 @@ OCP\Util::addScript('files', 'files');
OCP\Util::addScript('files', 'filelist');
OCP\Util::addscript('files', 'keyboardshortcuts');
$thumbSize=1024;
$previewSupported = OC\Preview::isMimeSupported($_['mimetype']) ? 'true' : 'false';
$thumbSize = 1024;
?>
<?php if ( \OC\Preview::isMimeSupported($_['mimetype'])): /* This enables preview images for links (e.g. on Facebook, Google+, ...)*/?>
<?php if ($_['previewSupported']): /* This enables preview images for links (e.g. on Facebook, Google+, ...)*/?>
<link rel="image_src" href="<?php p(OCP\Util::linkToRoute( 'core_ajax_public_preview', array('x' => $thumbSize, 'y' => $thumbSize, 'file' => $_['directory_path'], 't' => $_['dirToken']))); ?>" />
<?php endif; ?>
@ -38,7 +37,7 @@ $previewSupported = OC\Preview::isMimeSupported($_['mimetype']) ? 'true' : 'fals
<input type="hidden" name="sharingToken" value="<?php p($_['sharingToken']) ?>" id="sharingToken">
<input type="hidden" name="filename" value="<?php p($_['filename']) ?>" id="filename">
<input type="hidden" name="mimetype" value="<?php p($_['mimetype']) ?>" id="mimetype">
<input type="hidden" name="previewSupported" value="<?php p($previewSupported); ?>" id="previewSupported">
<input type="hidden" name="previewSupported" value="<?php p($_['previewSupported'] ? 'true' : 'false'); ?>" id="previewSupported">
<input type="hidden" name="mimetypeIcon" value="<?php p(OC_Helper::mimetypeIcon($_['mimetype'])); ?>" id="mimetypeIcon">
<input type="hidden" name="filesize" value="<?php p($_['nonHumanFileSize']); ?>" id="filesize">
<input type="hidden" name="maxSizeAnimateGif" value="<?php p($_['maxSizeAnimateGif']); ?>" id="maxSizeAnimateGif">

View File

@ -158,6 +158,7 @@ class ShareControllerTest extends \Test\TestCase {
'fileSize' => '33 B',
'nonHumanFileSize' => 33,
'maxSizeAnimateGif' => 10,
'previewSupported' => true,
);
$csp = new \OCP\AppFramework\Http\ContentSecurityPolicy();

View File

@ -29,13 +29,12 @@ if ($maxX === 0 || $maxY === 0) {
exit;
}
$preview = new \OC\Preview(\OC_User::getUser(), 'files');
$info = \OC\Files\Filesystem::getFileInfo($file);
if (!$info instanceof OCP\Files\FileInfo || !$always && !$preview->isAvailable($info)) {
if (!$info instanceof OCP\Files\FileInfo || !$always && !\OC::$server->getPreviewManager()->isAvailable($info)) {
\OC_Response::setStatus(404);
} else {
$preview = new \OC\Preview(\OC_User::getUser(), 'files');
$preview->setFile($file);
$preview->setMaxX($maxX);
$preview->setMaxY($maxY);

View File

@ -95,7 +95,7 @@ class AvatarController extends Controller {
$avatar = $this->avatarManager->getAvatar($userId);
$image = $avatar->get($size);
if ($image instanceof \OC_Image) {
if ($image instanceof \OCP\IImage) {
$resp = new DataDisplayResponse($image->data(),
Http::STATUS_OK,
['Content-Type' => $image->mimeType()]);

View File

@ -29,7 +29,7 @@ class Avatar implements \OCP\IAvatar {
/**
* get the users avatar
* @param int $size size in px of the avatar, avatars are square, defaults to 64
* @return boolean|\OC_Image containing the avatar or false if there's no image
* @return boolean|\OCP\IImage containing the avatar or false if there's no image
*/
public function get ($size = 64) {
if ($this->view->file_exists('avatar.jpg')) {
@ -57,14 +57,14 @@ class Avatar implements \OCP\IAvatar {
/**
* sets the users avatar
* @param \OC_Image|resource|string $data OC_Image, imagedata or path to set a new avatar
* @param \OCP\IImage|resource|string $data An image object, imagedata or path to set a new avatar
* @throws \Exception if the provided file is not a jpg or png image
* @throws \Exception if the provided image is not valid
* @throws \OC\NotSquareException if the image is not square
* @return void
*/
public function set ($data) {
if($data instanceOf OC_Image) {
if($data instanceOf \OCP\IImage) {
$img = $data;
$data = $img->data();
} else {

View File

@ -15,7 +15,7 @@
/**
* Class for basic image manipulation
*/
class OC_Image {
class OC_Image implements \OCP\IImage {
protected $resource = false; // tmp resource.
protected $imageType = IMAGETYPE_PNG; // Default to png if file type isn't evident.
protected $mimeType = "image/png"; // Default to png
@ -285,7 +285,7 @@ class OC_Image {
/**
* @return null|string Returns the raw image data.
*/
function data() {
public function data() {
if (!$this->valid()) {
return null;
}
@ -949,6 +949,9 @@ class OC_Image {
return true;
}
/**
* Destroys the current image and resets the object
*/
public function destroy() {
if ($this->valid()) {
imagedestroy($this->resource);

View File

@ -46,15 +46,10 @@ class Preview {
/**
* preview images object
*
* @var \OC_Image
* @var \OCP\IImage
*/
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');
}
@ -474,7 +465,7 @@ class Preview {
/**
* return a preview of a file
* @return \OC_Image
* @return \OCP\IImage
*/
public function getPreview() {
if (!is_null($this->preview) && $this->preview->valid()) {
@ -510,37 +501,45 @@ class Preview {
if (is_null($this->preview)) {
$preview = null;
foreach (self::$providers 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 \OCP\Preview\IProvider)) {
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 \OCP\IImage)) {
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;
}
}
@ -565,7 +564,7 @@ class Preview {
if (is_null($this->preview)) {
$this->getPreview();
}
if ($this->preview instanceof \OC_Image) {
if ($this->preview instanceof \OCP\IImage) {
$this->preview->show($mimeType);
}
}
@ -581,8 +580,8 @@ class Preview {
$scalingUp = $this->getScalingUp();
$maxScaleFactor = $this->getMaxScaleFactor();
if (!($image instanceof \OC_Image)) {
\OC_Log::write('core', '$this->preview is not an instance of OC_Image', \OC_Log::DEBUG);
if (!($image instanceof \OCP\IImage)) {
\OC_Log::write('core', '$this->preview is not an instance of \OCP\IImage', \OC_Log::DEBUG);
return;
}
@ -685,146 +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 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
*/
@ -914,60 +773,6 @@ class Preview {
$preview->deleteAllPreviews();
}
/**
* Check if a preview can be generated for a file
*
* @param \OC\Files\FileInfo $file
* @return bool
*/
public static function isAvailable(\OC\Files\FileInfo $file) {
if (!\OC_Config::getValue('enable_previews', true)) {
return false;
}
$mount = $file->getMountPoint();
if ($mount and !$mount->getOption('previews', true)){
return false;
}
//check if there are preview backends
if (empty(self::$providers)) {
self::initProviders();
}
foreach (self::$providers as $supportedMimeType => $provider) {
/**
* @var \OC\Preview\Provider $provider
*/
if (preg_match($supportedMimeType, $file->getMimetype())) {
return $provider->isAvailable($file);
}
}
return false;
}
/**
* @param string $mimeType
* @return bool
*/
public static function isMimeSupported($mimeType) {
if (!\OC_Config::getValue('enable_previews', true)) {
return false;
}
//check if there are preview backends
if (empty(self::$providers)) {
self::initProviders();
}
foreach(self::$providers as $supportedMimetype => $provider) {
if(preg_match($supportedMimetype, $mimeType)) {
return true;
}
}
return false;
}
/**
* @param int $fileId
* @return string

View File

@ -61,7 +61,7 @@ class Movie extends Provider {
* @param int $maxY
* @param string $absPath
* @param int $second
* @return bool|\OC_Image
* @return bool|\OCP\IImage
*/
private function generateThumbNail($maxX, $maxY, $absPath, $second) {
$tmpPath = \OC_Helper::tmpFile();

View File

@ -39,8 +39,7 @@ class MP3 extends Provider {
/**
* Generates a default image when the file has no cover
*
* @return false|\OC_Image False if the default image is missing or invalid,
* otherwise the image is returned as \OC_Image
* @return bool|\OCP\IImage false if the default image is missing or invalid
*/
private function getNoCoverThumbnail() {
$icon = \OC::$SERVERROOT . '/core/img/filetypes/audio.png';

View File

@ -1,10 +1,17 @@
<?php
namespace OC\Preview;
abstract class Provider {
use OCP\Preview\IProvider;
abstract class Provider implements IProvider {
private $options;
public function __construct($options) {
/**
* Constructor
*
* @param array $options
*/
public function __construct(array $options = []) {
$this->options = $options;
}
@ -16,10 +23,10 @@ abstract class Provider {
/**
* Check if a preview can be generated for $path
*
* @param \OC\Files\FileInfo $file
* @param \OCP\Files\FileInfo $file
* @return bool
*/
public function isAvailable($file) {
public function isAvailable(\OCP\Files\FileInfo $file) {
return true;
}
@ -30,9 +37,7 @@ abstract class Provider {
* @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 mixed
* false if no preview was generated
* OC_Image object of the preview
* @return bool|\OCP\IImage false if no preview was generated
*/
abstract public function getThumbnail($path, $maxX, $maxY, $scalingup, $fileview);
}

View File

@ -18,7 +18,7 @@ class TXT extends Provider {
/**
* {@inheritDoc}
*/
public function isAvailable($file) {
public function isAvailable(\OCP\Files\FileInfo $file) {
return $file->getSize() > 5;
}

View File

@ -8,10 +8,87 @@
*/
namespace OC;
use OCP\image;
use OCP\IPreview;
use OCP\Preview\IProvider;
class PreviewManager implements IPreview {
/** @var \OCP\IConfig */
protected $config;
/** @var bool */
protected $providerListDirty = false;
/** @var bool */
protected $registeredCoreProviders = false;
/** @var array */
protected $providers = [];
/** @var array mime type => support status */
protected $mimeTypeSupportMap = [];
/** @var array */
protected $defaultProviders;
/**
* Constructor
*
* @param \OCP\IConfig $config
*/
public function __construct(\OCP\IConfig $config) {
$this->config = $config;
}
/**
* 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
*/
public function registerProvider($mimeTypeRegex, \Closure $callable) {
if (!$this->config->getSystemValue('enable_previews', true)) {
return;
}
if (!isset($this->providers[$mimeTypeRegex])) {
$this->providers[$mimeTypeRegex] = [];
}
$this->providers[$mimeTypeRegex][] = $callable;
$this->providerListDirty = true;
}
/**
* Get all providers
* @return array
*/
public function getProviders() {
if (!$this->config->getSystemValue('enable_previews', true)) {
return [];
}
$this->registerCoreProviders();
if ($this->providerListDirty) {
$keys = array_map('strlen', array_keys($this->providers));
array_multisort($keys, SORT_DESC, $this->providers);
$this->providerListDirty = false;
}
return $this->providers;
}
/**
* Does the manager have any providers
* @return bool
*/
public function hasProviders() {
$this->registerCoreProviders();
return !empty($this->providers);
}
/**
* return a preview of a file
*
@ -19,9 +96,9 @@ class PreviewManager implements IPreview {
* @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 boolean $scaleUp Scale smaller images up to the thumbnail size or not. Might look ugly
* @return \OCP\Image
* @return \OCP\IImage
*/
function createPreview($file, $maxX = 100, $maxY = 75, $scaleUp = false) {
public function createPreview($file, $maxX = 100, $maxY = 75, $scaleUp = false) {
$preview = new \OC\Preview('', '/', $file, $maxX, $maxY, $scaleUp);
return $preview->getPreview();
}
@ -32,17 +109,198 @@ class PreviewManager implements IPreview {
* @param string $mimeType
* @return boolean
*/
function isMimeSupported($mimeType = '*') {
return \OC\Preview::isMimeSupported($mimeType);
public function isMimeSupported($mimeType = '*') {
if (!$this->config->getSystemValue('enable_previews', true)) {
return false;
}
if (isset($this->mimeTypeSupportMap[$mimeType])) {
return $this->mimeTypeSupportMap[$mimeType];
}
$this->registerCoreProviders();
$providerMimeTypes = array_keys($this->providers);
foreach ($providerMimeTypes as $supportedMimeType) {
if (preg_match($supportedMimeType, $mimeType)) {
$this->mimeTypeSupportMap[$mimeType] = true;
return true;
}
}
$this->mimeTypeSupportMap[$mimeType] = false;
return false;
}
/**
* Check if a preview can be generated for a file
*
* @param \OC\Files\FileInfo $file
* @param \OCP\Files\FileInfo $file
* @return bool
*/
function isAvailable($file) {
return \OC\Preview::isAvailable($file);
public function isAvailable(\OCP\Files\FileInfo $file) {
if (!$this->config->getSystemValue('enable_previews', true)) {
return false;
}
$this->registerCoreProviders();
if (!$this->isMimeSupported($file->getMimetype())) {
return false;
}
$mount = $file->getMountPoint();
if ($mount and !$mount->getOption('previews', true)){
return false;
}
foreach ($this->providers as $supportedMimeType => $providers) {
if (preg_match($supportedMimeType, $file->getMimetype())) {
foreach ($providers as $closure) {
$provider = $closure();
if (!($provider instanceof IProvider)) {
continue;
}
/** @var $provider IProvider */
if ($provider->isAvailable($file)) {
return true;
}
}
}
}
return false;
}
/**
* List of enabled default providers
*
* The following providers are enabled by default:
* - OC\Preview\Image
* - OC\Preview\MarkDown
* - OC\Preview\MP3
* - OC\Preview\TXT
*
* The following providers are disabled by default due to performance or privacy concerns:
* - OC\Preview\Font
* - OC\Preview\Illustrator
* - OC\Preview\Movie
* - OC\Preview\MSOfficeDoc
* - OC\Preview\MSOffice2003
* - OC\Preview\MSOffice2007
* - OC\Preview\OpenDocument
* - OC\Preview\PDF
* - OC\Preview\Photoshop
* - OC\Preview\Postscript
* - OC\Preview\StarOffice
* - OC\Preview\SVG
* - OC\Preview\TIFF
*
* @return array
*/
protected function getEnabledDefaultProvider() {
if ($this->defaultProviders !== null) {
return $this->defaultProviders;
}
$this->defaultProviders = $this->config->getSystemValue('enabledPreviewProviders', [
'OC\Preview\Image',
'OC\Preview\MarkDown',
'OC\Preview\MP3',
'OC\Preview\TXT',
]);
return $this->defaultProviders;
}
/**
* Register the default providers (if enabled)
*
* @param string $class
* @param string $mimeType
*/
protected function registerCoreProvider($class, $mimeType, $options = []) {
if (in_array(trim($class, '\\'), $this->getEnabledDefaultProvider())) {
$this->registerProvider($mimeType, function () use ($class, $options) {
return new $class($options);
});
}
}
/**
* Register the default providers (if enabled)
*/
protected function registerCoreProviders() {
if ($this->registeredCoreProviders) {
return;
}
$this->registeredCoreProviders = true;
$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($this->config->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\/.*/');
}
}
}
}

View File

@ -45,8 +45,8 @@ class Server extends SimpleContainer implements IServerContainer {
$this->registerService('ContactsManager', function ($c) {
return new ContactsManager();
});
$this->registerService('PreviewManager', function ($c) {
return new PreviewManager();
$this->registerService('PreviewManager', function (Server $c) {
return new PreviewManager($c->getConfig());
});
$this->registerService('TagMapper', function(Server $c) {
return new TagMapper($c->getDatabaseConnection());

View File

@ -16,7 +16,7 @@ interface IAvatar {
/**
* get the users avatar
* @param int $size size in px of the avatar, avatars are square, defaults to 64
* @return boolean|\OC_Image containing the avatar or false if there's no image
* @return boolean|\OCP\IImage containing the avatar or false if there's no image
*/
function get($size = 64);
@ -29,7 +29,7 @@ interface IAvatar {
/**
* sets the users avatar
* @param \OC_Image|resource|string $data OC_Image, imagedata or path to set a new avatar
* @param \OCP\IImage|resource|string $data An image object, imagedata or path to set a new avatar
* @throws \Exception if the provided file is not a jpg or png image
* @throws \Exception if the provided image is not valid
* @throws \OC\NotSquareException if the image is not square

146
lib/public/iimage.php Normal file
View File

@ -0,0 +1,146 @@
<?php
/**
* ownCloud
*
* @author Joas Schilling
* @copyright 2015 Joas Schilling nickvergessen@owncloud.com
*
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace OCP;
/**
* Class for basic image manipulation
*/
interface IImage {
/**
* Determine whether the object contains an image resource.
*
* @return bool
*/
public function valid();
/**
* Returns the MIME type of the image or an empty string if no image is loaded.
*
* @return string
*/
public function mimeType();
/**
* Returns the width of the image or -1 if no image is loaded.
*
* @return int
*/
public function width();
/**
* Returns the height of the image or -1 if no image is loaded.
*
* @return int
*/
public function height();
/**
* Returns the width when the image orientation is top-left.
*
* @return int
*/
public function widthTopLeft();
/**
* Returns the height when the image orientation is top-left.
*
* @return int
*/
public function heightTopLeft();
/**
* Outputs the image.
*
* @param string $mimeType
* @return bool
*/
public function show($mimeType = null);
/**
* Saves the image.
*
* @param string $filePath
* @param string $mimeType
* @return bool
*/
public function save($filePath = null, $mimeType = null);
/**
* @return resource Returns the image resource in any.
*/
public function resource();
/**
* @return string Returns the raw image data.
*/
public function data();
/**
* (I'm open for suggestions on better method name ;)
* Get the orientation based on EXIF data.
*
* @return int The orientation or -1 if no EXIF data is available.
*/
public function getOrientation();
/**
* (I'm open for suggestions on better method name ;)
* Fixes orientation based on EXIF data.
*
* @return bool.
*/
public function fixOrientation();
/**
* Resizes the image preserving ratio.
*
* @param integer $maxSize The maximum size of either the width or height.
* @return bool
*/
public function resize($maxSize);
/**
* @param int $width
* @param int $height
* @return bool
*/
public function preciseResize($width, $height);
/**
* Crops the image to the middle square. If the image is already square it just returns.
*
* @param int $size maximum size for the result (optional)
* @return bool for success or failure
*/
public function centerCrop($size = 0);
/**
* Crops the image from point $x$y with dimension $wx$h.
*
* @param int $x Horizontal position
* @param int $y Vertical position
* @param int $w Width
* @param int $h Height
* @return bool for success or failure
*/
public function crop($x, $y, $w, $h);
/**
* Resizes the image to fit within a boundary while preserving ratio.
*
* @param integer $maxWidth
* @param integer $maxHeight
* @return bool
*/
public function fitIn($maxWidth, $maxHeight);
}

View File

@ -36,8 +36,30 @@ namespace OCP;
/**
* This class provides functions to render and show thumbnails and previews of files
*/
interface IPreview
{
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
*/
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
@ -45,9 +67,9 @@ interface IPreview
* @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 boolean $scaleUp Scale smaller images up to the thumbnail size or not. Might look ugly
* @return \OCP\Image
* @return \OCP\IImage
*/
function createPreview($file, $maxX = 100, $maxY = 75, $scaleUp = false);
public function createPreview($file, $maxX = 100, $maxY = 75, $scaleUp = false);
/**
@ -55,7 +77,7 @@ interface IPreview
* @param string $mimeType
* @return boolean
*/
function isMimeSupported($mimeType = '*');
public function isMimeSupported($mimeType = '*');
/**
* Check if a preview can be generated for a file
@ -63,5 +85,5 @@ interface IPreview
* @param \OCP\Files\FileInfo $file
* @return bool
*/
function isAvailable($file);
public function isAvailable(\OCP\Files\FileInfo $file);
}

View File

@ -0,0 +1,39 @@
<?php
/**
* ownCloud
*
* @author Joas Schilling
* @copyright 2015 Joas Schilling nickvergessen@owncloud.com
*
* This file is licensed under the Affero General Public License version 3 or
* later.
* See the COPYING-README file.
*/
namespace OCP\Preview;
interface IProvider {
/**
* @return string Regex with the mimetypes that are supported by this provider
*/
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);
/**
* get thumbnail 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
*/
public function getThumbnail($path, $maxX, $maxY, $scalingup, $fileview);
}

View File

@ -31,20 +31,24 @@ class Test_Image extends \Test\TestCase {
public function testConstructDestruct() {
$img = new \OC_Image(OC::$SERVERROOT.'/tests/data/testimage.png');
$this->assertInstanceOf('\OC_Image', $img);
$this->assertInstanceOf('\OCP\IImage', $img);
unset($img);
$imgcreate = imagecreatefromjpeg(OC::$SERVERROOT.'/tests/data/testimage.jpg');
$img = new \OC_Image($imgcreate);
$this->assertInstanceOf('\OC_Image', $img);
$this->assertInstanceOf('\OCP\IImage', $img);
unset($img);
$base64 = base64_encode(file_get_contents(OC::$SERVERROOT.'/tests/data/testimage.gif'));
$img = new \OC_Image($base64);
$this->assertInstanceOf('\OC_Image', $img);
$this->assertInstanceOf('\OCP\IImage', $img);
unset($img);
$img = new \OC_Image(null);
$this->assertInstanceOf('\OC_Image', $img);
$this->assertInstanceOf('\OCP\IImage', $img);
unset($img);
}