summaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
authorJulius Haertl <jus@bitgrid.net>2016-09-18 20:15:06 +0200
committerJulius Haertl <jus@bitgrid.net>2016-11-18 10:23:24 +0100
commit492d0b9f9bd72591183ff8bf4e8d5f9b4aecba35 (patch)
treeb275b40ab0b278ef690cf445a9e5e8baae196d8e /apps
parent9e28a3ba120356b03063e44445a9401c3aa205f3 (diff)
downloadnextcloud-server-492d0b9f9bd72591183ff8bf4e8d5f9b4aecba35.tar.gz
nextcloud-server-492d0b9f9bd72591183ff8bf4e8d5f9b4aecba35.zip
Caching for icon files using AppData
Signed-off-by: Julius Haertl <jus@bitgrid.net>
Diffstat (limited to 'apps')
-rw-r--r--apps/theming/lib/Controller/IconController.php53
-rw-r--r--apps/theming/lib/IconBuilder.php18
-rw-r--r--apps/theming/lib/ImageManager.php118
-rw-r--r--apps/theming/tests/Controller/IconControllerTest.php133
-rw-r--r--apps/theming/tests/IconBuilderTest.php19
-rw-r--r--apps/theming/tests/ImageManagerTest.php185
6 files changed, 433 insertions, 93 deletions
diff --git a/apps/theming/lib/Controller/IconController.php b/apps/theming/lib/Controller/IconController.php
index f2355fe3f82..eb65ae54f1a 100644
--- a/apps/theming/lib/Controller/IconController.php
+++ b/apps/theming/lib/Controller/IconController.php
@@ -23,13 +23,16 @@
namespace OCA\Theming\Controller;
use OCA\Theming\IconBuilder;
+use OCA\Theming\ImageManager;
use OCA\Theming\ThemingDefaults;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataDisplayResponse;
+use OCP\AppFramework\Http\FileDisplayResponse;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\IRequest;
use OCA\Theming\Util;
+use OCP\IConfig;
class IconController extends Controller {
/** @var ThemingDefaults */
@@ -38,8 +41,12 @@ class IconController extends Controller {
private $util;
/** @var ITimeFactory */
private $timeFactory;
+ /** @var IConfig */
+ private $config;
/** @var IconBuilder */
private $iconBuilder;
+ /** @var ImageManager */
+ private $imageManager;
/**
* IconController constructor.
@@ -49,7 +56,9 @@ class IconController extends Controller {
* @param ThemingDefaults $themingDefaults
* @param Util $util
* @param ITimeFactory $timeFactory
+ * @param IConfig $config
* @param IconBuilder $iconBuilder
+ * @param ImageManager $imageManager
*/
public function __construct(
$appName,
@@ -57,14 +66,18 @@ class IconController extends Controller {
ThemingDefaults $themingDefaults,
Util $util,
ITimeFactory $timeFactory,
- IconBuilder $iconBuilder
+ IConfig $config,
+ IconBuilder $iconBuilder,
+ ImageManager $imageManager
) {
parent::__construct($appName, $request);
$this->themingDefaults = $themingDefaults;
$this->util = $util;
$this->timeFactory = $timeFactory;
+ $this->config = $config;
$this->iconBuilder = $iconBuilder;
+ $this->imageManager = $imageManager;
}
/**
@@ -73,14 +86,15 @@ class IconController extends Controller {
*
* @param $app string app name
* @param $image string image file name (svg required)
- * @return DataDisplayResponse
+ * @return FileDisplayResponse
*/
public function getThemedIcon($app, $image) {
- $image = $this->util->getAppImage($app, $image);
- $svg = file_get_contents($image);
- $color = $this->util->elementColor($this->themingDefaults->getMailHeaderColor());
- $svg = $this->util->colorizeSvg($svg, $color);
- $response = new DataDisplayResponse($svg, Http::STATUS_OK, ['Content-Type' => 'image/svg+xml']);
+ $iconFile = $this->imageManager->getCachedImage("icon-" . $app . '-' . str_replace("/","_",$image));
+ if ($iconFile === null) {
+ $icon = $this->iconBuilder->colorSvg($app, $image);
+ $iconFile = $this->imageManager->setCachedImage("icon-" . $app . '-' . str_replace("/","_",$image), $icon);
+ }
+ $response = new FileDisplayResponse($iconFile, Http::STATUS_OK, ['Content-Type' => 'image/svg+xml']);
$response->cacheFor(86400);
$response->addHeader('Expires', date(\DateTime::RFC2822, $this->timeFactory->getTime()));
$response->addHeader('Pragma', 'cache');
@@ -94,12 +108,16 @@ class IconController extends Controller {
* @NoCSRFRequired
*
* @param $app string app name
- * @return DataDisplayResponse
+ * @return FileDisplayResponse|DataDisplayResponse
*/
- public function getFavicon($app="core") {
- if($this->themingDefaults->shouldReplaceIcons()) {
+ public function getFavicon($app = "core") {
+ $iconFile = $this->imageManager->getCachedImage('favIcon-' . $app);
+ if($iconFile === null && $this->themingDefaults->shouldReplaceIcons()) {
$icon = $this->iconBuilder->getFavicon($app);
- $response = new DataDisplayResponse($icon, Http::STATUS_OK, ['Content-Type' => 'image/x-icon']);
+ $iconFile = $this->imageManager->setCachedImage('favIcon-' . $app, $icon);
+ }
+ if ($this->themingDefaults->shouldReplaceIcons()) {
+ $response = new FileDisplayResponse($iconFile, Http::STATUS_OK, ['Content-Type' => 'image/x-icon']);
} else {
$response = new DataDisplayResponse(null, Http::STATUS_NOT_FOUND);
}
@@ -116,12 +134,16 @@ class IconController extends Controller {
* @NoCSRFRequired
*
* @param $app string app name
- * @return DataDisplayResponse
+ * @return FileDisplayResponse|DataDisplayResponse
*/
- public function getTouchIcon($app="core") {
- if($this->themingDefaults->shouldReplaceIcons()) {
+ public function getTouchIcon($app = "core") {
+ $iconFile = $this->imageManager->getCachedImage('touchIcon-' . $app);
+ if ($iconFile === null && $this->themingDefaults->shouldReplaceIcons()) {
$icon = $this->iconBuilder->getTouchIcon($app);
- $response = new DataDisplayResponse($icon, Http::STATUS_OK, ['Content-Type' => 'image/png']);
+ $iconFile = $this->imageManager->setCachedImage('touchIcon-' . $app, $icon);
+ }
+ if ($this->themingDefaults->shouldReplaceIcons()) {
+ $response = new FileDisplayResponse($iconFile, Http::STATUS_OK, ['Content-Type' => 'image/png']);
} else {
$response = new DataDisplayResponse(null, Http::STATUS_NOT_FOUND);
}
@@ -130,5 +152,4 @@ class IconController extends Controller {
$response->addHeader('Pragma', 'cache');
return $response;
}
-
} \ No newline at end of file
diff --git a/apps/theming/lib/IconBuilder.php b/apps/theming/lib/IconBuilder.php
index edd7602a2e4..10ba3cacc43 100644
--- a/apps/theming/lib/IconBuilder.php
+++ b/apps/theming/lib/IconBuilder.php
@@ -80,19 +80,21 @@ class IconBuilder {
*/
public function renderAppIcon($app) {
$appIcon = $this->util->getAppIcon($app);
+ $appIconContent = file_get_contents($appIcon);
$color = $this->themingDefaults->getMailHeaderColor();
$mime = mime_content_type($appIcon);
+
// generate background image with rounded corners
$background = '<?xml version="1.0" encoding="UTF-8"?>' .
'<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:cc="http://creativecommons.org/ns#" width="512" height="512" xmlns:xlink="http://www.w3.org/1999/xlink">' .
'<rect x="0" y="0" rx="75" ry="75" width="512" height="512" style="fill:' . $color . ';" />' .
'</svg>';
-
// resize svg magic as this seems broken in Imagemagick
- if($mime === "image/svg+xml") {
- $svg = file_get_contents($appIcon);
-
+ if($mime === "image/svg+xml" || substr($appIconContent, 0, 4) === "<svg") {
+ if(substr($appIconContent, 0, 5) !== "<?xml") {
+ $svg = "<?xml version=\"1.0\"?>".$appIconContent;
+ }
$tmp = new Imagick();
$tmp->readImageBlob($svg);
$x = $tmp->getImageWidth();
@@ -137,4 +139,12 @@ class IconBuilder {
return $finalIconFile;
}
+ public function colorSvg($app, $image) {
+ $imageFile = $this->util->getAppImage($app, $image);
+ $svg = file_get_contents($imageFile);
+ $color = $this->util->elementColor($this->themingDefaults->getMailHeaderColor());
+ $svg = $this->util->colorizeSvg($svg, $color);
+ return $svg;
+ }
+
} \ No newline at end of file
diff --git a/apps/theming/lib/ImageManager.php b/apps/theming/lib/ImageManager.php
new file mode 100644
index 00000000000..5e1b61e3a92
--- /dev/null
+++ b/apps/theming/lib/ImageManager.php
@@ -0,0 +1,118 @@
+<?php
+/**
+ * @copyright Copyright (c) 2016 Julius Härtl <jus@bitgrid.net>
+ *
+ * @author Julius Härtl <jus@bitgrid.net>
+ *
+ * @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\Theming;
+
+use OCP\IConfig;
+use OCP\Files\IAppData;
+use OCP\Files\NotFoundException;
+use OCP\Files\NotPermittedException;
+
+class ImageManager {
+
+ /** @var IConfig */
+ private $config;
+ /** @var IAppData */
+ private $appData;
+
+ /**
+ * ImageManager constructor.
+ *
+ * @param IConfig $config
+ * @param IAppData $appData
+ */
+ public function __construct(IConfig $config,
+ IAppData $appData
+ ) {
+ $this->config = $config;
+ $this->appData = $appData;
+ }
+
+ /**
+ * Get folder for current theming files
+ *
+ * @return \OCP\Files\SimpleFS\ISimpleFolder
+ * @throws NotPermittedException
+ * @throws \RuntimeException
+ */
+ public function getCacheFolder() {
+ $cacheBusterValue = $this->config->getAppValue('theming', 'cachebuster', '0');
+ try {
+ $folder = $this->appData->getFolder($cacheBusterValue);
+ } catch (NotFoundException $e) {
+ $folder = $this->appData->newFolder($cacheBusterValue);
+ $this->cleanup();
+ }
+ return $folder;
+ }
+
+ /**
+ * Get a file from AppData
+ *
+ * @param string $filename
+ * @return null|\OCP\Files\SimpleFS\ISimpleFile
+ */
+ public function getCachedImage($filename) {
+ $currentFolder = $this->getCacheFolder();
+ if($currentFolder->fileExists($filename)) {
+ return $currentFolder->getFile($filename);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Store a file for theming in AppData
+ *
+ * @param string $filename
+ * @param string $data
+ * @return \OCP\Files\SimpleFS\ISimpleFile
+ */
+ public function setCachedImage($filename, $data) {
+ $currentFolder = $this->getCacheFolder();
+ if ($currentFolder->fileExists($filename)) {
+ $file = $currentFolder->getFile($filename);
+ } else {
+ $file = $currentFolder->newFile($filename);
+ }
+ $file->putContent($data);
+ return $file;
+ }
+
+ /**
+ * remove cached files that are not required any longer
+ */
+ public function cleanup() {
+ $currentFolder = $this->getCacheFolder();
+ $folders = $this->appData->getDirectoryListing();
+ foreach ($folders as $folder) {
+ if ($folder->getName() !== $currentFolder->getName()) {
+ $folder->delete();
+ }
+ }
+ }
+
+
+
+}
diff --git a/apps/theming/tests/Controller/IconControllerTest.php b/apps/theming/tests/Controller/IconControllerTest.php
index 09cb41088de..82a937c3b91 100644
--- a/apps/theming/tests/Controller/IconControllerTest.php
+++ b/apps/theming/tests/Controller/IconControllerTest.php
@@ -23,12 +23,18 @@
namespace OCA\Theming\Tests\Controller;
+use OC\Files\SimpleFS\SimpleFile;
+use OCA\Theming\ImageManager;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataDisplayResponse;
+use OCP\Files\IRootFolder;
+use OCP\IConfig;
+use OCP\IL10N;
use OCP\IRequest;
use Test\TestCase;
use OCA\Theming\Util;
use OCA\Theming\Controller\IconController;
+use OCP\AppFramework\Http\FileDisplayResponse;
class IconControllerTest extends TestCase {
@@ -42,8 +48,12 @@ class IconControllerTest extends TestCase {
private $timeFactory;
/** @var IL10N|\PHPUnit_Framework_MockObject_MockObject */
private $iconController;
+ /** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */
+ private $config;
/** @var IRootFolder|\PHPUnit_Framework_MockObject_MockObject */
private $iconBuilder;
+ /** @var ImageManager */
+ private $imageManager;
public function setUp() {
$this->request = $this->getMockBuilder('OCP\IRequest')->getMock();
@@ -54,9 +64,10 @@ class IconControllerTest extends TestCase {
$this->timeFactory = $this->getMockBuilder('OCP\AppFramework\Utility\ITimeFactory')
->disableOriginalConstructor()
->getMock();
+ $this->config = $this->getMockBuilder('OCP\IConfig')->getMock();
$this->iconBuilder = $this->getMockBuilder('OCA\Theming\IconBuilder')
->disableOriginalConstructor()->getMock();
-
+ $this->imageManager = $this->getMockBuilder('OCA\Theming\ImageManager')->disableOriginalConstructor()->getMock();
$this->timeFactory->expects($this->any())
->method('getTime')
->willReturn(123);
@@ -67,124 +78,114 @@ class IconControllerTest extends TestCase {
$this->themingDefaults,
$this->util,
$this->timeFactory,
- $this->iconBuilder
+ $this->config,
+ $this->iconBuilder,
+ $this->imageManager
);
parent::setUp();
}
+ private function iconFileMock($filename, $data) {
+ $icon = $this->getMockBuilder('OCP\Files\File')->getMock();
+ $icon->expects($this->any())->method('getContent')->willReturn($data);
+ $icon->expects($this->any())->method('getMimeType')->willReturn('image type');
+ $icon->expects($this->any())->method('getEtag')->willReturn('my etag');
+ $icon->method('getName')->willReturn($filename);
+ return new SimpleFile($icon);
+ }
+
public function testGetThemedIcon() {
- $this->util->expects($this->once())
- ->method('getAppImage')
- ->with('core','filetypes/folder.svg')
- ->willReturn(\OC::$SERVERROOT . "/core/img/filetypes/folder.svg");
- $this->themingDefaults
- ->expects($this->once())
- ->method('getMailHeaderColor')
- ->willReturn('#000000');
- $this->util
- ->expects($this->once())
- ->method('elementColor')
- ->willReturn('#000000');
-
- $svg = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>
-<svg xmlns=\"http://www.w3.org/2000/svg\" height=\"16\" width=\"16\" version=\"1.0\">
- <g fill-rule=\"evenodd\" transform=\"matrix(.86667 0 0 .86667 -172.05 -864.43)\" fill=\"#000000\">
- <path d=\"m200.2 999.72c-0.28913 0-0.53125 0.2421-0.53125 0.53117v12.784c0 0.2985 0.23264 0.5312 0.53125 0.5312h15.091c0.2986 0 0.53124-0.2327 0.53124-0.5312l0.0004-10.474c0-0.2889-0.24211-0.5338-0.53124-0.5338l-7.5457 0.0005-2.3076-2.3078z\" fill-rule=\"evenodd\" fill=\"#000000\"/>
- </g>
-</svg>
-";
- $expected = new DataDisplayResponse($svg, Http::STATUS_OK, ['Content-Type' => 'image/svg+xml']);
+ $file = $this->iconFileMock('icon-core-filetypes_folder.svg', 'filecontent');
+ $this->imageManager->expects($this->once())
+ ->method('getCachedImage')
+ ->with('icon-core-filetypes_folder.svg')
+ ->willReturn($file);
+ $expected = new FileDisplayResponse($file, Http::STATUS_OK, ['Content-Type' => 'image/svg+xml']);
$expected->cacheFor(86400);
$expected->addHeader('Expires', date(\DateTime::RFC2822, $this->timeFactory->getTime()));
$expected->addHeader('Pragma', 'cache');
- @$this->assertEquals($expected, $this->iconController->getThemedIcon('core','filetypes/folder.svg'));
+ @$this->assertEquals($expected, $this->iconController->getThemedIcon('core', 'filetypes/folder.svg'));
+
+
}
public function testGetFaviconDefault() {
- if(!extension_loaded('imagick')) {
+ if (!extension_loaded('imagick')) {
$this->markTestSkipped('Imagemagick is required for dynamic icon generation.');
}
$checkImagick = new \Imagick();
if (count($checkImagick->queryFormats('SVG')) < 1) {
$this->markTestSkipped('No SVG provider present.');
}
- $this->themingDefaults->expects($this->once())
+ $this->themingDefaults->expects($this->any())
->method('shouldReplaceIcons')
->willReturn(true);
- $expectedIcon = new \Imagick(realpath(dirname(__FILE__)) . '/../data/favicon-original.ico');
+
$this->iconBuilder->expects($this->once())
->method('getFavicon')
->with('core')
- ->willReturn($expectedIcon);
- $favicon = $this->iconController->getFavicon();
+ ->willReturn('filecontent');
+ $file = $this->iconFileMock('filename', 'filecontent');
+ $this->imageManager->expects($this->once())
+ ->method('setCachedImage')
+ ->willReturn($file);
- $expected = new DataDisplayResponse($expectedIcon, Http::STATUS_OK, ['Content-Type' => 'image/x-icon']);
+ $expected = new FileDisplayResponse($file, Http::STATUS_OK, ['Content-Type' => 'image/x-icon']);
$expected->cacheFor(86400);
$expected->addHeader('Expires', date(\DateTime::RFC2822, $this->timeFactory->getTime()));
$expected->addHeader('Pragma', 'cache');
- $this->assertEquals($expected, $favicon);
+ $this->assertEquals($expected, $this->iconController->getFavicon());
}
+
+ public function testGetFaviconFail() {
+ $this->themingDefaults->expects($this->any())
+ ->method('shouldReplaceIcons')
+ ->willReturn(false);
+ $expected = new DataDisplayResponse(null, Http::STATUS_NOT_FOUND);
+ $expected->cacheFor(86400);
+ $expected->addHeader('Expires', date(\DateTime::RFC2822, $this->timeFactory->getTime()));
+ $expected->addHeader('Pragma', 'cache');
+ $this->assertEquals($expected, $this->iconController->getFavicon());
+ }
+
public function testGetTouchIconDefault() {
- if(!extension_loaded('imagick')) {
+ if (!extension_loaded('imagick')) {
$this->markTestSkipped('Imagemagick is required for dynamic icon generation.');
}
$checkImagick = new \Imagick();
if (count($checkImagick->queryFormats('SVG')) < 1) {
$this->markTestSkipped('No SVG provider present.');
}
- $this->themingDefaults->expects($this->once())
+ $this->themingDefaults->expects($this->any())
->method('shouldReplaceIcons')
->willReturn(true);
- $expectedIcon = new \Imagick(realpath(dirname(__FILE__)) . '/../data/touch-original.png');
+
$this->iconBuilder->expects($this->once())
->method('getTouchIcon')
->with('core')
- ->willReturn($expectedIcon);
- $favicon = $this->iconController->getTouchIcon();
+ ->willReturn('filecontent');
+ $file = $this->iconFileMock('filename', 'filecontent');
+ $this->imageManager->expects($this->once())
+ ->method('setCachedImage')
+ ->willReturn($file);
- $expected = new DataDisplayResponse($expectedIcon, Http::STATUS_OK, ['Content-Type' => 'image/png']);
+ $expected = new FileDisplayResponse($file, Http::STATUS_OK, ['Content-Type' => 'image/png']);
$expected->cacheFor(86400);
$expected->addHeader('Expires', date(\DateTime::RFC2822, $this->timeFactory->getTime()));
$expected->addHeader('Pragma', 'cache');
- $this->assertEquals($expected, $favicon);
+ $this->assertEquals($expected, $this->iconController->getTouchIcon());
}
- public function testGetFaviconFail() {
- if(!extension_loaded('imagick')) {
- $this->markTestSkipped('Imagemagick is required for dynamic icon generation.');
- }
- $checkImagick = new \Imagick();
- if (count($checkImagick->queryFormats('SVG')) < 1) {
- $this->markTestSkipped('No SVG provider present.');
- }
- $this->themingDefaults->expects($this->once())
- ->method('shouldReplaceIcons')
- ->willReturn(false);
- $favicon = $this->iconController->getFavicon();
- $expected = new DataDisplayResponse(null, Http::STATUS_NOT_FOUND);
- $expected->cacheFor(86400);
- $expected->addHeader('Expires', date(\DateTime::RFC2822, $this->timeFactory->getTime()));
- $expected->addHeader('Pragma', 'cache');
- $this->assertEquals($expected, $favicon);
- }
public function testGetTouchIconFail() {
- if(!extension_loaded('imagick')) {
- $this->markTestSkipped('Imagemagick is required for dynamic icon generation.');
- }
- $checkImagick = new \Imagick();
- if (count($checkImagick->queryFormats('SVG')) < 1) {
- $this->markTestSkipped('No SVG provider present.');
- }
- $this->themingDefaults->expects($this->once())
+ $this->themingDefaults->expects($this->any())
->method('shouldReplaceIcons')
->willReturn(false);
- $favicon = $this->iconController->getTouchIcon();
$expected = new DataDisplayResponse(null, Http::STATUS_NOT_FOUND);
$expected->cacheFor(86400);
$expected->addHeader('Expires', date(\DateTime::RFC2822, $this->timeFactory->getTime()));
$expected->addHeader('Pragma', 'cache');
- $this->assertEquals($expected, $favicon);
+ $this->assertEquals($expected, $this->iconController->getTouchIcon());
}
}
diff --git a/apps/theming/tests/IconBuilderTest.php b/apps/theming/tests/IconBuilderTest.php
index 03054367210..529518b30de 100644
--- a/apps/theming/tests/IconBuilderTest.php
+++ b/apps/theming/tests/IconBuilderTest.php
@@ -45,6 +45,15 @@ class IconBuilderTest extends TestCase {
protected function setUp() {
parent::setUp();
+ $this->config = $this->getMockBuilder('\OCP\IConfig')->getMock();
+ $this->rootFolder = $this->getMockBuilder('OCP\Files\IRootFolder')->getMock();
+ $this->themingDefaults = $this->getMockBuilder('OCA\Theming\ThemingDefaults')
+ ->disableOriginalConstructor()->getMock();
+ $this->util = new Util($this->config, $this->rootFolder);
+ $this->iconBuilder = new IconBuilder($this->themingDefaults, $this->util);
+ }
+
+ private function checkImagick() {
if(!extension_loaded('imagick')) {
$this->markTestSkipped('Imagemagick is required for dynamic icon generation.');
}
@@ -52,13 +61,6 @@ class IconBuilderTest extends TestCase {
if (count($checkImagick->queryFormats('SVG')) < 1) {
$this->markTestSkipped('No SVG provider present.');
}
-
- $this->config = $this->getMockBuilder('\OCP\IConfig')->getMock();
- $this->rootFolder = $this->getMockBuilder('OCP\Files\IRootFolder')->getMock();
- $this->themingDefaults = $this->getMockBuilder('OCA\Theming\ThemingDefaults')
- ->disableOriginalConstructor()->getMock();
- $this->util = new Util($this->config, $this->rootFolder);
- $this->iconBuilder = new IconBuilder($this->themingDefaults, $this->util);
}
public function dataRenderAppIcon() {
@@ -78,6 +80,7 @@ class IconBuilderTest extends TestCase {
* @param $file
*/
public function testRenderAppIcon($app, $color, $file) {
+ $this->checkImagick();
$this->themingDefaults->expects($this->once())
->method('getMailHeaderColor')
->willReturn($color);
@@ -102,6 +105,7 @@ class IconBuilderTest extends TestCase {
* @param $file
*/
public function testGetTouchIcon($app, $color, $file) {
+ $this->checkImagick();
$this->themingDefaults->expects($this->once())
->method('getMailHeaderColor')
->willReturn($color);
@@ -127,6 +131,7 @@ class IconBuilderTest extends TestCase {
* @param $file
*/
public function testGetFavicon($app, $color, $file) {
+ $this->checkImagick();
$this->themingDefaults->expects($this->once())
->method('getMailHeaderColor')
->willReturn($color);
diff --git a/apps/theming/tests/ImageManagerTest.php b/apps/theming/tests/ImageManagerTest.php
new file mode 100644
index 00000000000..b52d557ab67
--- /dev/null
+++ b/apps/theming/tests/ImageManagerTest.php
@@ -0,0 +1,185 @@
+<?php
+/**
+ * @copyright Copyright (c) 2016 Julius Härtl <jus@bitgrid.net>
+ *
+ * @author Julius Härtl <jus@bitgrid.net>
+ *
+ * @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\Theming\Tests;
+
+use OCP\Files\SimpleFS\ISimpleFile;
+use OCP\IConfig;
+use Test\TestCase;
+use OCP\Files\SimpleFS\ISimpleFolder;
+use OCP\Files\IAppData;
+use OCP\Files\NotFoundException;
+
+class ImageManager extends TestCase {
+
+ /** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */
+ protected $config;
+ /** @var IAppData|\PHPUnit_Framework_MockObject_MockObject */
+ protected $appData;
+ /** @var ImageManager */
+ protected $imageManager;
+
+ protected function setUp() {
+ parent::setUp();
+ $this->config = $this->getMockBuilder('\OCP\IConfig')->getMock();
+ $this->appData = $this->getMockBuilder('OCP\Files\IAppData')->getMock();
+ $this->imageManager = new \OCA\Theming\ImageManager(
+ $this->config,
+ $this->appData
+ );
+ }
+
+ public function testGetCacheFolder() {
+ $folder = $this->createMock(ISimpleFolder::class);
+ $this->config->expects($this->once())
+ ->method('getAppValue')
+ ->with('theming', 'cachebuster', '0')
+ ->willReturn('0');
+ $this->appData->expects($this->at(0))
+ ->method('getFolder')
+ ->with('0')
+ ->willReturn($folder);
+ $this->assertEquals($folder, $this->imageManager->getCacheFolder());
+ }
+ public function testGetCacheFolderCreate() {
+ $folder = $this->createMock(ISimpleFolder::class);
+ $this->config->expects($this->exactly(2))
+ ->method('getAppValue')
+ ->with('theming', 'cachebuster', '0')
+ ->willReturn('0');
+ $this->appData->expects($this->at(0))
+ ->method('getFolder')
+ ->willThrowException(new NotFoundException());
+ $this->appData->expects($this->at(1))
+ ->method('newFolder')
+ ->with('0')
+ ->willReturn($folder);
+ $this->appData->expects($this->at(2))
+ ->method('getFolder')
+ ->with('0')
+ ->willReturn($folder);
+ $this->appData->expects($this->once())
+ ->method('getDirectoryListing')
+ ->willReturn([]);
+ $this->assertEquals($folder, $this->imageManager->getCacheFolder());
+ }
+
+ public function testGetCachedImage() {
+ $folder = $this->setupCacheFolder();
+ $folder->expects($this->once())
+ ->method('fileExists')
+ ->with('filename')
+ ->willReturn(true);
+ $folder->expects($this->once())
+ ->method('getFile')
+ ->with('filename')
+ ->willReturn('filecontent');
+ $expected = 'filecontent';
+ $this->assertEquals($expected, $this->imageManager->getCachedImage('filename'));
+ }
+
+ public function testGetCachedImageNotFound() {
+ $folder = $this->setupCacheFolder();
+ $folder->expects($this->once())
+ ->method('fileExists')
+ ->with('filename')
+ ->willReturn(false);
+ $expected = null;
+ $this->assertEquals($expected, $this->imageManager->getCachedImage('filename'));
+ }
+
+ public function testSetCachedImage() {
+ $folder = $this->setupCacheFolder();
+ $file = $this->createMock(ISimpleFile::class);
+ $folder->expects($this->once())
+ ->method('fileExists')
+ ->with('filename')
+ ->willReturn(true);
+ $folder->expects($this->once())
+ ->method('getFile')
+ ->with('filename')
+ ->willReturn($file);
+ $file->expects($this->once())
+ ->method('putContent')
+ ->with('filecontent');
+ $this->assertEquals($file, $this->imageManager->setCachedImage('filename', 'filecontent'));
+ }
+
+ public function testSetCachedImageCreate() {
+ $folder = $this->setupCacheFolder();
+ $file = $this->createMock(ISimpleFile::class);
+ $folder->expects($this->once())
+ ->method('fileExists')
+ ->with('filename')
+ ->willReturn(false);
+ $folder->expects($this->once())
+ ->method('newFile')
+ ->with('filename')
+ ->willReturn($file);
+ $file->expects($this->once())
+ ->method('putContent')
+ ->with('filecontent');
+ $this->assertEquals($file, $this->imageManager->setCachedImage('filename', 'filecontent'));
+ }
+
+ private function setupCacheFolder() {
+ $folder = $this->createMock(ISimpleFolder::class);
+ $this->config->expects($this->once())
+ ->method('getAppValue')
+ ->with('theming', 'cachebuster', '0')
+ ->willReturn('0');
+ $this->appData->expects($this->at(0))
+ ->method('getFolder')
+ ->with('0')
+ ->willReturn($folder);
+ return $folder;
+ }
+
+ public function testCleanup() {
+ $folders = [
+ $this->createMock(ISimpleFolder::class),
+ $this->createMock(ISimpleFolder::class),
+ $this->createMock(ISimpleFolder::class)
+ ];
+ foreach ($folders as $index=>$folder) {
+ $folder->expects($this->any())
+ ->method('getName')
+ ->willReturn($index);
+ }
+ $folders[0]->expects($this->once())->method('delete');
+ $folders[1]->expects($this->once())->method('delete');
+ $folders[2]->expects($this->never())->method('delete');
+ $this->config->expects($this->once())
+ ->method('getAppValue')
+ ->with('theming','cachebuster','0')
+ ->willReturn('2');
+ $this->appData->expects($this->once())
+ ->method('getDirectoryListing')
+ ->willReturn($folders);
+ $this->appData->expects($this->once())
+ ->method('getFolder')
+ ->with('2')
+ ->willReturn($folders[2]);
+ $this->imageManager->cleanup();
+ }
+
+}