mirror of
https://github.com/nextcloud/server.git
synced 2026-04-22 23:03:00 -04:00
commit
c0bbae28f0
32 changed files with 2353 additions and 382 deletions
|
|
@ -6,3 +6,10 @@ NC 11 (????-??-??)
|
|||
* PHP 5.4 and 5.5 no longer supported
|
||||
* PHP 7.1 support
|
||||
* OC_L10N removed use \OCP\IL10N (#1948)
|
||||
* Preview handling is improved by sharing previews:
|
||||
* Preview sharing (shared files/external storages)
|
||||
* Previews are stored in the AppData
|
||||
* Previews are served faster by not first converting them to image objects
|
||||
* Core preview route changed:
|
||||
* Route for the urlgenerator changed from 'core_ajax_preview' to 'core.Preview.getPreview'
|
||||
* $urlGenerator->linkToRoute('core_ajax_preview', ...) => $urlGenerator->linkToRoute('core.Preview.getPreview', ...)
|
||||
|
|
|
|||
|
|
@ -31,11 +31,13 @@ namespace OCA\Files\Controller;
|
|||
|
||||
use OCP\AppFramework\Http;
|
||||
use OCP\AppFramework\Controller;
|
||||
use OCP\Files\File;
|
||||
use OCP\Files\Folder;
|
||||
use OCP\Files\NotFoundException;
|
||||
use OCP\IConfig;
|
||||
use OCP\IRequest;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\AppFramework\Http\DataDisplayResponse;
|
||||
use OCP\AppFramework\Http\FileDisplayResponse;
|
||||
use OCP\AppFramework\Http\Response;
|
||||
use OCA\Files\Service\TagService;
|
||||
use OCP\IPreview;
|
||||
|
|
@ -101,18 +103,27 @@ class ApiController extends Controller {
|
|||
* @param int $x
|
||||
* @param int $y
|
||||
* @param string $file URL-encoded filename
|
||||
* @return DataResponse|DataDisplayResponse
|
||||
* @return DataResponse|FileDisplayResponse
|
||||
*/
|
||||
public function getThumbnail($x, $y, $file) {
|
||||
if($x < 1 || $y < 1) {
|
||||
return new DataResponse(['message' => 'Requested size must be numeric and a positive value.'], Http::STATUS_BAD_REQUEST);
|
||||
}
|
||||
|
||||
$preview = $this->previewManager->createPreview('files/'.$file, $x, $y, true);
|
||||
if ($preview->valid()) {
|
||||
return new DataDisplayResponse($preview->data(), Http::STATUS_OK, ['Content-Type' => 'image/png']);
|
||||
} else {
|
||||
try {
|
||||
$file = $this->userFolder->get($file);
|
||||
if ($file instanceof Folder) {
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
/** @var File $file */
|
||||
$preview = $this->previewManager->getPreview($file, $x, $y, true);
|
||||
|
||||
return new FileDisplayResponse($preview, Http::STATUS_OK, ['Content-Type' => $preview->getMimeType()]);
|
||||
} catch (NotFoundException $e) {
|
||||
return new DataResponse(['message' => 'File not found.'], Http::STATUS_NOT_FOUND);
|
||||
} catch (\Exception $e) {
|
||||
return new DataResponse([], Http::STATUS_BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,11 +28,15 @@ namespace OCA\Files\Controller;
|
|||
|
||||
use OC\Files\FileInfo;
|
||||
use OCP\AppFramework\Http;
|
||||
use OCP\Files\File;
|
||||
use OCP\Files\Folder;
|
||||
use OCP\Files\NotFoundException;
|
||||
use OCP\Files\SimpleFS\ISimpleFile;
|
||||
use OCP\Files\StorageNotAvailableException;
|
||||
use OCP\IConfig;
|
||||
use OCP\IUser;
|
||||
use OCP\IUserSession;
|
||||
use OCP\Share\IManager;
|
||||
use Test\TestCase;
|
||||
use OCP\IRequest;
|
||||
use OCA\Files\Service\TagService;
|
||||
|
|
@ -54,7 +58,7 @@ class ApiControllerTest extends TestCase {
|
|||
private $request;
|
||||
/** @var TagService */
|
||||
private $tagService;
|
||||
/** @var IPreview */
|
||||
/** @var IPreview|\PHPUnit_Framework_MockObject_MockObject */
|
||||
private $preview;
|
||||
/** @var ApiController */
|
||||
private $apiController;
|
||||
|
|
@ -62,11 +66,13 @@ class ApiControllerTest extends TestCase {
|
|||
private $shareManager;
|
||||
/** @var \OCP\IConfig */
|
||||
private $config;
|
||||
/** @var \OC\Files\Node\Folder */
|
||||
/** @var Folder|\PHPUnit_Framework_MockObject_MockObject */
|
||||
private $userFolder;
|
||||
|
||||
public function setUp() {
|
||||
$this->request = $this->getMockBuilder('\OCP\IRequest')
|
||||
parent::setUp();
|
||||
|
||||
$this->request = $this->getMockBuilder(IRequest::class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$this->user = $this->createMock(IUser::class);
|
||||
|
|
@ -77,17 +83,17 @@ class ApiControllerTest extends TestCase {
|
|||
$userSession->expects($this->any())
|
||||
->method('getUser')
|
||||
->will($this->returnValue($this->user));
|
||||
$this->tagService = $this->getMockBuilder('\OCA\Files\Service\TagService')
|
||||
$this->tagService = $this->getMockBuilder(TagService::class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$this->shareManager = $this->getMockBuilder('\OCP\Share\IManager')
|
||||
$this->shareManager = $this->getMockBuilder(IManager::class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$this->preview = $this->getMockBuilder('\OCP\IPreview')
|
||||
$this->preview = $this->getMockBuilder(IPreview::class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$this->config = $this->createMock(IConfig::class);
|
||||
$this->userFolder = $this->getMockBuilder('\OC\Files\Node\Folder')
|
||||
$this->userFolder = $this->getMockBuilder(Folder::class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
|
|
@ -153,28 +159,41 @@ class ApiControllerTest extends TestCase {
|
|||
}
|
||||
|
||||
public function testGetThumbnailInvalidSize() {
|
||||
$this->userFolder->method('get')
|
||||
->with($this->equalTo(''))
|
||||
->willThrowException(new NotFoundException());
|
||||
$expected = new DataResponse(['message' => 'Requested size must be numeric and a positive value.'], Http::STATUS_BAD_REQUEST);
|
||||
$this->assertEquals($expected, $this->apiController->getThumbnail(0, 0, ''));
|
||||
}
|
||||
|
||||
public function testGetThumbnailInvaidImage() {
|
||||
$file = $this->createMock(File::class);
|
||||
$this->userFolder->method('get')
|
||||
->with($this->equalTo('unknown.jpg'))
|
||||
->willReturn($file);
|
||||
$this->preview->expects($this->once())
|
||||
->method('createPreview')
|
||||
->with('files/unknown.jpg', 10, 10, true)
|
||||
->willReturn(new Image);
|
||||
->method('getPreview')
|
||||
->with($file, 10, 10, true)
|
||||
->willThrowException(new NotFoundException());
|
||||
$expected = new DataResponse(['message' => 'File not found.'], Http::STATUS_NOT_FOUND);
|
||||
$this->assertEquals($expected, $this->apiController->getThumbnail(10, 10, 'unknown.jpg'));
|
||||
}
|
||||
|
||||
public function testGetThumbnail() {
|
||||
$file = $this->createMock(File::class);
|
||||
$this->userFolder->method('get')
|
||||
->with($this->equalTo('known.jpg'))
|
||||
->willReturn($file);
|
||||
$preview = $this->createMock(ISimpleFile::class);
|
||||
$this->preview->expects($this->once())
|
||||
->method('createPreview')
|
||||
->with('files/known.jpg', 10, 10, true)
|
||||
->willReturn(new Image(\OC::$SERVERROOT.'/tests/data/testimage.jpg'));
|
||||
->method('getPreview')
|
||||
->with($this->equalTo($file), 10, 10, true)
|
||||
->willReturn($preview);
|
||||
|
||||
$ret = $this->apiController->getThumbnail(10, 10, 'known.jpg');
|
||||
|
||||
$this->assertEquals(Http::STATUS_OK, $ret->getStatus());
|
||||
$this->assertInstanceOf(Http\FileDisplayResponse::class, $ret);
|
||||
}
|
||||
|
||||
public function testUpdateFileSorting() {
|
||||
|
|
|
|||
|
|
@ -1,126 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2016, ownCloud, Inc.
|
||||
*
|
||||
* @author Björn Schießle <bjoern@schiessle.org>
|
||||
* @author Georg Ehrke <georg@owncloud.com>
|
||||
* @author Lukas Reschke <lukas@statuscode.ch>
|
||||
* @author Morris Jobke <hey@morrisjobke.de>
|
||||
* @author Roeland Jago Douma <roeland@famdouma.nl>
|
||||
* @author Thomas Müller <thomas.mueller@tmit.eu>
|
||||
*
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License, version 3,
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
OCP\JSON::checkAppEnabled('files_sharing');
|
||||
|
||||
\OC_User::setIncognitoMode(true);
|
||||
|
||||
$file = array_key_exists('file', $_GET) ? (string) $_GET['file'] : '';
|
||||
$maxX = array_key_exists('x', $_GET) ? (int) $_GET['x'] : '32';
|
||||
$maxY = array_key_exists('y', $_GET) ? (int) $_GET['y'] : '32';
|
||||
$scalingUp = array_key_exists('scalingup', $_GET) ? (bool) $_GET['scalingup'] : true;
|
||||
$token = array_key_exists('t', $_GET) ? (string) $_GET['t'] : '';
|
||||
$keepAspect = array_key_exists('a', $_GET) ? true : false;
|
||||
|
||||
if($token === ''){
|
||||
\OC_Response::setStatus(\OC_Response::STATUS_BAD_REQUEST);
|
||||
\OCP\Util::writeLog('core-preview', 'No token parameter was passed', \OCP\Util::DEBUG);
|
||||
exit;
|
||||
}
|
||||
|
||||
$linkedItem = \OCP\Share::getShareByToken($token);
|
||||
$shareManager = \OC::$server->getShareManager();
|
||||
$share = $shareManager->getShareByToken($token);
|
||||
if(!($share->getPermissions() & \OCP\Constants::PERMISSION_READ)) {
|
||||
OCP\JSON::error(array('data' => 'Share is not readable.'));
|
||||
exit();
|
||||
}
|
||||
|
||||
if($linkedItem === false || ($linkedItem['item_type'] !== 'file' && $linkedItem['item_type'] !== 'folder')) {
|
||||
\OC_Response::setStatus(\OC_Response::STATUS_NOT_FOUND);
|
||||
\OCP\Util::writeLog('core-preview', 'Passed token parameter is not valid', \OCP\Util::DEBUG);
|
||||
exit;
|
||||
}
|
||||
|
||||
if(!isset($linkedItem['uid_owner']) || !isset($linkedItem['file_source'])) {
|
||||
\OC_Response::setStatus(\OC_Response::STATUS_INTERNAL_SERVER_ERROR);
|
||||
\OCP\Util::writeLog('core-preview', 'Passed token seems to be valid, but it does not contain all necessary information . ("' . $token . '")', \OCP\Util::WARN);
|
||||
exit;
|
||||
}
|
||||
|
||||
$rootLinkItem = OCP\Share::resolveReShare($linkedItem);
|
||||
$userId = $rootLinkItem['uid_owner'];
|
||||
|
||||
OCP\JSON::checkUserExists($rootLinkItem['uid_owner']);
|
||||
\OC_Util::setupFS($userId);
|
||||
\OC\Files\Filesystem::initMountPoints($userId);
|
||||
$view = new \OC\Files\View('/' . $userId . '/files');
|
||||
|
||||
$pathId = $linkedItem['file_source'];
|
||||
$path = $view->getPath($pathId);
|
||||
|
||||
if($path === null) {
|
||||
\OC_Response::setStatus(\OC_Response::STATUS_NOT_FOUND);
|
||||
\OCP\Util::writeLog('core-preview', 'Could not resolve file for shared item', \OCP\Util::WARN);
|
||||
exit;
|
||||
}
|
||||
|
||||
$pathInfo = $view->getFileInfo($path);
|
||||
$sharedFile = null;
|
||||
|
||||
if($linkedItem['item_type'] === 'folder') {
|
||||
$isValid = \OC\Files\Filesystem::isValidPath($file);
|
||||
if(!$isValid) {
|
||||
\OC_Response::setStatus(\OC_Response::STATUS_BAD_REQUEST);
|
||||
\OCP\Util::writeLog('core-preview', 'Passed filename is not valid, might be malicious (file:"' . $file . '";ip:"' . \OC::$server->getRequest()->getRemoteAddress() . '")', \OCP\Util::WARN);
|
||||
exit;
|
||||
}
|
||||
$sharedFile = \OC\Files\Filesystem::normalizePath($file);
|
||||
}
|
||||
|
||||
if($linkedItem['item_type'] === 'file') {
|
||||
$parent = $pathInfo['parent'];
|
||||
$path = $view->getPath($parent);
|
||||
$sharedFile = $pathInfo['name'];
|
||||
}
|
||||
|
||||
$path = \OC\Files\Filesystem::normalizePath($path, false);
|
||||
if(substr($path, 0, 1) === '/') {
|
||||
$path = substr($path, 1);
|
||||
}
|
||||
|
||||
if($maxX === 0 || $maxY === 0) {
|
||||
\OC_Response::setStatus(\OC_Response::STATUS_BAD_REQUEST);
|
||||
\OCP\Util::writeLog('core-preview', 'x and/or y set to 0', \OCP\Util::DEBUG);
|
||||
exit;
|
||||
}
|
||||
|
||||
$root = 'files/' . $path;
|
||||
|
||||
try{
|
||||
$preview = new \OC\Preview($userId, $root);
|
||||
$preview->setFile($sharedFile);
|
||||
$preview->setMaxX($maxX);
|
||||
$preview->setMaxY($maxY);
|
||||
$preview->setScalingUp($scalingUp);
|
||||
$preview->setKeepAspect($keepAspect);
|
||||
|
||||
$preview->showPreview();
|
||||
} catch (\Exception $e) {
|
||||
\OC_Response::setStatus(\OC_Response::STATUS_INTERNAL_SERVER_ERROR);
|
||||
\OCP\Util::writeLog('core', $e->getmessage(), \OCP\Util::DEBUG);
|
||||
}
|
||||
|
|
@ -39,6 +39,17 @@ $application->registerRoutes($this, [
|
|||
'url' => '/testremote',
|
||||
'verb' => 'GET'
|
||||
],
|
||||
[
|
||||
'name' => 'PublicPreview#getPreview',
|
||||
'url' => '/publicpreview',
|
||||
'verb' => 'GET',
|
||||
],
|
||||
|
||||
[
|
||||
'name' => 'PublicPreview#getPreview',
|
||||
'url' => '/ajax/publicpreview.php',
|
||||
'verb' => 'GET',
|
||||
],
|
||||
],
|
||||
'ocs' => [
|
||||
/*
|
||||
|
|
@ -114,15 +125,8 @@ $application->registerRoutes($this, [
|
|||
]);
|
||||
|
||||
/** @var $this \OCP\Route\IRouter */
|
||||
$this->create('core_ajax_public_preview', '/publicpreview')->action(
|
||||
function() {
|
||||
require_once __DIR__ . '/../ajax/publicpreview.php';
|
||||
});
|
||||
|
||||
$this->create('files_sharing_ajax_list', 'ajax/list.php')
|
||||
->actionInclude('files_sharing/ajax/list.php');
|
||||
$this->create('files_sharing_ajax_publicpreview', 'ajax/publicpreview.php')
|
||||
->actionInclude('files_sharing/ajax/publicpreview.php');
|
||||
$this->create('sharing_external_shareinfo', '/shareinfo')
|
||||
->actionInclude('files_sharing/ajax/shareinfo.php');
|
||||
|
||||
|
|
|
|||
102
apps/files_sharing/lib/Controller/PublicPreviewController.php
Normal file
102
apps/files_sharing/lib/Controller/PublicPreviewController.php
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2016, Roeland Jago Douma <roeland@famdouma.nl>
|
||||
*
|
||||
* @author Roeland Jago Douma <roeland@famdouma.nl>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
namespace OCA\Files_Sharing\Controller;
|
||||
|
||||
use OCP\AppFramework\Controller;
|
||||
use OCP\AppFramework\Http;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\AppFramework\Http\FileDisplayResponse;
|
||||
use OCP\Constants;
|
||||
use OCP\Files\Folder;
|
||||
use OCP\Files\NotFoundException;
|
||||
use OCP\IPreview;
|
||||
use OCP\IRequest;
|
||||
use OCP\Share\Exceptions\ShareNotFound;
|
||||
use OCP\Share\IManager as ShareManager;
|
||||
|
||||
class PublicPreviewController extends Controller {
|
||||
|
||||
/** @var ShareManager */
|
||||
private $shareManager;
|
||||
|
||||
/** @var IPreview */
|
||||
private $previewManager;
|
||||
|
||||
public function __construct($appName,
|
||||
IRequest $request,
|
||||
ShareManager $shareManger,
|
||||
IPreview $previewManager) {
|
||||
parent::__construct($appName, $request);
|
||||
|
||||
$this->shareManager = $shareManger;
|
||||
$this->previewManager = $previewManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* @PublicPage
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* @param string $file
|
||||
* @param int $x
|
||||
* @param int $y
|
||||
* @param string $t
|
||||
* @param bool $a
|
||||
* @return DataResponse|FileDisplayResponse
|
||||
*/
|
||||
public function getPreview(
|
||||
$file = '',
|
||||
$x = 32,
|
||||
$y = 32,
|
||||
$t = '',
|
||||
$a = false
|
||||
) {
|
||||
|
||||
if ($t === '' || $x === 0 || $y === 0) {
|
||||
return new DataResponse([], Http::STATUS_BAD_REQUEST);
|
||||
}
|
||||
|
||||
try {
|
||||
$share = $this->shareManager->getShareByToken($t);
|
||||
} catch (ShareNotFound $e) {
|
||||
return new DataResponse([], Http::STATUS_NOT_FOUND);
|
||||
}
|
||||
|
||||
if (($share->getPermissions() & Constants::PERMISSION_READ) === 0) {
|
||||
return new DataResponse([], Http::STATUS_FORBIDDEN);
|
||||
}
|
||||
|
||||
try {
|
||||
$node = $share->getNode();
|
||||
if ($node instanceof Folder) {
|
||||
$file = $node->get($file);
|
||||
} else {
|
||||
$file = $node;
|
||||
}
|
||||
|
||||
$f = $this->previewManager->getPreview($file, $x, $y, !$a);
|
||||
return new FileDisplayResponse($f, Http::STATUS_OK, ['Content-Type' => $f->getMimeType()]);
|
||||
} catch (NotFoundException $e) {
|
||||
return new DataResponse([], Http::STATUS_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,193 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2016, Roeland Jago Douma <roeland@famdouma.nl>
|
||||
*
|
||||
* @author Roeland Jago Douma <roeland@famdouma.nl>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
namespace OCA\Files_Sharing\Tests\Controller;
|
||||
|
||||
use OCA\Files_Sharing\Controller\PublicPreviewController;
|
||||
use OCP\AppFramework\Http;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\AppFramework\Http\FileDisplayResponse;
|
||||
use OCP\Constants;
|
||||
use OCP\Files\File;
|
||||
use OCP\Files\Folder;
|
||||
use OCP\Files\NotFoundException;
|
||||
use OCP\Files\SimpleFS\ISimpleFile;
|
||||
use OCP\IPreview;
|
||||
use OCP\IRequest;
|
||||
use OCP\Share\Exceptions\ShareNotFound;
|
||||
use OCP\Share\IManager;
|
||||
use OCP\Share\IShare;
|
||||
use Punic\Data;
|
||||
use Test\TestCase;
|
||||
|
||||
class PublicPreviewControllerTest extends TestCase {
|
||||
|
||||
/** @var IPreview|\PHPUnit_Framework_MockObject_MockObject */
|
||||
private $previewManager;
|
||||
|
||||
/** @var IManager|\PHPUnit_Framework_MockObject_MockObject */
|
||||
private $shareManager;
|
||||
|
||||
/** @var PublicPreviewController */
|
||||
private $controller;
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->previewManager = $this->createMock(IPreview::class);
|
||||
$this->shareManager = $this->createMock(IManager::class);
|
||||
|
||||
$this->controller = new PublicPreviewController(
|
||||
'files_sharing',
|
||||
$this->createMock(IRequest::class),
|
||||
$this->shareManager,
|
||||
$this->previewManager
|
||||
);
|
||||
}
|
||||
|
||||
public function testInvalidToken() {
|
||||
$res = $this->controller->getPreview('file', 10, 10, '');
|
||||
$expected = new DataResponse([], Http::STATUS_BAD_REQUEST);
|
||||
|
||||
$this->assertEquals($expected, $res);
|
||||
}
|
||||
|
||||
public function testInvalidWidth() {
|
||||
$res = $this->controller->getPreview('file', 0);
|
||||
$expected = new DataResponse([], Http::STATUS_BAD_REQUEST);
|
||||
|
||||
$this->assertEquals($expected, $res);
|
||||
}
|
||||
|
||||
public function testInvalidHeight() {
|
||||
$res = $this->controller->getPreview('file', 10, 0);
|
||||
$expected = new DataResponse([], Http::STATUS_BAD_REQUEST);
|
||||
|
||||
$this->assertEquals($expected, $res);
|
||||
}
|
||||
|
||||
public function testInvalidShare() {
|
||||
$this->shareManager->method('getShareByToken')
|
||||
->with($this->equalTo('token'))
|
||||
->willThrowException(new ShareNotFound());
|
||||
|
||||
$res = $this->controller->getPreview('file', 10, 10, 'token');
|
||||
$expected = new DataResponse([], Http::STATUS_NOT_FOUND);
|
||||
|
||||
$this->assertEquals($expected, $res);
|
||||
}
|
||||
|
||||
public function testShareNotAccessable() {
|
||||
$share = $this->createMock(IShare::class);
|
||||
$this->shareManager->method('getShareByToken')
|
||||
->with($this->equalTo('token'))
|
||||
->willReturn($share);
|
||||
|
||||
$share->method('getPermissions')
|
||||
->willReturn(0);
|
||||
|
||||
$res = $this->controller->getPreview('file', 10, 10, 'token');
|
||||
$expected = new DataResponse([], Http::STATUS_FORBIDDEN);
|
||||
|
||||
$this->assertEquals($expected, $res);
|
||||
}
|
||||
|
||||
public function testPreviewFile() {
|
||||
$share = $this->createMock(IShare::class);
|
||||
$this->shareManager->method('getShareByToken')
|
||||
->with($this->equalTo('token'))
|
||||
->willReturn($share);
|
||||
|
||||
$share->method('getPermissions')
|
||||
->willReturn(Constants::PERMISSION_READ);
|
||||
|
||||
$file = $this->createMock(File::class);
|
||||
$share->method('getNode')
|
||||
->willReturn($file);
|
||||
|
||||
$preview = $this->createMock(ISimpleFile::class);
|
||||
$this->previewManager->method('getPreview')
|
||||
->with($this->equalTo($file), 10, 10, false)
|
||||
->willReturn($preview);
|
||||
|
||||
$preview->method('getMimeType')
|
||||
->willReturn('myMime');
|
||||
|
||||
$res = $this->controller->getPreview('file', 10, 10, 'token', true);
|
||||
$expected = new FileDisplayResponse($preview, Http::STATUS_OK, ['Content-Type' => 'myMime']);
|
||||
$this->assertEquals($expected, $res);
|
||||
}
|
||||
|
||||
public function testPreviewFolderInvalidFile() {
|
||||
$share = $this->createMock(IShare::class);
|
||||
$this->shareManager->method('getShareByToken')
|
||||
->with($this->equalTo('token'))
|
||||
->willReturn($share);
|
||||
|
||||
$share->method('getPermissions')
|
||||
->willReturn(Constants::PERMISSION_READ);
|
||||
|
||||
$folder = $this->createMock(Folder::class);
|
||||
$share->method('getNode')
|
||||
->willReturn($folder);
|
||||
|
||||
$folder->method('get')
|
||||
->with($this->equalTo('file'))
|
||||
->willThrowException(new NotFoundException());
|
||||
|
||||
$res = $this->controller->getPreview('file', 10, 10, 'token', true);
|
||||
$expected = new DataResponse([], Http::STATUS_NOT_FOUND);
|
||||
$this->assertEquals($expected, $res);
|
||||
}
|
||||
|
||||
|
||||
public function testPreviewFolderValidFile() {
|
||||
$share = $this->createMock(IShare::class);
|
||||
$this->shareManager->method('getShareByToken')
|
||||
->with($this->equalTo('token'))
|
||||
->willReturn($share);
|
||||
|
||||
$share->method('getPermissions')
|
||||
->willReturn(Constants::PERMISSION_READ);
|
||||
|
||||
$folder = $this->createMock(Folder::class);
|
||||
$share->method('getNode')
|
||||
->willReturn($folder);
|
||||
|
||||
$file = $this->createMock(File::class);
|
||||
$folder->method('get')
|
||||
->with($this->equalTo('file'))
|
||||
->willReturn($file);
|
||||
|
||||
$preview = $this->createMock(ISimpleFile::class);
|
||||
$this->previewManager->method('getPreview')
|
||||
->with($this->equalTo($file), 10, 10, false)
|
||||
->willReturn($preview);
|
||||
|
||||
$preview->method('getMimeType')
|
||||
->willReturn('myMime');
|
||||
|
||||
$res = $this->controller->getPreview('file', 10, 10, 'token', true);
|
||||
$expected = new FileDisplayResponse($preview, Http::STATUS_OK, ['Content-Type' => 'myMime']);
|
||||
$this->assertEquals($expected, $res);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2016, ownCloud, Inc.
|
||||
*
|
||||
* @author Björn Schießle <bjoern@schiessle.org>
|
||||
* @author Georg Ehrke <georg@owncloud.com>
|
||||
* @author Lukas Reschke <lukas@statuscode.ch>
|
||||
* @author Morris Jobke <hey@morrisjobke.de>
|
||||
* @author Roeland Jago Douma <roeland@famdouma.nl>
|
||||
* @author Vincent Petry <pvince81@owncloud.com>
|
||||
*
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License, version 3,
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
\OC_Util::checkLoggedIn();
|
||||
\OC::$server->getSession()->close();
|
||||
|
||||
if(!\OC_App::isEnabled('files_trashbin')){
|
||||
exit;
|
||||
}
|
||||
|
||||
$file = array_key_exists('file', $_GET) ? (string) $_GET['file'] : '';
|
||||
$maxX = array_key_exists('x', $_GET) ? (int) $_GET['x'] : '44';
|
||||
$maxY = array_key_exists('y', $_GET) ? (int) $_GET['y'] : '44';
|
||||
$scalingUp = array_key_exists('scalingup', $_GET) ? (bool) $_GET['scalingup'] : true;
|
||||
|
||||
if($file === '') {
|
||||
\OC_Response::setStatus(400); //400 Bad Request
|
||||
\OCP\Util::writeLog('core-preview', 'No file parameter was passed', \OCP\Util::DEBUG);
|
||||
exit;
|
||||
}
|
||||
|
||||
if($maxX === 0 || $maxY === 0) {
|
||||
\OC_Response::setStatus(400); //400 Bad Request
|
||||
\OCP\Util::writeLog('core-preview', 'x and/or y set to 0', \OCP\Util::DEBUG);
|
||||
exit;
|
||||
}
|
||||
|
||||
try{
|
||||
$preview = new \OC\Preview(\OC_User::getUser(), 'files_trashbin/files', $file);
|
||||
$view = new \OC\Files\View('/'.\OC_User::getUser(). '/files_trashbin/files');
|
||||
if ($view->is_dir($file)) {
|
||||
$mimetype = 'httpd/unix-directory';
|
||||
} else {
|
||||
$pathInfo = pathinfo(ltrim($file, '/'));
|
||||
$fileName = $pathInfo['basename'];
|
||||
// if in root dir
|
||||
if ($pathInfo['dirname'] === '.') {
|
||||
// cut off the .d* suffix
|
||||
$i = strrpos($fileName, '.');
|
||||
if ($i !== false) {
|
||||
$fileName = substr($fileName, 0, $i);
|
||||
}
|
||||
}
|
||||
$mimetype = \OC::$server->getMimeTypeDetector()->detectPath($fileName);
|
||||
}
|
||||
$preview->setMimetype($mimetype);
|
||||
$preview->setMaxX($maxX);
|
||||
$preview->setMaxY($maxY);
|
||||
$preview->setScalingUp($scalingUp);
|
||||
|
||||
$preview->showPreview();
|
||||
} catch (\OC\PreviewNotAvailableException $e) {
|
||||
\OC_Response::setStatus(404);
|
||||
}catch(\Exception $e) {
|
||||
\OC_Response::setStatus(500);
|
||||
\OCP\Util::writeLog('core', $e->getmessage(), \OCP\Util::DEBUG);
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2016, ownCloud, Inc.
|
||||
* @copyright Copyright (c) 2016, Roeland Jago Douma <roeland@famdouma.nl>
|
||||
*
|
||||
* @author Lukas Reschke <lukas@statuscode.ch>
|
||||
* @author Roeland Jago Douma <roeland@famdouma.nl>
|
||||
|
|
@ -25,9 +26,16 @@
|
|||
namespace OCA\Files_Trashbin\AppInfo;
|
||||
|
||||
$application = new Application();
|
||||
$application->registerRoutes($this, [
|
||||
'routes' => [
|
||||
[
|
||||
'name' => 'Preview#getPreview',
|
||||
'url' => '/ajax/preview.php',
|
||||
'verb' => 'GET',
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$this->create('core_ajax_trashbin_preview', 'ajax/preview.php')
|
||||
->actionInclude('files_trashbin/ajax/preview.php');
|
||||
$this->create('files_trashbin_ajax_delete', 'ajax/delete.php')
|
||||
->actionInclude('files_trashbin/ajax/delete.php');
|
||||
$this->create('files_trashbin_ajax_isEmpty', 'ajax/isEmpty.php')
|
||||
|
|
|
|||
119
apps/files_trashbin/lib/Controller/PreviewController.php
Normal file
119
apps/files_trashbin/lib/Controller/PreviewController.php
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2016, Roeland Jago Douma <roeland@famdouma.nl>
|
||||
*
|
||||
* @author Roeland Jago Douma <roeland@famdouma.nl>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
namespace OCA\Files_Trashbin\Controller;
|
||||
|
||||
use OCP\AppFramework\Controller;
|
||||
use OCP\AppFramework\Http;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\Files\File;
|
||||
use OCP\Files\Folder;
|
||||
use OCP\Files\IMimeTypeDetector;
|
||||
use OCP\Files\IRootFolder;
|
||||
use OCP\Files\NotFoundException;
|
||||
use OCP\IPreview;
|
||||
use OCP\IRequest;
|
||||
|
||||
class PreviewController extends Controller {
|
||||
|
||||
/** @var IRootFolder */
|
||||
private $rootFolder;
|
||||
|
||||
/** @var string */
|
||||
private $userId;
|
||||
|
||||
/** @var IMimeTypeDetector */
|
||||
private $mimeTypeDetector;
|
||||
|
||||
/** @var IPreview */
|
||||
private $previewManager;
|
||||
|
||||
/**
|
||||
* @param string $appName
|
||||
* @param IRequest $request
|
||||
* @param IRootFolder $rootFolder
|
||||
* @param $userId
|
||||
* @param IMimeTypeDetector $mimeTypeDetector
|
||||
* @param IPreview $previewManager
|
||||
*/
|
||||
public function __construct($appName,
|
||||
IRequest $request,
|
||||
IRootFolder $rootFolder,
|
||||
$userId,
|
||||
IMimeTypeDetector $mimeTypeDetector,
|
||||
IPreview $previewManager) {
|
||||
parent::__construct($appName, $request);
|
||||
|
||||
$this->rootFolder = $rootFolder;
|
||||
$this->userId = $userId;
|
||||
$this->mimeTypeDetector = $mimeTypeDetector;
|
||||
$this->previewManager = $previewManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* @param string $file
|
||||
* @param int $x
|
||||
* @param int $y
|
||||
* @return DataResponse|Http\FileDisplayResponse
|
||||
*/
|
||||
public function getPreview(
|
||||
$file = '',
|
||||
$x = 44,
|
||||
$y = 44
|
||||
) {
|
||||
if ($file === '') {
|
||||
return new DataResponse([], Http::STATUS_BAD_REQUEST);
|
||||
}
|
||||
|
||||
if ($x === 0 || $y === 0) {
|
||||
return new DataResponse([], Http::STATUS_BAD_REQUEST);
|
||||
}
|
||||
|
||||
try {
|
||||
$userFolder = $this->rootFolder->getUserFolder($this->userId);
|
||||
/** @var Folder $trash */
|
||||
$trash = $userFolder->getParent()->get('files_trashbin/files');
|
||||
$trashFile = $trash->get($file);
|
||||
|
||||
if ($trashFile instanceof Folder) {
|
||||
return new DataResponse([], Http::STATUS_BAD_REQUEST);
|
||||
}
|
||||
|
||||
/** @var File $trashFile */
|
||||
$fileName = $trashFile->getName();
|
||||
$i = strrpos($fileName, '.');
|
||||
if ($i !== false) {
|
||||
$fileName = substr($fileName, 0, $i);
|
||||
}
|
||||
|
||||
$mimeType = $this->mimeTypeDetector->detectPath($fileName);
|
||||
|
||||
$f = $this->previewManager->getPreview($trashFile, $x, $y, true, IPreview::MODE_FILL, $mimeType);
|
||||
return new Http\FileDisplayResponse($f, Http::STATUS_OK, ['Content-Type' => $f->getMimeType()]);
|
||||
} catch (NotFoundException $e) {
|
||||
return new DataResponse([], Http::STATUS_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
}
|
||||
181
apps/files_trashbin/tests/Controller/PreviewControllerTest.php
Normal file
181
apps/files_trashbin/tests/Controller/PreviewControllerTest.php
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2016, Roeland Jago Douma <roeland@famdouma.nl>
|
||||
*
|
||||
* @author Roeland Jago Douma <roeland@famdouma.nl>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
namespace OCA\Files_Trashbin\Tests\Controller;
|
||||
|
||||
use OCA\Files_Trashbin\Controller\PreviewController;
|
||||
use OCP\AppFramework\Http;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\AppFramework\Http\FileDisplayResponse;
|
||||
use OCP\Files\File;
|
||||
use OCP\Files\Folder;
|
||||
use OCP\Files\IMimeTypeDetector;
|
||||
use OCP\Files\IRootFolder;
|
||||
use OCP\Files\NotFoundException;
|
||||
use OCP\Files\SimpleFS\ISimpleFile;
|
||||
use OCP\IPreview;
|
||||
use OCP\IRequest;
|
||||
use Test\TestCase;
|
||||
|
||||
class PreviewControllerTest extends TestCase {
|
||||
|
||||
/** @var IRootFolder|\PHPUnit_Framework_MockObject_MockObject */
|
||||
private $rootFolder;
|
||||
|
||||
/** @var string */
|
||||
private $userId;
|
||||
|
||||
/** @var IMimeTypeDetector|\PHPUnit_Framework_MockObject_MockObject */
|
||||
private $mimeTypeDetector;
|
||||
|
||||
/** @var IPreview|\PHPUnit_Framework_MockObject_MockObject */
|
||||
private $previewManager;
|
||||
|
||||
/** @var PreviewController */
|
||||
private $controller;
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->rootFolder = $this->createMock(IRootFolder::class);
|
||||
$this->userId = 'user';
|
||||
$this->mimeTypeDetector = $this->createMock(IMimeTypeDetector::class);
|
||||
$this->previewManager = $this->createMock(IPreview::class);
|
||||
|
||||
$this->controller = new PreviewController(
|
||||
'files_versions',
|
||||
$this->createMock(IRequest::class),
|
||||
$this->rootFolder,
|
||||
$this->userId,
|
||||
$this->mimeTypeDetector,
|
||||
$this->previewManager
|
||||
);
|
||||
}
|
||||
|
||||
public function testInvalidFile() {
|
||||
$res = $this->controller->getPreview('');
|
||||
$expected = new DataResponse([], Http::STATUS_BAD_REQUEST);
|
||||
|
||||
$this->assertEquals($expected, $res);
|
||||
}
|
||||
|
||||
public function testInvalidWidth() {
|
||||
$res = $this->controller->getPreview('file', 0);
|
||||
$expected = new DataResponse([], Http::STATUS_BAD_REQUEST);
|
||||
|
||||
$this->assertEquals($expected, $res);
|
||||
}
|
||||
|
||||
public function testInvalidHeight() {
|
||||
$res = $this->controller->getPreview('file', 10, 0);
|
||||
$expected = new DataResponse([], Http::STATUS_BAD_REQUEST);
|
||||
|
||||
$this->assertEquals($expected, $res);
|
||||
}
|
||||
|
||||
public function testValidPreview() {
|
||||
$userFolder = $this->createMock(Folder::class);
|
||||
$userRoot = $this->createMock(Folder::class);
|
||||
$trash = $this->createMock(Folder::class);
|
||||
|
||||
$this->rootFolder->method('getUserFolder')
|
||||
->with($this->userId)
|
||||
->willReturn($userFolder);
|
||||
$userFolder->method('getParent')
|
||||
->willReturn($userRoot);
|
||||
$userRoot->method('get')
|
||||
->with('files_trashbin/files')
|
||||
->willReturn($trash);
|
||||
|
||||
$this->mimeTypeDetector->method('detectPath')
|
||||
->with($this->equalTo('file'))
|
||||
->willReturn('myMime');
|
||||
|
||||
$file = $this->createMock(File::class);
|
||||
$trash->method('get')
|
||||
->with($this->equalTo('file.1234'))
|
||||
->willReturn($file);
|
||||
$file->method('getName')
|
||||
->willReturn('file.1234');
|
||||
|
||||
$preview = $this->createMock(ISimpleFile::class);
|
||||
$this->previewManager->method('getPreview')
|
||||
->with($this->equalTo($file), 10, 10, true, IPreview::MODE_FILL, 'myMime')
|
||||
->willReturn($preview);
|
||||
$preview->method('getMimeType')
|
||||
->willReturn('previewMime');
|
||||
|
||||
$res = $this->controller->getPreview('file.1234', 10, 10);
|
||||
$expected = new FileDisplayResponse($preview, Http::STATUS_OK, ['Content-Type' => 'previewMime']);
|
||||
|
||||
$this->assertEquals($expected, $res);
|
||||
}
|
||||
|
||||
public function testTrashFileNotFound() {
|
||||
$userFolder = $this->createMock(Folder::class);
|
||||
$userRoot = $this->createMock(Folder::class);
|
||||
$trash = $this->createMock(Folder::class);
|
||||
|
||||
$this->rootFolder->method('getUserFolder')
|
||||
->with($this->userId)
|
||||
->willReturn($userFolder);
|
||||
$userFolder->method('getParent')
|
||||
->willReturn($userRoot);
|
||||
$userRoot->method('get')
|
||||
->with('files_trashbin/files')
|
||||
->willReturn($trash);
|
||||
|
||||
$trash->method('get')
|
||||
->with($this->equalTo('file.1234'))
|
||||
->willThrowException(new NotFoundException());
|
||||
|
||||
$res = $this->controller->getPreview('file.1234', 10, 10);
|
||||
$expected = new DataResponse([], Http::STATUS_NOT_FOUND);
|
||||
|
||||
$this->assertEquals($expected, $res);
|
||||
}
|
||||
|
||||
public function testTrashFolder() {
|
||||
$userFolder = $this->createMock(Folder::class);
|
||||
$userRoot = $this->createMock(Folder::class);
|
||||
$trash = $this->createMock(Folder::class);
|
||||
|
||||
$this->rootFolder->method('getUserFolder')
|
||||
->with($this->userId)
|
||||
->willReturn($userFolder);
|
||||
$userFolder->method('getParent')
|
||||
->willReturn($userRoot);
|
||||
$userRoot->method('get')
|
||||
->with('files_trashbin/files')
|
||||
->willReturn($trash);
|
||||
|
||||
$folder = $this->createMock(Folder::class);
|
||||
$trash->method('get')
|
||||
->with($this->equalTo('folder'))
|
||||
->willReturn($folder);
|
||||
|
||||
$res = $this->controller->getPreview('folder', 10, 10);
|
||||
$expected = new DataResponse([], Http::STATUS_BAD_REQUEST);
|
||||
|
||||
$this->assertEquals($expected, $res);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2016, ownCloud, Inc.
|
||||
*
|
||||
* @author Björn Schießle <bjoern@schiessle.org>
|
||||
* @author Morris Jobke <hey@morrisjobke.de>
|
||||
* @author Roeland Jago Douma <roeland@famdouma.nl>
|
||||
* @author Thomas Müller <thomas.mueller@tmit.eu>
|
||||
* @author Vincent Petry <pvince81@owncloud.com>
|
||||
*
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License, version 3,
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
\OC_Util::checkLoggedIn();
|
||||
|
||||
if(!\OC_App::isEnabled('files_versions')){
|
||||
exit;
|
||||
}
|
||||
|
||||
$file = array_key_exists('file', $_GET) ? (string) urldecode($_GET['file']) : '';
|
||||
$maxX = array_key_exists('x', $_GET) ? (int) $_GET['x'] : 44;
|
||||
$maxY = array_key_exists('y', $_GET) ? (int) $_GET['y'] : 44;
|
||||
$version = array_key_exists('version', $_GET) ? $_GET['version'] : '';
|
||||
$scalingUp = array_key_exists('scalingup', $_GET) ? (bool) $_GET['scalingup'] : true;
|
||||
|
||||
if($file === '' && $version === '') {
|
||||
\OC_Response::setStatus(400); //400 Bad Request
|
||||
\OCP\Util::writeLog('versions-preview', 'No file parameter was passed', \OCP\Util::DEBUG);
|
||||
exit;
|
||||
}
|
||||
|
||||
if($maxX === 0 || $maxY === 0) {
|
||||
\OC_Response::setStatus(400); //400 Bad Request
|
||||
\OCP\Util::writeLog('versions-preview', 'x and/or y set to 0', \OCP\Util::DEBUG);
|
||||
exit;
|
||||
}
|
||||
|
||||
try {
|
||||
list($user, $file) = \OCA\Files_Versions\Storage::getUidAndFilename($file);
|
||||
$preview = new \OC\Preview($user, 'files_versions', $file.'.v'.$version);
|
||||
$mimetype = \OC::$server->getMimeTypeDetector()->detectPath($file);
|
||||
$preview->setMimetype($mimetype);
|
||||
$preview->setMaxX($maxX);
|
||||
$preview->setMaxY($maxY);
|
||||
$preview->setScalingUp($scalingUp);
|
||||
|
||||
$preview->showPreview();
|
||||
} catch (\OCP\Files\NotFoundException $e) {
|
||||
\OC_Response::setStatus(404);
|
||||
\OCP\Util::writeLog('core', $e->getmessage(), \OCP\Util::DEBUG);
|
||||
} catch (\Exception $e) {
|
||||
\OC_Response::setStatus(500);
|
||||
\OCP\Util::writeLog('core', $e->getmessage(), \OCP\Util::DEBUG);
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2016, ownCloud, Inc.
|
||||
* @copyright Copyright (c) 2016, Roeland Jago Douma <roeland@famdouma.nl>
|
||||
*
|
||||
* @author Björn Schießle <bjoern@schiessle.org>
|
||||
* @author Jörn Friedrich Dreyer <jfd@butonic.de>
|
||||
|
|
@ -29,13 +30,17 @@
|
|||
namespace OCA\Files_Versions\AppInfo;
|
||||
|
||||
$application = new Application();
|
||||
$application->registerRoutes($this, [
|
||||
'routes' => [
|
||||
[
|
||||
'name' => 'Preview#getPreview',
|
||||
'url' => '/preview',
|
||||
'verb' => 'GET',
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
/** @var $this \OCP\Route\IRouter */
|
||||
$this->create('core_ajax_versions_preview', '/preview')->action(
|
||||
function() {
|
||||
require_once __DIR__ . '/../ajax/preview.php';
|
||||
});
|
||||
|
||||
$this->create('files_versions_download', 'download.php')
|
||||
->actionInclude('files_versions/download.php');
|
||||
$this->create('files_versions_ajax_getVersions', 'ajax/getVersions.php')
|
||||
|
|
|
|||
99
apps/files_versions/lib/Controller/PreviewController.php
Normal file
99
apps/files_versions/lib/Controller/PreviewController.php
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2016, Roeland Jago Douma <roeland@famdouma.nl>
|
||||
*
|
||||
* @author Roeland Jago Douma <roeland@famdouma.nl>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
namespace OCA\Files_Versions\Controller;
|
||||
|
||||
use OCP\AppFramework\Controller;
|
||||
use OCP\AppFramework\Http;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\AppFramework\Http\FileDisplayResponse;
|
||||
use OCP\Files\File;
|
||||
use OCP\Files\Folder;
|
||||
use OCP\Files\IMimeTypeDetector;
|
||||
use OCP\Files\IRootFolder;
|
||||
use OCP\Files\NotFoundException;
|
||||
use OCP\IPreview;
|
||||
use OCP\IRequest;
|
||||
|
||||
class PreviewController extends Controller {
|
||||
|
||||
/** @var IRootFolder */
|
||||
private $rootFolder;
|
||||
|
||||
/** @var string */
|
||||
private $userId;
|
||||
|
||||
/** @var IMimeTypeDetector */
|
||||
private $mimeTypeDetector;
|
||||
|
||||
/** @var IPreview */
|
||||
private $previewManager;
|
||||
|
||||
public function __construct($appName,
|
||||
IRequest $request,
|
||||
IRootFolder $rootFolder,
|
||||
$userId,
|
||||
IMimeTypeDetector $mimeTypeDetector,
|
||||
IPreview $previewManager) {
|
||||
parent::__construct($appName, $request);
|
||||
|
||||
$this->rootFolder = $rootFolder;
|
||||
$this->userId = $userId;
|
||||
$this->mimeTypeDetector = $mimeTypeDetector;
|
||||
$this->previewManager = $previewManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* @param string $file
|
||||
* @param int $x
|
||||
* @param int $y
|
||||
* @param string $version
|
||||
* @return DataResponse|FileDisplayResponse
|
||||
*/
|
||||
public function getPreview(
|
||||
$file = '',
|
||||
$x = 44,
|
||||
$y = 44,
|
||||
$version = ''
|
||||
) {
|
||||
if($file === '' || $version === '' || $x === 0 || $y === 0) {
|
||||
return new DataResponse([], Http::STATUS_BAD_REQUEST);
|
||||
}
|
||||
|
||||
try {
|
||||
$userFolder = $this->rootFolder->getUserFolder($this->userId);
|
||||
/** @var Folder $versionFolder */
|
||||
$versionFolder = $userFolder->getParent()->get('files_versions');
|
||||
$mimeType = $this->mimeTypeDetector->detectPath($file);
|
||||
$file = $versionFolder->get($file.'.v'.$version);
|
||||
|
||||
/** @var File $file */
|
||||
$f = $this->previewManager->getPreview($file, $x, $y, true, IPreview::MODE_FILL, $mimeType);
|
||||
return new FileDisplayResponse($f, Http::STATUS_OK, ['Content-Type' => $f->getMimeType()]);
|
||||
} catch (NotFoundException $e) {
|
||||
return new DataResponse([], Http::STATUS_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -462,7 +462,7 @@ class Storage {
|
|||
if (empty($userFullPath)) {
|
||||
$versions[$key]['preview'] = '';
|
||||
} else {
|
||||
$versions[$key]['preview'] = \OCP\Util::linkToRoute('core_ajax_versions_preview', array('file' => $userFullPath, 'version' => $timestamp));
|
||||
$versions[$key]['preview'] = \OC::$server->getURLGenerator('files_version.Preview.getPreview', ['file' => $userFullPath, 'version' => $timestamp]);
|
||||
}
|
||||
$versions[$key]['path'] = Filesystem::normalizePath($pathinfo['dirname'] . '/' . $filename);
|
||||
$versions[$key]['name'] = $versionedFile;
|
||||
|
|
|
|||
167
apps/files_versions/tests/Controller/PreviewControllerTest.php
Normal file
167
apps/files_versions/tests/Controller/PreviewControllerTest.php
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2016, Roeland Jago Douma <roeland@famdouma.nl>
|
||||
*
|
||||
* @author Roeland Jago Douma <roeland@famdouma.nl>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
namespace OCA\Files_Versions\Tests\Controller;
|
||||
|
||||
use OCA\Files_Versions\Controller\PreviewController;
|
||||
use OCP\AppFramework\Http;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\AppFramework\Http\FileDisplayResponse;
|
||||
use OCP\Files\File;
|
||||
use OCP\Files\Folder;
|
||||
use OCP\Files\IMimeTypeDetector;
|
||||
use OCP\Files\IRootFolder;
|
||||
use OCP\Files\NotFoundException;
|
||||
use OCP\Files\SimpleFS\ISimpleFile;
|
||||
use OCP\IPreview;
|
||||
use OCP\IRequest;
|
||||
use Test\TestCase;
|
||||
|
||||
class PreviewControllerTest extends TestCase {
|
||||
|
||||
/** @var IRootFolder|\PHPUnit_Framework_MockObject_MockObject */
|
||||
private $rootFolder;
|
||||
|
||||
/** @var string */
|
||||
private $userId;
|
||||
|
||||
/** @var IMimeTypeDetector|\PHPUnit_Framework_MockObject_MockObject */
|
||||
private $mimeTypeDetector;
|
||||
|
||||
/** @var IPreview|\PHPUnit_Framework_MockObject_MockObject */
|
||||
private $previewManager;
|
||||
|
||||
/** @var PreviewController */
|
||||
private $controller;
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->rootFolder = $this->createMock(IRootFolder::class);
|
||||
$this->userId = 'user';
|
||||
$this->mimeTypeDetector = $this->createMock(IMimeTypeDetector::class);
|
||||
$this->previewManager = $this->createMock(IPreview::class);
|
||||
|
||||
$this->controller = new PreviewController(
|
||||
'files_versions',
|
||||
$this->createMock(IRequest::class),
|
||||
$this->rootFolder,
|
||||
$this->userId,
|
||||
$this->mimeTypeDetector,
|
||||
$this->previewManager
|
||||
);
|
||||
}
|
||||
|
||||
public function testInvalidFile() {
|
||||
$res = $this->controller->getPreview('');
|
||||
$expected = new DataResponse([], Http::STATUS_BAD_REQUEST);
|
||||
|
||||
$this->assertEquals($expected, $res);
|
||||
}
|
||||
|
||||
public function testInvalidWidth() {
|
||||
$res = $this->controller->getPreview('file', 0);
|
||||
$expected = new DataResponse([], Http::STATUS_BAD_REQUEST);
|
||||
|
||||
$this->assertEquals($expected, $res);
|
||||
}
|
||||
|
||||
public function testInvalidHeight() {
|
||||
$res = $this->controller->getPreview('file', 10, 0);
|
||||
$expected = new DataResponse([], Http::STATUS_BAD_REQUEST);
|
||||
|
||||
$this->assertEquals($expected, $res);
|
||||
}
|
||||
|
||||
public function testInvalidVersion() {
|
||||
$res = $this->controller->getPreview('file', 10, 0);
|
||||
$expected = new DataResponse([], Http::STATUS_BAD_REQUEST);
|
||||
|
||||
$this->assertEquals($expected, $res);
|
||||
}
|
||||
|
||||
public function testValidPreview() {
|
||||
$userFolder = $this->createMock(Folder::class);
|
||||
$userRoot = $this->createMock(Folder::class);
|
||||
$versions = $this->createMock(Folder::class);
|
||||
|
||||
$this->rootFolder->method('getUserFolder')
|
||||
->with($this->userId)
|
||||
->willReturn($userFolder);
|
||||
$userFolder->method('getParent')
|
||||
->willReturn($userRoot);
|
||||
$userRoot->method('get')
|
||||
->with('files_versions')
|
||||
->willReturn($versions);
|
||||
|
||||
$this->mimeTypeDetector->method('detectPath')
|
||||
->with($this->equalTo('file'))
|
||||
->willReturn('myMime');
|
||||
|
||||
$file = $this->createMock(File::class);
|
||||
$versions->method('get')
|
||||
->with($this->equalTo('file.v42'))
|
||||
->willReturn($file);
|
||||
|
||||
$preview = $this->createMock(ISimpleFile::class);
|
||||
$this->previewManager->method('getPreview')
|
||||
->with($this->equalTo($file), 10, 10, true, IPreview::MODE_FILL, 'myMime')
|
||||
->willReturn($preview);
|
||||
$preview->method('getMimeType')
|
||||
->willReturn('previewMime');
|
||||
|
||||
$res = $this->controller->getPreview('file', 10, 10, '42');
|
||||
$expected = new FileDisplayResponse($preview, Http::STATUS_OK, ['Content-Type' => 'previewMime']);
|
||||
|
||||
$this->assertEquals($expected, $res);
|
||||
}
|
||||
|
||||
public function testVersionNotFound() {
|
||||
$userFolder = $this->createMock(Folder::class);
|
||||
$userRoot = $this->createMock(Folder::class);
|
||||
$versions = $this->createMock(Folder::class);
|
||||
|
||||
$this->rootFolder->method('getUserFolder')
|
||||
->with($this->userId)
|
||||
->willReturn($userFolder);
|
||||
$userFolder->method('getParent')
|
||||
->willReturn($userRoot);
|
||||
$userRoot->method('get')
|
||||
->with('files_versions')
|
||||
->willReturn($versions);
|
||||
|
||||
$this->mimeTypeDetector->method('detectPath')
|
||||
->with($this->equalTo('file'))
|
||||
->willReturn('myMime');
|
||||
|
||||
$file = $this->createMock(File::class);
|
||||
$versions->method('get')
|
||||
->with($this->equalTo('file.v42'))
|
||||
->willThrowException(new NotFoundException());
|
||||
|
||||
$res = $this->controller->getPreview('file', 10, 10, '42');
|
||||
$expected = new DataResponse([], Http::STATUS_NOT_FOUND);
|
||||
|
||||
$this->assertEquals($expected, $res);
|
||||
}
|
||||
|
||||
}
|
||||
132
core/Controller/PreviewController.php
Normal file
132
core/Controller/PreviewController.php
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2016, Roeland Jago Douma <roeland@famdouma.nl>
|
||||
*
|
||||
* @author Roeland Jago Douma <roeland@famdouma.nl>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OC\Core\Controller;
|
||||
|
||||
use OCP\AppFramework\Controller;
|
||||
use OCP\AppFramework\Utility\ITimeFactory;
|
||||
use OCP\Files\File;
|
||||
use OCP\AppFramework\Http;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\AppFramework\Http\FileDisplayResponse;
|
||||
use OCP\Files\IRootFolder;
|
||||
use OCP\Files\NotFoundException;
|
||||
use OCP\IPreview;
|
||||
use OCP\IRequest;
|
||||
|
||||
class PreviewController extends Controller {
|
||||
|
||||
/** @var string */
|
||||
private $userId;
|
||||
|
||||
/** @var IRootFolder */
|
||||
private $root;
|
||||
|
||||
/** @var IPreview */
|
||||
private $preview;
|
||||
|
||||
/** @var ITimeFactory */
|
||||
private $timeFactory;
|
||||
|
||||
/**
|
||||
* PreviewController constructor.
|
||||
*
|
||||
* @param string $appName
|
||||
* @param IRequest $request
|
||||
* @param IPreview $preview
|
||||
* @param IRootFolder $root
|
||||
* @param string $userId
|
||||
*/
|
||||
public function __construct($appName,
|
||||
IRequest $request,
|
||||
IPreview $preview,
|
||||
IRootFolder $root,
|
||||
$userId,
|
||||
ITimeFactory $timeFactory
|
||||
) {
|
||||
parent::__construct($appName, $request);
|
||||
|
||||
$this->preview = $preview;
|
||||
$this->root = $root;
|
||||
$this->userId = $userId;
|
||||
$this->timeFactory = $timeFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* @param string $file
|
||||
* @param int $x
|
||||
* @param int $y
|
||||
* @param bool $a
|
||||
* @param bool $forceIcon
|
||||
* @param string $mode
|
||||
* @return DataResponse|Http\FileDisplayResponse
|
||||
*/
|
||||
public function getPreview(
|
||||
$file = '',
|
||||
$x = 32,
|
||||
$y = 32,
|
||||
$a = false,
|
||||
$forceIcon = true,
|
||||
$mode = 'fill') {
|
||||
|
||||
if ($file === '' || $x === 0 || $y === 0) {
|
||||
return new DataResponse([], Http::STATUS_BAD_REQUEST);
|
||||
}
|
||||
|
||||
try {
|
||||
$userFolder = $this->root->getUserFolder($this->userId);
|
||||
$file = $userFolder->get($file);
|
||||
} catch (NotFoundException $e) {
|
||||
return new DataResponse([], Http::STATUS_NOT_FOUND);
|
||||
}
|
||||
|
||||
if (!($file instanceof File) || (!$forceIcon && !$this->preview->isAvailable($file))) {
|
||||
return new DataResponse([], Http::STATUS_NOT_FOUND);
|
||||
} else if (!$file->isReadable()) {
|
||||
return new DataResponse([], Http::STATUS_FORBIDDEN);
|
||||
}
|
||||
|
||||
try {
|
||||
$f = $this->preview->getPreview($file, $x, $y, !$a, $mode);
|
||||
$response = new FileDisplayResponse($f, Http::STATUS_OK, ['Content-Type' => $f->getMimeType()]);
|
||||
|
||||
// Let cache this!
|
||||
$response->addHeader('Pragma', 'public');
|
||||
|
||||
// Cache previews for 24H
|
||||
$response->cacheFor(3600 * 24);
|
||||
$expires = new \DateTime();
|
||||
$expires->setTimestamp($this->timeFactory->getTime());
|
||||
$expires->add(new \DateInterval('P1D'));
|
||||
$response->addHeader('Expires', $expires->format(\DateTime::RFC2822));
|
||||
|
||||
return $response;
|
||||
} catch (NotFoundException $e) {
|
||||
return new DataResponse([], Http::STATUS_NOT_FOUND);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2016, ownCloud, Inc.
|
||||
*
|
||||
* @author Georg Ehrke <georg@owncloud.com>
|
||||
* @author Joas Schilling <coding@schilljs.com>
|
||||
* @author Lukas Reschke <lukas@statuscode.ch>
|
||||
* @author Morris Jobke <hey@morrisjobke.de>
|
||||
* @author Robin Appelman <robin@icewind.nl>
|
||||
* @author Thomas Müller <thomas.mueller@tmit.eu>
|
||||
*
|
||||
* @license AGPL-3.0
|
||||
*
|
||||
* This code is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License, version 3,
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
\OC_Util::checkLoggedIn();
|
||||
\OC::$server->getSession()->close();
|
||||
|
||||
$file = array_key_exists('file', $_GET) ? (string)$_GET['file'] : '';
|
||||
$maxX = array_key_exists('x', $_GET) ? (int)$_GET['x'] : '32';
|
||||
$maxY = array_key_exists('y', $_GET) ? (int)$_GET['y'] : '32';
|
||||
$scalingUp = array_key_exists('scalingup', $_GET) ? (bool)$_GET['scalingup'] : true;
|
||||
$keepAspect = array_key_exists('a', $_GET) ? true : false;
|
||||
$always = array_key_exists('forceIcon', $_GET) ? (bool)$_GET['forceIcon'] : true;
|
||||
$mode = array_key_exists('mode', $_GET) ? $_GET['mode'] : 'fill';
|
||||
|
||||
if ($file === '') {
|
||||
//400 Bad Request
|
||||
\OC_Response::setStatus(400);
|
||||
\OCP\Util::writeLog('core-preview', 'No file parameter was passed', \OCP\Util::DEBUG);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($maxX === 0 || $maxY === 0) {
|
||||
//400 Bad Request
|
||||
\OC_Response::setStatus(400);
|
||||
\OCP\Util::writeLog('core-preview', 'x and/or y set to 0', \OCP\Util::DEBUG);
|
||||
exit;
|
||||
}
|
||||
|
||||
$info = \OC\Files\Filesystem::getFileInfo($file);
|
||||
|
||||
if (!$info instanceof OCP\Files\FileInfo || !$always && !\OC::$server->getPreviewManager()->isAvailable($info)) {
|
||||
\OC_Response::setStatus(404);
|
||||
} else if (!$info->isReadable()) {
|
||||
\OC_Response::setStatus(403);
|
||||
} else {
|
||||
$preview = new \OC\Preview(\OC_User::getUser(), 'files');
|
||||
$preview->setFile($file, $info);
|
||||
$preview->setMaxX($maxX);
|
||||
$preview->setMaxY($maxY);
|
||||
$preview->setScalingUp($scalingUp);
|
||||
$preview->setMode($mode);
|
||||
$preview->setKeepAspect($keepAspect);
|
||||
$preview->showPreview();
|
||||
}
|
||||
|
|
@ -52,6 +52,8 @@ $application->registerRoutes($this, [
|
|||
['name' => 'TwoFactorChallenge#showChallenge', 'url' => '/login/challenge/{challengeProviderId}', 'verb' => 'GET'],
|
||||
['name' => 'TwoFactorChallenge#solveChallenge', 'url' => '/login/challenge/{challengeProviderId}', 'verb' => 'POST'],
|
||||
['name' => 'OCJS#getConfig', 'url' => '/core/js/oc.js', 'verb' => 'GET'],
|
||||
['name' => 'Preview#getPreview', 'url' => '/core/preview', 'verb' => 'GET'],
|
||||
['name' => 'Preview#getPreview', 'url' => '/core/preview.png', 'verb' => 'GET'],
|
||||
],
|
||||
'ocs' => [
|
||||
['root' => '/cloud', 'name' => 'OCS#getCapabilities', 'url' => '/capabilities', 'verb' => 'GET'],
|
||||
|
|
@ -68,10 +70,6 @@ $application->registerRoutes($this, [
|
|||
$this->create('search_ajax_search', '/core/search')
|
||||
->actionInclude('core/search/ajax/search.php');
|
||||
// Routing
|
||||
$this->create('core_ajax_preview', '/core/preview')
|
||||
->actionInclude('core/ajax/preview.php');
|
||||
$this->create('core_ajax_preview', '/core/preview.png')
|
||||
->actionInclude('core/ajax/preview.php');
|
||||
$this->create('core_ajax_update', '/core/ajax/update.php')
|
||||
->actionInclude('core/ajax/update.php');
|
||||
|
||||
|
|
|
|||
|
|
@ -411,6 +411,7 @@ return array(
|
|||
'OC\\Core\\Controller\\LostController' => $baseDir . '/core/Controller/LostController.php',
|
||||
'OC\\Core\\Controller\\OCJSController' => $baseDir . '/core/Controller/OCJSController.php',
|
||||
'OC\\Core\\Controller\\OCSController' => $baseDir . '/core/Controller/OCSController.php',
|
||||
'OC\\Core\\Controller\\PreviewController' => $baseDir . '/core/Controller/PreviewController.php',
|
||||
'OC\\Core\\Controller\\SetupController' => $baseDir . '/core/Controller/SetupController.php',
|
||||
'OC\\Core\\Controller\\TwoFactorChallengeController' => $baseDir . '/core/Controller/TwoFactorChallengeController.php',
|
||||
'OC\\Core\\Controller\\UserController' => $baseDir . '/core/Controller/UserController.php',
|
||||
|
|
@ -620,6 +621,8 @@ return array(
|
|||
'OC\\Preview\\Bitmap' => $baseDir . '/lib/private/Preview/Bitmap.php',
|
||||
'OC\\Preview\\Font' => $baseDir . '/lib/private/Preview/Font.php',
|
||||
'OC\\Preview\\GIF' => $baseDir . '/lib/private/Preview/GIF.php',
|
||||
'OC\\Preview\\Generator' => $baseDir . '/lib/private/Preview/Generator.php',
|
||||
'OC\\Preview\\GeneratorHelper' => $baseDir . '/lib/private/Preview/GeneratorHelper.php',
|
||||
'OC\\Preview\\Illustrator' => $baseDir . '/lib/private/Preview/Illustrator.php',
|
||||
'OC\\Preview\\Image' => $baseDir . '/lib/private/Preview/Image.php',
|
||||
'OC\\Preview\\JPEG' => $baseDir . '/lib/private/Preview/JPEG.php',
|
||||
|
|
@ -640,6 +643,8 @@ return array(
|
|||
'OC\\Preview\\StarOffice' => $baseDir . '/lib/private/Preview/StarOffice.php',
|
||||
'OC\\Preview\\TIFF' => $baseDir . '/lib/private/Preview/TIFF.php',
|
||||
'OC\\Preview\\TXT' => $baseDir . '/lib/private/Preview/TXT.php',
|
||||
'OC\\Preview\\Watcher' => $baseDir . '/lib/private/Preview/Watcher.php',
|
||||
'OC\\Preview\\WatcherConnector' => $baseDir . '/lib/private/Preview/WatcherConnector.php',
|
||||
'OC\\Preview\\XBitmap' => $baseDir . '/lib/private/Preview/XBitmap.php',
|
||||
'OC\\RedisFactory' => $baseDir . '/lib/private/RedisFactory.php',
|
||||
'OC\\Repair' => $baseDir . '/lib/private/Repair.php',
|
||||
|
|
|
|||
|
|
@ -441,6 +441,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
|
|||
'OC\\Core\\Controller\\LostController' => __DIR__ . '/../../..' . '/core/Controller/LostController.php',
|
||||
'OC\\Core\\Controller\\OCJSController' => __DIR__ . '/../../..' . '/core/Controller/OCJSController.php',
|
||||
'OC\\Core\\Controller\\OCSController' => __DIR__ . '/../../..' . '/core/Controller/OCSController.php',
|
||||
'OC\\Core\\Controller\\PreviewController' => __DIR__ . '/../../..' . '/core/Controller/PreviewController.php',
|
||||
'OC\\Core\\Controller\\SetupController' => __DIR__ . '/../../..' . '/core/Controller/SetupController.php',
|
||||
'OC\\Core\\Controller\\TwoFactorChallengeController' => __DIR__ . '/../../..' . '/core/Controller/TwoFactorChallengeController.php',
|
||||
'OC\\Core\\Controller\\UserController' => __DIR__ . '/../../..' . '/core/Controller/UserController.php',
|
||||
|
|
@ -650,6 +651,8 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
|
|||
'OC\\Preview\\Bitmap' => __DIR__ . '/../../..' . '/lib/private/Preview/Bitmap.php',
|
||||
'OC\\Preview\\Font' => __DIR__ . '/../../..' . '/lib/private/Preview/Font.php',
|
||||
'OC\\Preview\\GIF' => __DIR__ . '/../../..' . '/lib/private/Preview/GIF.php',
|
||||
'OC\\Preview\\Generator' => __DIR__ . '/../../..' . '/lib/private/Preview/Generator.php',
|
||||
'OC\\Preview\\GeneratorHelper' => __DIR__ . '/../../..' . '/lib/private/Preview/GeneratorHelper.php',
|
||||
'OC\\Preview\\Illustrator' => __DIR__ . '/../../..' . '/lib/private/Preview/Illustrator.php',
|
||||
'OC\\Preview\\Image' => __DIR__ . '/../../..' . '/lib/private/Preview/Image.php',
|
||||
'OC\\Preview\\JPEG' => __DIR__ . '/../../..' . '/lib/private/Preview/JPEG.php',
|
||||
|
|
@ -670,6 +673,8 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
|
|||
'OC\\Preview\\StarOffice' => __DIR__ . '/../../..' . '/lib/private/Preview/StarOffice.php',
|
||||
'OC\\Preview\\TIFF' => __DIR__ . '/../../..' . '/lib/private/Preview/TIFF.php',
|
||||
'OC\\Preview\\TXT' => __DIR__ . '/../../..' . '/lib/private/Preview/TXT.php',
|
||||
'OC\\Preview\\Watcher' => __DIR__ . '/../../..' . '/lib/private/Preview/Watcher.php',
|
||||
'OC\\Preview\\WatcherConnector' => __DIR__ . '/../../..' . '/lib/private/Preview/WatcherConnector.php',
|
||||
'OC\\Preview\\XBitmap' => __DIR__ . '/../../..' . '/lib/private/Preview/XBitmap.php',
|
||||
'OC\\RedisFactory' => __DIR__ . '/../../..' . '/lib/private/RedisFactory.php',
|
||||
'OC\\Repair' => __DIR__ . '/../../..' . '/lib/private/Repair.php',
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ class Preview {
|
|||
$sysConfig = \OC::$server->getConfig();
|
||||
$this->configMaxWidth = $sysConfig->getSystemValue('preview_max_x', 2048);
|
||||
$this->configMaxHeight = $sysConfig->getSystemValue('preview_max_y', 2048);
|
||||
$this->maxScaleFactor = $sysConfig->getSystemValue('preview_max_scale_factor', 2);
|
||||
$this->maxScaleFactor = $sysConfig->getSystemValue('preview_max_scale_factor', 1);
|
||||
|
||||
//save parameters
|
||||
$this->setFile($file);
|
||||
|
|
|
|||
338
lib/private/Preview/Generator.php
Normal file
338
lib/private/Preview/Generator.php
Normal file
|
|
@ -0,0 +1,338 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2016, Roeland Jago Douma <roeland@famdouma.nl>
|
||||
*
|
||||
* @author Roeland Jago Douma <roeland@famdouma.nl>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OC\Preview;
|
||||
|
||||
use OCP\Files\File;
|
||||
use OCP\Files\IAppData;
|
||||
use OCP\Files\NotFoundException;
|
||||
use OCP\Files\SimpleFS\ISimpleFile;
|
||||
use OCP\Files\SimpleFS\ISimpleFolder;
|
||||
use OCP\IConfig;
|
||||
use OCP\IImage;
|
||||
use OCP\IPreview;
|
||||
use OCP\Preview\IProvider;
|
||||
|
||||
class Generator {
|
||||
|
||||
/** @var IPreview */
|
||||
private $previewManager;
|
||||
/** @var IConfig */
|
||||
private $config;
|
||||
/** @var IAppData */
|
||||
private $appData;
|
||||
/** @var GeneratorHelper */
|
||||
private $helper;
|
||||
|
||||
/**
|
||||
* @param IConfig $config
|
||||
* @param IPreview $previewManager
|
||||
* @param IAppData $appData
|
||||
* @param GeneratorHelper $helper
|
||||
*/
|
||||
public function __construct(
|
||||
IConfig $config,
|
||||
IPreview $previewManager,
|
||||
IAppData $appData,
|
||||
GeneratorHelper $helper
|
||||
) {
|
||||
$this->config = $config;
|
||||
$this->previewManager = $previewManager;
|
||||
$this->appData = $appData;
|
||||
$this->helper = $helper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a preview of a file
|
||||
*
|
||||
* 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 $mimeType
|
||||
* @return ISimpleFile
|
||||
* @throws NotFoundException
|
||||
*/
|
||||
public function getPreview(File $file, $width = -1, $height = -1, $crop = false, $mode = IPreview::MODE_FILL, $mimeType = null) {
|
||||
if ($mimeType === null) {
|
||||
$mimeType = $file->getMimeType();
|
||||
}
|
||||
if (!$this->previewManager->isMimeSupported($mimeType)) {
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
$previewFolder = $this->getPreviewFolder($file);
|
||||
|
||||
// Get the max preview and infer the max preview sizes from that
|
||||
$maxPreview = $this->getMaxPreview($previewFolder, $file, $mimeType);
|
||||
list($maxWidth, $maxHeight) = $this->getPreviewSize($maxPreview);
|
||||
|
||||
// Calculate the preview size
|
||||
list($width, $height) = $this->calculateSize($width, $height, $crop, $mode, $maxWidth, $maxHeight);
|
||||
|
||||
// Try to get a cached preview. Else generate (and store) one
|
||||
try {
|
||||
$file = $this->getCachedPreview($previewFolder, $width, $height, $crop);
|
||||
} catch (NotFoundException $e) {
|
||||
$file = $this->generatePreview($previewFolder, $maxPreview, $width, $height, $crop, $maxWidth, $maxHeight);
|
||||
}
|
||||
|
||||
return $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ISimpleFolder $previewFolder
|
||||
* @param File $file
|
||||
* @param string $mimeType
|
||||
* @return ISimpleFile
|
||||
* @throws NotFoundException
|
||||
*/
|
||||
private function getMaxPreview(ISimpleFolder $previewFolder, File $file, $mimeType) {
|
||||
$nodes = $previewFolder->getDirectoryListing();
|
||||
|
||||
foreach ($nodes as $node) {
|
||||
if (strpos($node->getName(), 'max')) {
|
||||
return $node;
|
||||
}
|
||||
}
|
||||
|
||||
$previewProviders = $this->previewManager->getProviders();
|
||||
foreach ($previewProviders as $supportedMimeType => $providers) {
|
||||
if (!preg_match($supportedMimeType, $mimeType)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($providers as $provider) {
|
||||
$provider = $this->helper->getProvider($provider);
|
||||
if (!($provider instanceof IProvider)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$maxWidth = (int)$this->config->getSystemValue('preview_max_x', 2048);
|
||||
$maxHeight = (int)$this->config->getSystemValue('preview_max_y', 2048);
|
||||
|
||||
$preview = $this->helper->getThumbnail($provider, $file, $maxWidth, $maxHeight);
|
||||
|
||||
if (!($preview instanceof IImage)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$path = strval($preview->width()) . '-' . strval($preview->height()) . '-max.png';
|
||||
$file = $previewFolder->newFile($path);
|
||||
$file->putContent($preview->data());
|
||||
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ISimpleFile $file
|
||||
* @return int[]
|
||||
*/
|
||||
private function getPreviewSize(ISimpleFile $file) {
|
||||
$size = explode('-', $file->getName());
|
||||
return [(int)$size[0], (int)$size[1]];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $width
|
||||
* @param int $height
|
||||
* @param bool $crop
|
||||
* @return string
|
||||
*/
|
||||
private function generatePath($width, $height, $crop) {
|
||||
$path = strval($width) . '-' . strval($height);
|
||||
if ($crop) {
|
||||
$path .= '-crop';
|
||||
}
|
||||
$path .= '.png';
|
||||
return $path;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param int $width
|
||||
* @param int $height
|
||||
* @param bool $crop
|
||||
* @param string $mode
|
||||
* @param int $maxWidth
|
||||
* @param int $maxHeight
|
||||
* @return int[]
|
||||
*/
|
||||
private function calculateSize($width, $height, $crop, $mode, $maxWidth, $maxHeight) {
|
||||
|
||||
/*
|
||||
* If we are not cropping we have to make sure the requested image
|
||||
* respects the aspect ratio of the original.
|
||||
*/
|
||||
if (!$crop) {
|
||||
$ratio = $maxHeight / $maxWidth;
|
||||
|
||||
if ($width === -1) {
|
||||
$width = $height / $ratio;
|
||||
}
|
||||
if ($height === -1) {
|
||||
$height = $width * $ratio;
|
||||
}
|
||||
|
||||
$ratioH = $height / $maxHeight;
|
||||
$ratioW = $width / $maxWidth;
|
||||
|
||||
/*
|
||||
* Fill means that the $height and $width are the max
|
||||
* Cover means min.
|
||||
*/
|
||||
if ($mode === IPreview::MODE_FILL) {
|
||||
if ($ratioH > $ratioW) {
|
||||
$height = $width * $ratio;
|
||||
} else {
|
||||
$width = $height / $ratio;
|
||||
}
|
||||
} else if ($mode === IPreview::MODE_COVER) {
|
||||
if ($ratioH > $ratioW) {
|
||||
$width = $height / $ratio;
|
||||
} else {
|
||||
$height = $width * $ratio;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($height !== $maxHeight && $width !== $maxWidth) {
|
||||
/*
|
||||
* Scale to the nearest power of two
|
||||
*/
|
||||
$pow2height = pow(2, ceil(log($height) / log(2)));
|
||||
$pow2width = pow(2, ceil(log($width) / log(2)));
|
||||
|
||||
$ratioH = $height / $pow2height;
|
||||
$ratioW = $width / $pow2width;
|
||||
|
||||
if ($ratioH < $ratioW) {
|
||||
$width = $pow2width;
|
||||
$height = $height / $ratioW;
|
||||
} else {
|
||||
$height = $pow2height;
|
||||
$width = $width / $ratioH;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure the requested height and width fall within the max
|
||||
* of the preview.
|
||||
*/
|
||||
if ($height > $maxHeight) {
|
||||
$ratio = $height / $maxHeight;
|
||||
$height = $maxHeight;
|
||||
$width = $width / $ratio;
|
||||
}
|
||||
if ($width > $maxWidth) {
|
||||
$ratio = $width / $maxWidth;
|
||||
$width = $maxWidth;
|
||||
$height = $height / $ratio;
|
||||
}
|
||||
|
||||
return [(int)round($width), (int)round($height)];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ISimpleFolder $previewFolder
|
||||
* @param ISimpleFile $maxPreview
|
||||
* @param int $width
|
||||
* @param int $height
|
||||
* @param bool $crop
|
||||
* @param int $maxWidth
|
||||
* @param int $maxHeight
|
||||
* @return ISimpleFile
|
||||
* @throws NotFoundException
|
||||
*/
|
||||
private function generatePreview(ISimpleFolder $previewFolder, ISimpleFile $maxPreview, $width, $height, $crop, $maxWidth, $maxHeight) {
|
||||
$preview = $this->helper->getImage($maxPreview);
|
||||
|
||||
if ($crop) {
|
||||
if ($height !== $preview->height() && $width !== $preview->width()) {
|
||||
//Resize
|
||||
$widthR = $preview->width() / $width;
|
||||
$heightR = $preview->height() / $height;
|
||||
|
||||
if ($widthR > $heightR) {
|
||||
$scaleH = $height;
|
||||
$scaleW = $maxWidth / $heightR;
|
||||
} else {
|
||||
$scaleH = $maxHeight / $widthR;
|
||||
$scaleW = $width;
|
||||
}
|
||||
$preview->preciseResize(round($scaleW), round($scaleH));
|
||||
}
|
||||
$cropX = floor(abs($width - $preview->width()) * 0.5);
|
||||
$cropY = 0;
|
||||
$preview->crop($cropX, $cropY, $width, $height);
|
||||
} else {
|
||||
$preview->resize(max($width, $height));
|
||||
}
|
||||
|
||||
$path = $this->generatePath($width, $height, $crop);
|
||||
$file = $previewFolder->newFile($path);
|
||||
$file->putContent($preview->data());
|
||||
|
||||
return $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ISimpleFolder $previewFolder
|
||||
* @param int $width
|
||||
* @param int $height
|
||||
* @param bool $crop
|
||||
* @return ISimpleFile
|
||||
*
|
||||
* @throws NotFoundException
|
||||
*/
|
||||
private function getCachedPreview(ISimpleFolder $previewFolder, $width, $height, $crop) {
|
||||
$path = $this->generatePath($width, $height, $crop);
|
||||
|
||||
return $previewFolder->getFile($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the specific preview folder for this file
|
||||
*
|
||||
* @param File $file
|
||||
* @return ISimpleFolder
|
||||
*/
|
||||
private function getPreviewFolder(File $file) {
|
||||
try {
|
||||
$folder = $this->appData->getFolder($file->getId());
|
||||
} catch (NotFoundException $e) {
|
||||
$folder = $this->appData->newFolder($file->getId());
|
||||
}
|
||||
|
||||
return $folder;
|
||||
}
|
||||
}
|
||||
91
lib/private/Preview/GeneratorHelper.php
Normal file
91
lib/private/Preview/GeneratorHelper.php
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2016, Roeland Jago Douma <roeland@famdouma.nl>
|
||||
*
|
||||
* @author Roeland Jago Douma <roeland@famdouma.nl>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
namespace OC\Preview;
|
||||
|
||||
use OC\Files\View;
|
||||
use OCP\Files\File;
|
||||
use OCP\Files\IRootFolder;
|
||||
use OCP\Files\SimpleFS\ISimpleFile;
|
||||
use OCP\IImage;
|
||||
use OCP\Image as img;
|
||||
use OCP\Preview\IProvider;
|
||||
|
||||
/**
|
||||
* Very small wrapper class to make the generator fully unit testable
|
||||
*/
|
||||
class GeneratorHelper {
|
||||
|
||||
/** @var IRootFolder */
|
||||
private $rootFolder;
|
||||
|
||||
public function __construct(IRootFolder $rootFolder) {
|
||||
$this->rootFolder = $rootFolder;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IProvider $provider
|
||||
* @param File $file
|
||||
* @param int $maxWidth
|
||||
* @param int $maxHeight
|
||||
* @return bool|IImage
|
||||
*/
|
||||
public function getThumbnail(IProvider $provider, File $file, $maxWidth, $maxHeight) {
|
||||
list($view, $path) = $this->getViewAndPath($file);
|
||||
return $provider->getThumbnail($path, $maxWidth, $maxHeight, false, $view);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param File $file
|
||||
* @return array
|
||||
* This is required to create the old view and path
|
||||
*/
|
||||
private function getViewAndPath(File $file) {
|
||||
$owner = $file->getOwner()->getUID();
|
||||
|
||||
$userFolder = $this->rootFolder->getUserFolder($owner)->getParent();
|
||||
|
||||
$nodes = $userFolder->getById($file->getId());
|
||||
$file = $nodes[0];
|
||||
|
||||
$view = new View($userFolder->getPath());
|
||||
$path = $userFolder->getRelativePath($file->getPath());
|
||||
|
||||
return [$view, $path];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ISimpleFile $maxPreview
|
||||
* @return IImage
|
||||
*/
|
||||
public function getImage(ISimpleFile $maxPreview) {
|
||||
return new img($maxPreview->getContent());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $provider
|
||||
* @return IProvider
|
||||
*/
|
||||
public function getProvider($provider) {
|
||||
return $provider();
|
||||
}
|
||||
}
|
||||
98
lib/private/Preview/Watcher.php
Normal file
98
lib/private/Preview/Watcher.php
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2016, Roeland Jago Douma <roeland@famdouma.nl>
|
||||
*
|
||||
* @author Roeland Jago Douma <roeland@famdouma.nl>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
namespace OC\Preview;
|
||||
|
||||
use OCP\Files\File;
|
||||
use OCP\Files\Node;
|
||||
use OCP\Files\Folder;
|
||||
use OCP\Files\IAppData;
|
||||
use OCP\Files\NotFoundException;
|
||||
|
||||
/**
|
||||
* Class Watcher
|
||||
*
|
||||
* @package OC\Preview
|
||||
*
|
||||
* Class that will watch filesystem activity and remove previews as needed.
|
||||
*/
|
||||
class Watcher {
|
||||
/** @var IAppData */
|
||||
private $appData;
|
||||
|
||||
/** @var int[] */
|
||||
private $toDelete = [];
|
||||
|
||||
/**
|
||||
* Watcher constructor.
|
||||
*
|
||||
* @param IAppData $appData
|
||||
*/
|
||||
public function __construct(IAppData $appData) {
|
||||
$this->appData = $appData;
|
||||
}
|
||||
|
||||
public function postWrite(Node $node) {
|
||||
// We only handle files
|
||||
if ($node instanceof Folder) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$folder = $this->appData->getFolder($node->getId());
|
||||
$folder->delete();
|
||||
} catch (NotFoundException $e) {
|
||||
//Nothing to do
|
||||
}
|
||||
}
|
||||
|
||||
public function preDelete(Node $node) {
|
||||
// To avoid cycles
|
||||
if ($this->toDelete !== []) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($node instanceof File) {
|
||||
$this->toDelete[] = $node->getId();
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var Folder $node */
|
||||
$nodes = $node->search('');
|
||||
foreach ($nodes as $node) {
|
||||
if ($node instanceof File) {
|
||||
$this->toDelete[] = $node->getId();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function postDelete(Node $node) {
|
||||
foreach ($this->toDelete as $fid) {
|
||||
try {
|
||||
$folder = $this->appData->getFolder($fid);
|
||||
$folder->delete();
|
||||
} catch (NotFoundException $e) {
|
||||
// continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
72
lib/private/Preview/WatcherConnector.php
Normal file
72
lib/private/Preview/WatcherConnector.php
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2016, Roeland Jago Douma <roeland@famdouma.nl>
|
||||
*
|
||||
* @author Roeland Jago Douma <roeland@famdouma.nl>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
namespace OC\Preview;
|
||||
|
||||
use OC\SystemConfig;
|
||||
use OCP\Files\Node;
|
||||
use OCP\Files\IRootFolder;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Watcher
|
||||
*/
|
||||
private function getWatcher() {
|
||||
return \OC::$server->query(Watcher::class);
|
||||
}
|
||||
|
||||
public function connectWatcher() {
|
||||
// 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);
|
||||
});
|
||||
|
||||
$this->root->listen('\OC\Files', 'preDelete', function (Node $node) {
|
||||
$this->getWatcher()->preDelete($node);
|
||||
});
|
||||
|
||||
$this->root->listen('\OC\Files', 'postDelete', function (Node $node) {
|
||||
$this->getWatcher()->postDelete($node);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -25,13 +25,30 @@
|
|||
*/
|
||||
namespace OC;
|
||||
|
||||
use OC\Preview\Generator;
|
||||
use OC\Preview\GeneratorHelper;
|
||||
use OCP\Files\File;
|
||||
use OCP\Files\IAppData;
|
||||
use OCP\Files\IRootFolder;
|
||||
use OCP\Files\NotFoundException;
|
||||
use OCP\Files\SimpleFS\ISimpleFile;
|
||||
use OCP\IConfig;
|
||||
use OCP\IPreview;
|
||||
use OCP\Preview\IProvider;
|
||||
|
||||
class PreviewManager implements IPreview {
|
||||
/** @var \OCP\IConfig */
|
||||
/** @var IConfig */
|
||||
protected $config;
|
||||
|
||||
/** @var IRootFolder */
|
||||
protected $rootFolder;
|
||||
|
||||
/** @var IAppData */
|
||||
protected $appData;
|
||||
|
||||
/** @var Generator */
|
||||
private $generator;
|
||||
|
||||
/** @var bool */
|
||||
protected $providerListDirty = false;
|
||||
|
||||
|
|
@ -52,8 +69,12 @@ class PreviewManager implements IPreview {
|
|||
*
|
||||
* @param \OCP\IConfig $config
|
||||
*/
|
||||
public function __construct(\OCP\IConfig $config) {
|
||||
public function __construct(IConfig $config,
|
||||
IRootFolder $rootFolder,
|
||||
IAppData $appData) {
|
||||
$this->config = $config;
|
||||
$this->rootFolder = $rootFolder;
|
||||
$this->appData = $appData;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -120,6 +141,37 @@ class PreviewManager implements IPreview {
|
|||
return $preview->getPreview();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a preview of a file
|
||||
*
|
||||
* 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 $mimeType
|
||||
* @return ISimpleFile
|
||||
* @throws NotFoundException
|
||||
* @since 9.2.0
|
||||
*/
|
||||
public function getPreview(File $file, $width = -1, $height = -1, $crop = false, $mode = IPreview::MODE_FILL, $mimeType = null) {
|
||||
if ($this->generator === null) {
|
||||
$this->generator = new Generator(
|
||||
$this->config,
|
||||
$this,
|
||||
$this->appData,
|
||||
new GeneratorHelper(
|
||||
$this->rootFolder
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return $this->generator->getPreview($file, $width, $height, $crop, $mode, $mimeType);
|
||||
}
|
||||
|
||||
/**
|
||||
* returns true if the passed mime type is supported
|
||||
*
|
||||
|
|
|
|||
|
|
@ -117,7 +117,17 @@ class Server extends ServerContainer implements IServerContainer {
|
|||
});
|
||||
|
||||
$this->registerService('PreviewManager', function (Server $c) {
|
||||
return new PreviewManager($c->getConfig());
|
||||
return new PreviewManager(
|
||||
$c->getConfig(),
|
||||
$c->getRootFolder(),
|
||||
$c->getAppDataDir('preview')
|
||||
);
|
||||
});
|
||||
|
||||
$this->registerService(\OC\Preview\Watcher::class, function (Server $c) {
|
||||
return new \OC\Preview\Watcher(
|
||||
$c->getAppDataDir('preview')
|
||||
);
|
||||
});
|
||||
|
||||
$this->registerService('EncryptionManager', function (Server $c) {
|
||||
|
|
@ -192,6 +202,10 @@ class Server extends ServerContainer implements IServerContainer {
|
|||
);
|
||||
$connector = new HookConnector($root, $view);
|
||||
$connector->viewToNode();
|
||||
|
||||
$previewConnector = new \OC\Preview\WatcherConnector($root, $c->getSystemConfig());
|
||||
$previewConnector->connectWatcher();
|
||||
|
||||
return $root;
|
||||
});
|
||||
$this->registerService('LazyRootFolder', function(Server $c) {
|
||||
|
|
|
|||
|
|
@ -33,11 +33,19 @@
|
|||
// This means that they should be used by apps instead of the internal ownCloud classes
|
||||
namespace OCP;
|
||||
|
||||
use OCP\Files\File;
|
||||
use OCP\Files\SimpleFS\ISimpleFile;
|
||||
use OCP\Files\NotFoundException;
|
||||
|
||||
/**
|
||||
* This class provides functions to render and show thumbnails and previews of files
|
||||
* @since 6.0.0
|
||||
*/
|
||||
interface IPreview {
|
||||
|
||||
const MODE_FILL = 'fill';
|
||||
const MODE_COVER = 'cover';
|
||||
|
||||
/**
|
||||
* In order to improve lazy loading a closure can be registered which will be
|
||||
* called in case preview providers are actually requested
|
||||
|
|
@ -73,9 +81,27 @@ interface IPreview {
|
|||
* @param boolean $scaleUp Scale smaller images up to the thumbnail size or not. Might look ugly
|
||||
* @return \OCP\IImage
|
||||
* @since 6.0.0
|
||||
* @deprecated 9.2.0 Use getPreview
|
||||
*/
|
||||
public function createPreview($file, $maxX = 100, $maxY = 75, $scaleUp = false);
|
||||
|
||||
/**
|
||||
* Returns a preview of a file
|
||||
*
|
||||
* 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 $mimeType To force a given mimetype for the file (files_versions needs this)
|
||||
* @return ISimpleFile
|
||||
* @throws NotFoundException
|
||||
* @since 9.2.0
|
||||
*/
|
||||
public function getPreview(File $file, $width = -1, $height = -1, $crop = false, $mode = IPreview::MODE_FILL, $mimeType = null);
|
||||
|
||||
/**
|
||||
* Returns true if the passed mime type is supported
|
||||
|
|
|
|||
226
tests/Core/Controller/PreviewControllerTest.php
Normal file
226
tests/Core/Controller/PreviewControllerTest.php
Normal file
|
|
@ -0,0 +1,226 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2016, Roeland Jago Douma <roeland@famdouma.nl>
|
||||
*
|
||||
* @author Roeland Jago Douma <roeland@famdouma.nl>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
namespace Tests\Core\Controller;
|
||||
|
||||
use OC\Core\Controller\PreviewController;
|
||||
use OCP\AppFramework\Http;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\AppFramework\Utility\ITimeFactory;
|
||||
use OCP\Files\File;
|
||||
use OCP\Files\Folder;
|
||||
use OCP\Files\IRootFolder;
|
||||
use OCP\Files\NotFoundException;
|
||||
use OCP\Files\SimpleFS\ISimpleFile;
|
||||
use OCP\IPreview;
|
||||
use OCP\IRequest;
|
||||
|
||||
class PreviewControllerTest extends \Test\TestCase {
|
||||
|
||||
/** @var IRootFolder|\PHPUnit_Framework_MockObject_MockObject */
|
||||
private $rootFolder;
|
||||
|
||||
/** @var string */
|
||||
private $userId;
|
||||
|
||||
/** @var IPreview|\PHPUnit_Framework_MockObject_MockObject */
|
||||
private $previewManager;
|
||||
|
||||
/** @var PreviewController|\PHPUnit_Framework_MockObject_MockObject */
|
||||
private $controller;
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->rootFolder = $this->createMock(IRootFolder::class);
|
||||
$this->userId = 'user';
|
||||
$this->previewManager = $this->createMock(IPreview::class);
|
||||
|
||||
$this->controller = new PreviewController(
|
||||
'core',
|
||||
$this->createMock(IRequest::class),
|
||||
$this->previewManager,
|
||||
$this->rootFolder,
|
||||
$this->userId,
|
||||
$this->createMock(ITimeFactory::class)
|
||||
);
|
||||
}
|
||||
|
||||
public function testInvalidFile() {
|
||||
$res = $this->controller->getPreview('');
|
||||
$expected = new DataResponse([], Http::STATUS_BAD_REQUEST);
|
||||
|
||||
$this->assertEquals($expected, $res);
|
||||
}
|
||||
|
||||
public function testInvalidWidth() {
|
||||
$res = $this->controller->getPreview('file', 0);
|
||||
$expected = new DataResponse([], Http::STATUS_BAD_REQUEST);
|
||||
|
||||
$this->assertEquals($expected, $res);
|
||||
}
|
||||
|
||||
public function testInvalidHeight() {
|
||||
$res = $this->controller->getPreview('file', 10, 0);
|
||||
$expected = new DataResponse([], Http::STATUS_BAD_REQUEST);
|
||||
|
||||
$this->assertEquals($expected, $res);
|
||||
}
|
||||
|
||||
public function testFileNotFound() {
|
||||
$userFolder = $this->createMock(Folder::class);
|
||||
$this->rootFolder->method('getUserFolder')
|
||||
->with($this->equalTo($this->userId))
|
||||
->willReturn($userFolder);
|
||||
|
||||
$userFolder->method('get')
|
||||
->with($this->equalTo('file'))
|
||||
->willThrowException(new NotFoundException());
|
||||
|
||||
$res = $this->controller->getPreview('file');
|
||||
$expected = new DataResponse([], Http::STATUS_NOT_FOUND);
|
||||
|
||||
$this->assertEquals($expected, $res);
|
||||
}
|
||||
|
||||
public function testNotAFile() {
|
||||
$userFolder = $this->createMock(Folder::class);
|
||||
$this->rootFolder->method('getUserFolder')
|
||||
->with($this->equalTo($this->userId))
|
||||
->willReturn($userFolder);
|
||||
|
||||
$folder = $this->createMock(Folder::class);
|
||||
$userFolder->method('get')
|
||||
->with($this->equalTo('file'))
|
||||
->willReturn($folder);
|
||||
|
||||
$res = $this->controller->getPreview('file');
|
||||
$expected = new DataResponse([], Http::STATUS_NOT_FOUND);
|
||||
|
||||
$this->assertEquals($expected, $res);
|
||||
}
|
||||
|
||||
public function testNoPreviewAndNoIcon() {
|
||||
$userFolder = $this->createMock(Folder::class);
|
||||
$this->rootFolder->method('getUserFolder')
|
||||
->with($this->equalTo($this->userId))
|
||||
->willReturn($userFolder);
|
||||
|
||||
$file = $this->createMock(File::class);
|
||||
$userFolder->method('get')
|
||||
->with($this->equalTo('file'))
|
||||
->willReturn($file);
|
||||
|
||||
$this->previewManager->method('isAvailable')
|
||||
->with($this->equalTo($file))
|
||||
->willReturn(false);
|
||||
|
||||
$res = $this->controller->getPreview('file', 10, 10, true, false);
|
||||
$expected = new DataResponse([], Http::STATUS_NOT_FOUND);
|
||||
|
||||
$this->assertEquals($expected, $res);
|
||||
}
|
||||
|
||||
public function testForbiddenFile() {
|
||||
$userFolder = $this->createMock(Folder::class);
|
||||
$this->rootFolder->method('getUserFolder')
|
||||
->with($this->equalTo($this->userId))
|
||||
->willReturn($userFolder);
|
||||
|
||||
$file = $this->createMock(File::class);
|
||||
$userFolder->method('get')
|
||||
->with($this->equalTo('file'))
|
||||
->willReturn($file);
|
||||
|
||||
$this->previewManager->method('isAvailable')
|
||||
->with($this->equalTo($file))
|
||||
->willReturn(true);
|
||||
|
||||
$file->method('isReadable')
|
||||
->willReturn(false);
|
||||
|
||||
$res = $this->controller->getPreview('file', 10, 10, true, true);
|
||||
$expected = new DataResponse([], Http::STATUS_FORBIDDEN);
|
||||
|
||||
$this->assertEquals($expected, $res);
|
||||
}
|
||||
|
||||
public function testNoPreview() {
|
||||
$userFolder = $this->createMock(Folder::class);
|
||||
$this->rootFolder->method('getUserFolder')
|
||||
->with($this->equalTo($this->userId))
|
||||
->willReturn($userFolder);
|
||||
|
||||
$file = $this->createMock(File::class);
|
||||
$userFolder->method('get')
|
||||
->with($this->equalTo('file'))
|
||||
->willReturn($file);
|
||||
|
||||
$this->previewManager->method('isAvailable')
|
||||
->with($this->equalTo($file))
|
||||
->willReturn(true);
|
||||
|
||||
$file->method('isReadable')
|
||||
->willReturn(true);
|
||||
|
||||
$this->previewManager->method('getPreview')
|
||||
->with($this->equalTo($file), 10, 10, false, $this->equalTo('myMode'))
|
||||
->willThrowException(new NotFoundException());
|
||||
|
||||
$res = $this->controller->getPreview('file', 10, 10, true, true, 'myMode');
|
||||
$expected = new DataResponse([], Http::STATUS_NOT_FOUND);
|
||||
|
||||
$this->assertEquals($expected, $res);
|
||||
}
|
||||
|
||||
public function testValidPreview() {
|
||||
$userFolder = $this->createMock(Folder::class);
|
||||
$this->rootFolder->method('getUserFolder')
|
||||
->with($this->equalTo($this->userId))
|
||||
->willReturn($userFolder);
|
||||
|
||||
$file = $this->createMock(File::class);
|
||||
$userFolder->method('get')
|
||||
->with($this->equalTo('file'))
|
||||
->willReturn($file);
|
||||
|
||||
$this->previewManager->method('isAvailable')
|
||||
->with($this->equalTo($file))
|
||||
->willReturn(true);
|
||||
|
||||
$file->method('isReadable')
|
||||
->willReturn(true);
|
||||
|
||||
$preview = $this->createMock(ISimpleFile::class);
|
||||
$this->previewManager->method('getPreview')
|
||||
->with($this->equalTo($file), 10, 10, false, $this->equalTo('myMode'))
|
||||
->willReturn($preview);
|
||||
$preview->method('getMimeType')
|
||||
->willReturn('myMime');
|
||||
|
||||
$res = $this->controller->getPreview('file', 10, 10, true, true, 'myMode');
|
||||
|
||||
$this->assertEquals('myMime', $res->getHeaders()['Content-Type']);
|
||||
$this->assertEquals(Http::STATUS_OK, $res->getStatus());
|
||||
$this->assertEquals($preview, $this->invokePrivate($res, 'file'));
|
||||
}
|
||||
}
|
||||
338
tests/lib/Preview/GeneratorTest.php
Normal file
338
tests/lib/Preview/GeneratorTest.php
Normal file
|
|
@ -0,0 +1,338 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2016, Roeland Jago Douma <roeland@famdouma.nl>
|
||||
*
|
||||
* @author Roeland Jago Douma <roeland@famdouma.nl>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
namespace Test\Preview;
|
||||
|
||||
use OC\Preview\Generator;
|
||||
use OC\Preview\GeneratorHelper;
|
||||
use OCP\Files\File;
|
||||
use OCP\Files\IAppData;
|
||||
use OCP\Files\NotFoundException;
|
||||
use OCP\Files\SimpleFS\ISimpleFile;
|
||||
use OCP\Files\SimpleFS\ISimpleFolder;
|
||||
use OCP\IConfig;
|
||||
use OCP\IImage;
|
||||
use OCP\IPreview;
|
||||
use OCP\Preview\IProvider;
|
||||
|
||||
class GeneratorTest extends \Test\TestCase {
|
||||
|
||||
/** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */
|
||||
private $config;
|
||||
|
||||
/** @var IPreview|\PHPUnit_Framework_MockObject_MockObject */
|
||||
private $previewManager;
|
||||
|
||||
/** @var IAppData|\PHPUnit_Framework_MockObject_MockObject */
|
||||
private $appData;
|
||||
|
||||
/** @var GeneratorHelper|\PHPUnit_Framework_MockObject_MockObject */
|
||||
private $helper;
|
||||
|
||||
/** @var Generator */
|
||||
private $generator;
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->config = $this->createMock(IConfig::class);
|
||||
$this->previewManager = $this->createMock(IPreview::class);
|
||||
$this->appData = $this->createMock(IAppData::class);
|
||||
$this->helper = $this->createMock(GeneratorHelper::class);
|
||||
|
||||
$this->generator = new Generator(
|
||||
$this->config,
|
||||
$this->previewManager,
|
||||
$this->appData,
|
||||
$this->helper
|
||||
);
|
||||
}
|
||||
|
||||
public function testGetCachedPreview() {
|
||||
$file = $this->createMock(File::class);
|
||||
$file->method('getMimeType')
|
||||
->willReturn('myMimeType');
|
||||
$file->method('getId')
|
||||
->willReturn(42);
|
||||
|
||||
$this->previewManager->method('isMimeSupported')
|
||||
->with($this->equalTo('myMimeType'))
|
||||
->willReturn(true);
|
||||
|
||||
$previewFolder = $this->createMock(ISimpleFolder::class);
|
||||
$this->appData->method('getFolder')
|
||||
->with($this->equalTo(42))
|
||||
->willReturn($previewFolder);
|
||||
|
||||
$maxPreview = $this->createMock(ISimpleFile::class);
|
||||
$maxPreview->method('getName')
|
||||
->willReturn('1000-1000-max.png');
|
||||
|
||||
$previewFolder->method('getDirectoryListing')
|
||||
->willReturn([$maxPreview]);
|
||||
|
||||
$previewFile = $this->createMock(ISimpleFile::class);
|
||||
|
||||
$previewFolder->method('getFile')
|
||||
->with($this->equalTo('128-128.png'))
|
||||
->willReturn($previewFile);
|
||||
|
||||
$result = $this->generator->getPreview($file, 100, 100);
|
||||
$this->assertSame($previewFile, $result);
|
||||
}
|
||||
|
||||
public function testGetNewPreview() {
|
||||
$file = $this->createMock(File::class);
|
||||
$file->method('getMimeType')
|
||||
->willReturn('myMimeType');
|
||||
$file->method('getId')
|
||||
->willReturn(42);
|
||||
|
||||
$this->previewManager->method('isMimeSupported')
|
||||
->with($this->equalTo('myMimeType'))
|
||||
->willReturn(true);
|
||||
|
||||
$previewFolder = $this->createMock(ISimpleFolder::class);
|
||||
$this->appData->method('getFolder')
|
||||
->with($this->equalTo(42))
|
||||
->willThrowException(new NotFoundException());
|
||||
|
||||
$this->appData->method('newFolder')
|
||||
->with($this->equalTo(42))
|
||||
->willReturn($previewFolder);
|
||||
|
||||
$this->config->method('getSystemValue')
|
||||
->will($this->returnCallback(function($key, $defult) {
|
||||
return $defult;
|
||||
}));
|
||||
|
||||
$invalidProvider = $this->createMock(IProvider::class);
|
||||
$validProvider = $this->createMock(IProvider::class);
|
||||
|
||||
$this->previewManager->method('getProviders')
|
||||
->willReturn([
|
||||
'/image\/png/' => ['wrongProvider'],
|
||||
'/myMimeType/' => ['brokenProvider', 'invalidProvider', 'validProvider'],
|
||||
]);
|
||||
|
||||
$this->helper->method('getProvider')
|
||||
->will($this->returnCallback(function($provider) use ($invalidProvider, $validProvider) {
|
||||
if ($provider === 'wrongProvider') {
|
||||
$this->fail('Wrongprovider should not be constructed!');
|
||||
} else if ($provider === 'brokenProvider') {
|
||||
return false;
|
||||
} else if ($provider === 'invalidProvider') {
|
||||
return $invalidProvider;
|
||||
} else if ($provider === 'validProvider') {
|
||||
return $validProvider;
|
||||
}
|
||||
$this->fail('Unexpected provider requested');
|
||||
}));
|
||||
|
||||
$image = $this->createMock(IImage::class);
|
||||
$image->method('width')->willReturn(2048);
|
||||
$image->method('height')->willReturn(2048);
|
||||
|
||||
$this->helper->method('getThumbnail')
|
||||
->will($this->returnCallback(function ($provider, $file, $x, $y) use ($invalidProvider, $validProvider, $image) {
|
||||
if ($provider === $validProvider) {
|
||||
return $image;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}));
|
||||
|
||||
$image->method('data')
|
||||
->willReturn('my data');
|
||||
|
||||
$maxPreview = $this->createMock(ISimpleFile::class);
|
||||
$maxPreview->method('getName')->willReturn('2048-2048-max.png');
|
||||
|
||||
$previewFile = $this->createMock(ISimpleFile::class);
|
||||
|
||||
$previewFolder->method('getDirectoryListing')
|
||||
->willReturn([]);
|
||||
$previewFolder->method('newFile')
|
||||
->will($this->returnCallback(function($filename) use ($maxPreview, $previewFile) {
|
||||
if ($filename === '2048-2048-max.png') {
|
||||
return $maxPreview;
|
||||
} else if ($filename === '128-128.png') {
|
||||
return $previewFile;
|
||||
}
|
||||
$this->fail('Unexpected file');
|
||||
}));
|
||||
|
||||
$maxPreview->expects($this->once())
|
||||
->method('putContent')
|
||||
->with($this->equalTo('my data'));
|
||||
|
||||
$previewFolder->method('getFile')
|
||||
->with($this->equalTo('128-128.png'))
|
||||
->willThrowException(new NotFoundException());
|
||||
|
||||
$image = $this->createMock(IImage::class);
|
||||
$this->helper->method('getImage')
|
||||
->with($this->equalTo($maxPreview))
|
||||
->willReturn($image);
|
||||
|
||||
$image->expects($this->once())
|
||||
->method('resize')
|
||||
->with(128);
|
||||
$image->method('data')
|
||||
->willReturn('my resized data');
|
||||
|
||||
$previewFile->expects($this->once())
|
||||
->method('putContent')
|
||||
->with('my resized data');
|
||||
|
||||
$result = $this->generator->getPreview($file, 100, 100);
|
||||
$this->assertSame($previewFile, $result);
|
||||
}
|
||||
|
||||
public function testInvalidMimeType() {
|
||||
$this->expectException(NotFoundException::class);
|
||||
|
||||
$file = $this->createMock(File::class);
|
||||
|
||||
$this->previewManager->method('isMimeSupported')
|
||||
->with('invalidType')
|
||||
->willReturn(false);
|
||||
|
||||
$this->generator->getPreview($file, 0, 0, true, IPreview::MODE_COVER, 'invalidType');
|
||||
}
|
||||
|
||||
public function testNoProvider() {
|
||||
$file = $this->createMock(File::class);
|
||||
$file->method('getMimeType')
|
||||
->willReturn('myMimeType');
|
||||
$file->method('getId')
|
||||
->willReturn(42);
|
||||
|
||||
$this->previewManager->method('isMimeSupported')
|
||||
->with($this->equalTo('myMimeType'))
|
||||
->willReturn(true);
|
||||
|
||||
$previewFolder = $this->createMock(ISimpleFolder::class);
|
||||
$this->appData->method('getFolder')
|
||||
->with($this->equalTo(42))
|
||||
->willReturn($previewFolder);
|
||||
|
||||
$previewFolder->method('getDirectoryListing')
|
||||
->willReturn([]);
|
||||
|
||||
$this->previewManager->method('getProviders')
|
||||
->willReturn([]);
|
||||
|
||||
$this->expectException(NotFoundException::class);
|
||||
$this->generator->getPreview($file, 100, 100);
|
||||
}
|
||||
|
||||
public function dataSize() {
|
||||
return [
|
||||
[1024, 2048, 512, 512, false, IPreview::MODE_FILL, 256, 512],
|
||||
[1024, 2048, 512, 512, false, IPreview::MODE_COVER, 512, 1024],
|
||||
[1024, 2048, 512, 512, true, IPreview::MODE_FILL, 512, 512],
|
||||
[1024, 2048, 512, 512, true, IPreview::MODE_COVER, 512, 512],
|
||||
|
||||
[1024, 2048, -1, 512, false, IPreview::MODE_COVER, 256, 512],
|
||||
[1024, 2048, 512, -1, false, IPreview::MODE_FILL, 512, 1024],
|
||||
|
||||
[1024, 2048, 250, 1100, true, IPreview::MODE_COVER, 256, 1126],
|
||||
[1024, 1100, 250, 1100, true, IPreview::MODE_COVER, 250, 1100],
|
||||
|
||||
[1024, 2048, 4096, 2048, false, IPreview::MODE_FILL, 1024, 2048],
|
||||
[1024, 2048, 4096, 2048, false, IPreview::MODE_COVER, 1024, 2048],
|
||||
|
||||
|
||||
[2048, 1024, 512, 512, false, IPreview::MODE_FILL, 512, 256],
|
||||
[2048, 1024, 512, 512, false, IPreview::MODE_COVER, 1024, 512],
|
||||
[2048, 1024, 512, 512, true, IPreview::MODE_FILL, 512, 512],
|
||||
[2048, 1024, 512, 512, true, IPreview::MODE_COVER, 512, 512],
|
||||
|
||||
[2048, 1024, -1, 512, false, IPreview::MODE_FILL, 1024, 512],
|
||||
[2048, 1024, 512, -1, false, IPreview::MODE_COVER, 512, 256],
|
||||
|
||||
[2048, 1024, 4096, 1024, true, IPreview::MODE_FILL, 2048, 512],
|
||||
[2048, 1024, 4096, 1024, true, IPreview::MODE_COVER, 2048, 512],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataSize
|
||||
*
|
||||
* @param int $maxX
|
||||
* @param int $maxY
|
||||
* @param int $reqX
|
||||
* @param int $reqY
|
||||
* @param bool $crop
|
||||
* @param string $mode
|
||||
* @param int $expectedX
|
||||
* @param int $expectedY
|
||||
*/
|
||||
public function testCorrectSize($maxX, $maxY, $reqX, $reqY, $crop, $mode, $expectedX, $expectedY) {
|
||||
$file = $this->createMock(File::class);
|
||||
$file->method('getMimeType')
|
||||
->willReturn('myMimeType');
|
||||
$file->method('getId')
|
||||
->willReturn(42);
|
||||
|
||||
$this->previewManager->method('isMimeSupported')
|
||||
->with($this->equalTo('myMimeType'))
|
||||
->willReturn(true);
|
||||
|
||||
$previewFolder = $this->createMock(ISimpleFolder::class);
|
||||
$this->appData->method('getFolder')
|
||||
->with($this->equalTo(42))
|
||||
->willReturn($previewFolder);
|
||||
|
||||
$maxPreview = $this->createMock(ISimpleFile::class);
|
||||
$maxPreview->method('getName')
|
||||
->willReturn($maxX . '-' . $maxY . '-max.png');
|
||||
|
||||
$previewFolder->method('getDirectoryListing')
|
||||
->willReturn([$maxPreview]);
|
||||
|
||||
$filename = $expectedX . '-' . $expectedY;
|
||||
if ($crop) {
|
||||
$filename .= '-crop';
|
||||
}
|
||||
$filename .= '.png';
|
||||
$previewFolder->method('getFile')
|
||||
->with($this->equalTo($filename))
|
||||
->willThrowException(new NotFoundException());
|
||||
|
||||
$image = $this->createMock(IImage::class);
|
||||
$this->helper->method('getImage')
|
||||
->with($this->equalTo($maxPreview))
|
||||
->willReturn($image);
|
||||
$image->method('height')->willReturn($maxY);
|
||||
$image->method('width')->willReturn($maxX);
|
||||
|
||||
$preview = $this->createMock(ISimpleFile::class);
|
||||
$previewFolder->method('newFile')
|
||||
->with($this->equalTo($filename))
|
||||
->willReturn($preview);
|
||||
|
||||
$result = $this->generator->getPreview($file, $reqX, $reqY, $crop, $mode);
|
||||
$this->assertSame($preview, $result);
|
||||
}
|
||||
}
|
||||
|
|
@ -63,7 +63,7 @@ class UrlGeneratorTest extends \Test\TestCase {
|
|||
public function provideRoutes() {
|
||||
return array(
|
||||
array('files_ajax_list', 'http://localhost/owncloud/index.php/apps/files/ajax/list.php'),
|
||||
array('core_ajax_preview', 'http://localhost/owncloud/index.php/core/preview.png'),
|
||||
array('core.Preview.getPreview', 'http://localhost/owncloud/index.php/core/preview.png'),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue