Merge pull request #9258 from nextcloud/theming-logo-png
Convert theming app logo to PNG to show it properly in emails
This commit is contained in:
commit
8f6acbff62
|
@ -119,7 +119,7 @@ class IconController extends Controller {
|
||||||
$response = new FileDisplayResponse($iconFile, Http::STATUS_OK, ['Content-Type' => 'image/x-icon']);
|
$response = new FileDisplayResponse($iconFile, Http::STATUS_OK, ['Content-Type' => 'image/x-icon']);
|
||||||
} catch (NotFoundException $e) {
|
} catch (NotFoundException $e) {
|
||||||
}
|
}
|
||||||
if ($iconFile === null && $this->themingDefaults->shouldReplaceIcons()) {
|
if ($iconFile === null && $this->imageManager->shouldReplaceIcons()) {
|
||||||
try {
|
try {
|
||||||
$iconFile = $this->imageManager->getCachedImage('favIcon-' . $app);
|
$iconFile = $this->imageManager->getCachedImage('favIcon-' . $app);
|
||||||
} catch (NotFoundException $exception) {
|
} catch (NotFoundException $exception) {
|
||||||
|
@ -155,7 +155,7 @@ class IconController extends Controller {
|
||||||
$response = new FileDisplayResponse($iconFile, Http::STATUS_OK, ['Content-Type' => 'image/x-icon']);
|
$response = new FileDisplayResponse($iconFile, Http::STATUS_OK, ['Content-Type' => 'image/x-icon']);
|
||||||
} catch (NotFoundException $e) {
|
} catch (NotFoundException $e) {
|
||||||
}
|
}
|
||||||
if ($this->themingDefaults->shouldReplaceIcons()) {
|
if ($this->imageManager->shouldReplaceIcons()) {
|
||||||
try {
|
try {
|
||||||
$iconFile = $this->imageManager->getCachedImage('touchIcon-' . $app);
|
$iconFile = $this->imageManager->getCachedImage('touchIcon-' . $app);
|
||||||
} catch (NotFoundException $exception) {
|
} catch (NotFoundException $exception) {
|
||||||
|
|
|
@ -262,6 +262,8 @@ class ThemingController extends Controller {
|
||||||
$folder = $this->appData->newFolder('images');
|
$folder = $this->appData->newFolder('images');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->imageManager->delete($key);
|
||||||
|
|
||||||
$target = $folder->newFile($key);
|
$target = $folder->newFile($key);
|
||||||
$supportedFormats = ['image/jpeg', 'image/png', 'image/gif', 'image/svg+xml', 'image/svg'];
|
$supportedFormats = ['image/jpeg', 'image/png', 'image/gif', 'image/svg+xml', 'image/svg'];
|
||||||
$detectedMimeType = mime_content_type($image['tmp_name']);
|
$detectedMimeType = mime_content_type($image['tmp_name']);
|
||||||
|
@ -351,12 +353,13 @@ class ThemingController extends Controller {
|
||||||
* @NoCSRFRequired
|
* @NoCSRFRequired
|
||||||
*
|
*
|
||||||
* @param string $key
|
* @param string $key
|
||||||
|
* @param bool $useSvg
|
||||||
* @return FileDisplayResponse|NotFoundResponse
|
* @return FileDisplayResponse|NotFoundResponse
|
||||||
* @throws \Exception
|
* @throws NotPermittedException
|
||||||
*/
|
*/
|
||||||
public function getImage(string $key) {
|
public function getImage(string $key, bool $useSvg = true) {
|
||||||
try {
|
try {
|
||||||
$file = $this->imageManager->getImage($key);
|
$file = $this->imageManager->getImage($key, $useSvg);
|
||||||
} catch (NotFoundException $e) {
|
} catch (NotFoundException $e) {
|
||||||
return new NotFoundResponse();
|
return new NotFoundResponse();
|
||||||
}
|
}
|
||||||
|
@ -365,6 +368,11 @@ class ThemingController extends Controller {
|
||||||
$response->cacheFor(3600);
|
$response->cacheFor(3600);
|
||||||
$response->addHeader('Content-Type', $this->config->getAppValue($this->appName, $key . 'Mime', ''));
|
$response->addHeader('Content-Type', $this->config->getAppValue($this->appName, $key . 'Mime', ''));
|
||||||
$response->addHeader('Content-Disposition', 'attachment; filename="' . $key . '"');
|
$response->addHeader('Content-Disposition', 'attachment; filename="' . $key . '"');
|
||||||
|
if (!$useSvg) {
|
||||||
|
$response->addHeader('Content-Type', 'image/png');
|
||||||
|
} else {
|
||||||
|
$response->addHeader('Content-Type', $this->config->getAppValue($this->appName, $key . 'Mime', ''));
|
||||||
|
}
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,19 +35,24 @@ class IconBuilder {
|
||||||
private $themingDefaults;
|
private $themingDefaults;
|
||||||
/** @var Util */
|
/** @var Util */
|
||||||
private $util;
|
private $util;
|
||||||
|
/** @var ImageManager */
|
||||||
|
private $imageManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IconBuilder constructor.
|
* IconBuilder constructor.
|
||||||
*
|
*
|
||||||
* @param ThemingDefaults $themingDefaults
|
* @param ThemingDefaults $themingDefaults
|
||||||
* @param Util $util
|
* @param Util $util
|
||||||
|
* @param ImageManager $imageManager
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
ThemingDefaults $themingDefaults,
|
ThemingDefaults $themingDefaults,
|
||||||
Util $util
|
Util $util,
|
||||||
|
ImageManager $imageManager
|
||||||
) {
|
) {
|
||||||
$this->themingDefaults = $themingDefaults;
|
$this->themingDefaults = $themingDefaults;
|
||||||
$this->util = $util;
|
$this->util = $util;
|
||||||
|
$this->imageManager = $imageManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -55,7 +60,7 @@ class IconBuilder {
|
||||||
* @return string|false image blob
|
* @return string|false image blob
|
||||||
*/
|
*/
|
||||||
public function getFavicon($app) {
|
public function getFavicon($app) {
|
||||||
if (!$this->themingDefaults->shouldReplaceIcons()) {
|
if (!$this->imageManager->shouldReplaceIcons()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -26,24 +26,28 @@ namespace OCA\Theming;
|
||||||
|
|
||||||
use OCP\Files\SimpleFS\ISimpleFile;
|
use OCP\Files\SimpleFS\ISimpleFile;
|
||||||
use OCP\Files\SimpleFS\ISimpleFolder;
|
use OCP\Files\SimpleFS\ISimpleFolder;
|
||||||
|
use OCP\ICacheFactory;
|
||||||
use OCP\IConfig;
|
use OCP\IConfig;
|
||||||
use OCP\Files\IAppData;
|
use OCP\Files\IAppData;
|
||||||
use OCP\Files\NotFoundException;
|
use OCP\Files\NotFoundException;
|
||||||
use OCP\Files\NotPermittedException;
|
use OCP\Files\NotPermittedException;
|
||||||
|
use OCP\ILogger;
|
||||||
use OCP\IURLGenerator;
|
use OCP\IURLGenerator;
|
||||||
|
|
||||||
/**
|
|
||||||
* @property IURLGenerator urlGenerator
|
|
||||||
*/
|
|
||||||
class ImageManager {
|
class ImageManager {
|
||||||
|
|
||||||
/** @var IConfig */
|
/** @var IConfig */
|
||||||
private $config;
|
private $config;
|
||||||
/** @var IAppData */
|
/** @var IAppData */
|
||||||
private $appData;
|
private $appData;
|
||||||
|
/** @var IURLGenerator */
|
||||||
|
private $urlGenerator;
|
||||||
/** @var array */
|
/** @var array */
|
||||||
private $supportedImageKeys = ['background', 'logo', 'logoheader', 'favicon'];
|
private $supportedImageKeys = ['background', 'logo', 'logoheader', 'favicon'];
|
||||||
|
/** @var ICacheFactory */
|
||||||
|
private $cacheFactory;
|
||||||
|
/** @var ILogger */
|
||||||
|
private $logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ImageManager constructor.
|
* ImageManager constructor.
|
||||||
|
@ -51,20 +55,26 @@ class ImageManager {
|
||||||
* @param IConfig $config
|
* @param IConfig $config
|
||||||
* @param IAppData $appData
|
* @param IAppData $appData
|
||||||
* @param IURLGenerator $urlGenerator
|
* @param IURLGenerator $urlGenerator
|
||||||
|
* @param ICacheFactory $cacheFactory
|
||||||
|
* @param ILogger $logger
|
||||||
*/
|
*/
|
||||||
public function __construct(IConfig $config,
|
public function __construct(IConfig $config,
|
||||||
IAppData $appData,
|
IAppData $appData,
|
||||||
IURLGenerator $urlGenerator
|
IURLGenerator $urlGenerator,
|
||||||
|
ICacheFactory $cacheFactory,
|
||||||
|
ILogger $logger
|
||||||
) {
|
) {
|
||||||
$this->config = $config;
|
$this->config = $config;
|
||||||
$this->appData = $appData;
|
$this->appData = $appData;
|
||||||
$this->urlGenerator = $urlGenerator;
|
$this->urlGenerator = $urlGenerator;
|
||||||
|
$this->cacheFactory = $cacheFactory;
|
||||||
|
$this->logger = $logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getImageUrl(string $key): string {
|
public function getImageUrl(string $key, bool $useSvg = true): string {
|
||||||
$cacheBusterCounter = $this->config->getAppValue('theming', 'cachebuster', '0');
|
$cacheBusterCounter = $this->config->getAppValue('theming', 'cachebuster', '0');
|
||||||
try {
|
try {
|
||||||
$this->getImage($key);
|
$image = $this->getImage($key, $useSvg);
|
||||||
return $this->urlGenerator->linkToRoute('theming.Theming.getImage', [ 'key' => $key ]) . '?v=' . $cacheBusterCounter;
|
return $this->urlGenerator->linkToRoute('theming.Theming.getImage', [ 'key' => $key ]) . '?v=' . $cacheBusterCounter;
|
||||||
} catch (NotFoundException $e) {
|
} catch (NotFoundException $e) {
|
||||||
}
|
}
|
||||||
|
@ -79,21 +89,44 @@ class ImageManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getImageUrlAbsolute(string $key): string {
|
public function getImageUrlAbsolute(string $key, bool $useSvg = true): string {
|
||||||
return $this->urlGenerator->getAbsoluteURL($this->getImageUrl($key));
|
return $this->urlGenerator->getAbsoluteURL($this->getImageUrl($key, $useSvg));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $key
|
* @param string $key
|
||||||
|
* @param bool $useSvg
|
||||||
* @return ISimpleFile
|
* @return ISimpleFile
|
||||||
* @throws NotFoundException
|
* @throws NotFoundException
|
||||||
|
* @throws NotPermittedException
|
||||||
*/
|
*/
|
||||||
public function getImage(string $key): ISimpleFile {
|
public function getImage(string $key, bool $useSvg = true): ISimpleFile {
|
||||||
|
$pngFile = null;
|
||||||
$logo = $this->config->getAppValue('theming', $key . 'Mime', false);
|
$logo = $this->config->getAppValue('theming', $key . 'Mime', false);
|
||||||
if ($logo === false) {
|
$folder = $this->appData->getFolder('images');
|
||||||
|
if ($logo === false || !$folder->fileExists($key)) {
|
||||||
throw new NotFoundException();
|
throw new NotFoundException();
|
||||||
}
|
}
|
||||||
$folder = $this->appData->getFolder('images');
|
if (!$useSvg && $this->shouldReplaceIcons()) {
|
||||||
|
if (!$folder->fileExists($key . '.png')) {
|
||||||
|
try {
|
||||||
|
$finalIconFile = new \Imagick();
|
||||||
|
$finalIconFile->setBackgroundColor('none');
|
||||||
|
$finalIconFile->readImageBlob($folder->getFile($key)->getContent());
|
||||||
|
$finalIconFile->setImageFormat('png32');
|
||||||
|
$pngFile = $folder->newFile($key . '.png');
|
||||||
|
$pngFile->putContent($finalIconFile->getImageBlob());
|
||||||
|
} catch (\ImagickException $e) {
|
||||||
|
$this->logger->info('The image was requested to be no SVG file, but converting it to PNG failed.', $e->getMessage());
|
||||||
|
$pngFile = null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$pngFile = $folder->getFile($key . '.png');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($pngFile !== null) {
|
||||||
|
return $pngFile;
|
||||||
|
}
|
||||||
return $folder->getFile($key);
|
return $folder->getFile($key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,12 +192,19 @@ class ImageManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function delete(string $key) {
|
public function delete(string $key) {
|
||||||
|
/* ignore exceptions, since we don't want to fail hard if something goes wrong during cleanup */
|
||||||
try {
|
try {
|
||||||
$file = $this->appData->getFolder('images')->getFile($key);
|
$file = $this->appData->getFolder('images')->getFile($key);
|
||||||
$file->delete();
|
$file->delete();
|
||||||
} catch (NotFoundException $e) {
|
} catch (NotFoundException $e) {
|
||||||
} catch (NotPermittedException $e) {
|
} catch (NotPermittedException $e) {
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
$file = $this->appData->getFolder('images')->getFile($key . '.png');
|
||||||
|
$file->delete();
|
||||||
|
} catch (NotFoundException $e) {
|
||||||
|
} catch (NotPermittedException $e) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -182,4 +222,25 @@ class ImageManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if Imagemagick is enabled and if SVG is supported
|
||||||
|
* otherwise we can't render custom icons
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function shouldReplaceIcons() {
|
||||||
|
$cache = $this->cacheFactory->createDistributed('theming-' . $this->urlGenerator->getBaseUrl());
|
||||||
|
if($value = $cache->get('shouldReplaceIcons')) {
|
||||||
|
return (bool)$value;
|
||||||
|
}
|
||||||
|
$value = false;
|
||||||
|
if(extension_loaded('imagick')) {
|
||||||
|
if (count(\Imagick::queryFormats('SVG')) >= 1) {
|
||||||
|
$value = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$cache->set('shouldReplaceIcons', $value);
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,7 +81,7 @@ class Admin implements ISettings {
|
||||||
'slogan' => $this->themingDefaults->getSlogan(),
|
'slogan' => $this->themingDefaults->getSlogan(),
|
||||||
'color' => $this->themingDefaults->getColorPrimary(),
|
'color' => $this->themingDefaults->getColorPrimary(),
|
||||||
'uploadLogoRoute' => $this->urlGenerator->linkToRoute('theming.Theming.uploadImage'),
|
'uploadLogoRoute' => $this->urlGenerator->linkToRoute('theming.Theming.uploadImage'),
|
||||||
'canThemeIcons' => $this->themingDefaults->shouldReplaceIcons(),
|
'canThemeIcons' => $this->imageManager->shouldReplaceIcons(),
|
||||||
'iconDocs' => $this->urlGenerator->linkToDocs('admin-theming-icons'),
|
'iconDocs' => $this->urlGenerator->linkToDocs('admin-theming-icons'),
|
||||||
'images' => $this->imageManager->getCustomImages(),
|
'images' => $this->imageManager->getCustomImages(),
|
||||||
'imprintUrl' => $this->themingDefaults->getImprintUrl(),
|
'imprintUrl' => $this->themingDefaults->getImprintUrl(),
|
||||||
|
|
|
@ -205,7 +205,7 @@ class ThemingDefaults extends \OC_Defaults {
|
||||||
|
|
||||||
$logoExists = true;
|
$logoExists = true;
|
||||||
try {
|
try {
|
||||||
$this->imageManager->getImage('logo');
|
$this->imageManager->getImage('logo', $useSvg);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
$logoExists = false;
|
$logoExists = false;
|
||||||
}
|
}
|
||||||
|
@ -221,7 +221,7 @@ class ThemingDefaults extends \OC_Defaults {
|
||||||
return $logo . '?v=' . $cacheBusterCounter;
|
return $logo . '?v=' . $cacheBusterCounter;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->urlGenerator->linkToRoute('theming.Theming.getImage', [ 'key' => 'logo' ]) . '?v=' . $cacheBusterCounter;
|
return $this->urlGenerator->linkToRoute('theming.Theming.getImage', [ 'key' => 'logo', 'useSvg' => $useSvg, 'v' => $cacheBusterCounter ]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -317,10 +317,10 @@ class ThemingDefaults extends \OC_Defaults {
|
||||||
$customFavicon = null;
|
$customFavicon = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($image === 'favicon.ico' && ($customFavicon !== null || $this->shouldReplaceIcons())) {
|
if ($image === 'favicon.ico' && ($customFavicon !== null || $this->imageManager->shouldReplaceIcons())) {
|
||||||
return $this->urlGenerator->linkToRoute('theming.Icon.getFavicon', ['app' => $app]) . '?v=' . $cacheBusterValue;
|
return $this->urlGenerator->linkToRoute('theming.Icon.getFavicon', ['app' => $app]) . '?v=' . $cacheBusterValue;
|
||||||
}
|
}
|
||||||
if ($image === 'favicon-touch.png' && ($customFavicon !== null || $this->shouldReplaceIcons())) {
|
if ($image === 'favicon-touch.png' && ($customFavicon !== null || $this->imageManager->shouldReplaceIcons())) {
|
||||||
return $this->urlGenerator->linkToRoute('theming.Icon.getTouchIcon', ['app' => $app]) . '?v=' . $cacheBusterValue;
|
return $this->urlGenerator->linkToRoute('theming.Icon.getTouchIcon', ['app' => $app]) . '?v=' . $cacheBusterValue;
|
||||||
}
|
}
|
||||||
if ($image === 'manifest.json') {
|
if ($image === 'manifest.json') {
|
||||||
|
@ -335,29 +335,6 @@ class ThemingDefaults extends \OC_Defaults {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if Imagemagick is enabled and if SVG is supported
|
|
||||||
* otherwise we can't render custom icons
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function shouldReplaceIcons() {
|
|
||||||
$cache = $this->cacheFactory->createDistributed('theming-' . $this->urlGenerator->getBaseUrl());
|
|
||||||
if($value = $cache->get('shouldReplaceIcons')) {
|
|
||||||
return (bool)$value;
|
|
||||||
}
|
|
||||||
$value = false;
|
|
||||||
if(extension_loaded('imagick')) {
|
|
||||||
$checkImagick = new \Imagick();
|
|
||||||
if (count($checkImagick->queryFormats('SVG')) >= 1) {
|
|
||||||
$value = true;
|
|
||||||
}
|
|
||||||
$checkImagick->clear();
|
|
||||||
}
|
|
||||||
$cache->set('shouldReplaceIcons', $value);
|
|
||||||
return $value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Increases the cache buster key
|
* Increases the cache buster key
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -120,7 +120,7 @@ class IconControllerTest extends TestCase {
|
||||||
->method('getImage')
|
->method('getImage')
|
||||||
->with('favicon')
|
->with('favicon')
|
||||||
->will($this->throwException(new NotFoundException()));
|
->will($this->throwException(new NotFoundException()));
|
||||||
$this->themingDefaults->expects($this->any())
|
$this->imageManager->expects($this->any())
|
||||||
->method('shouldReplaceIcons')
|
->method('shouldReplaceIcons')
|
||||||
->willReturn(true);
|
->willReturn(true);
|
||||||
$this->imageManager->expects($this->once())
|
$this->imageManager->expects($this->once())
|
||||||
|
@ -144,7 +144,7 @@ class IconControllerTest extends TestCase {
|
||||||
->method('getImage')
|
->method('getImage')
|
||||||
->with('favicon')
|
->with('favicon')
|
||||||
->will($this->throwException(new NotFoundException()));
|
->will($this->throwException(new NotFoundException()));
|
||||||
$this->themingDefaults->expects($this->any())
|
$this->imageManager->expects($this->any())
|
||||||
->method('shouldReplaceIcons')
|
->method('shouldReplaceIcons')
|
||||||
->willReturn(false);
|
->willReturn(false);
|
||||||
$fallbackLogo = \OC::$SERVERROOT . '/core/img/favicon.png';
|
$fallbackLogo = \OC::$SERVERROOT . '/core/img/favicon.png';
|
||||||
|
@ -165,10 +165,13 @@ class IconControllerTest extends TestCase {
|
||||||
if (count($checkImagick->queryFormats('SVG')) < 1) {
|
if (count($checkImagick->queryFormats('SVG')) < 1) {
|
||||||
$this->markTestSkipped('No SVG provider present.');
|
$this->markTestSkipped('No SVG provider present.');
|
||||||
}
|
}
|
||||||
$this->themingDefaults->expects($this->any())
|
|
||||||
|
$this->imageManager->expects($this->once())
|
||||||
|
->method('getImage')
|
||||||
|
->will($this->throwException(new NotFoundException()));
|
||||||
|
$this->imageManager->expects($this->any())
|
||||||
->method('shouldReplaceIcons')
|
->method('shouldReplaceIcons')
|
||||||
->willReturn(true);
|
->willReturn(true);
|
||||||
|
|
||||||
$this->iconBuilder->expects($this->once())
|
$this->iconBuilder->expects($this->once())
|
||||||
->method('getTouchIcon')
|
->method('getTouchIcon')
|
||||||
->with('core')
|
->with('core')
|
||||||
|
@ -191,7 +194,7 @@ class IconControllerTest extends TestCase {
|
||||||
->method('getImage')
|
->method('getImage')
|
||||||
->with('favicon')
|
->with('favicon')
|
||||||
->will($this->throwException(new NotFoundException()));
|
->will($this->throwException(new NotFoundException()));
|
||||||
$this->themingDefaults->expects($this->any())
|
$this->imageManager->expects($this->any())
|
||||||
->method('shouldReplaceIcons')
|
->method('shouldReplaceIcons')
|
||||||
->willReturn(false);
|
->willReturn(false);
|
||||||
$fallbackLogo = \OC::$SERVERROOT . '/core/img/favicon-touch.png';
|
$fallbackLogo = \OC::$SERVERROOT . '/core/img/favicon-touch.png';
|
||||||
|
|
|
@ -690,7 +690,7 @@ class ThemingControllerTest extends TestCase {
|
||||||
->method('getImage')
|
->method('getImage')
|
||||||
->willReturn($file);
|
->willReturn($file);
|
||||||
$this->config
|
$this->config
|
||||||
->expects($this->once())
|
->expects($this->any())
|
||||||
->method('getAppValue')
|
->method('getAppValue')
|
||||||
->with('theming', 'logoMime', '')
|
->with('theming', 'logoMime', '')
|
||||||
->willReturn('text/svg');
|
->willReturn('text/svg');
|
||||||
|
@ -718,7 +718,7 @@ class ThemingControllerTest extends TestCase {
|
||||||
->willReturn($file);
|
->willReturn($file);
|
||||||
|
|
||||||
$this->config
|
$this->config
|
||||||
->expects($this->once())
|
->expects($this->any())
|
||||||
->method('getAppValue')
|
->method('getAppValue')
|
||||||
->with('theming', 'backgroundMime', '')
|
->with('theming', 'backgroundMime', '')
|
||||||
->willReturn('image/png');
|
->willReturn('image/png');
|
||||||
|
|
|
@ -27,6 +27,7 @@ namespace OCA\Theming\Tests;
|
||||||
|
|
||||||
use OC\Files\AppData\AppData;
|
use OC\Files\AppData\AppData;
|
||||||
use OCA\Theming\IconBuilder;
|
use OCA\Theming\IconBuilder;
|
||||||
|
use OCA\Theming\ImageManager;
|
||||||
use OCA\Theming\ThemingDefaults;
|
use OCA\Theming\ThemingDefaults;
|
||||||
use OCA\Theming\Util;
|
use OCA\Theming\Util;
|
||||||
use OCP\App\IAppManager;
|
use OCP\App\IAppManager;
|
||||||
|
@ -45,6 +46,8 @@ class IconBuilderTest extends TestCase {
|
||||||
protected $themingDefaults;
|
protected $themingDefaults;
|
||||||
/** @var Util */
|
/** @var Util */
|
||||||
protected $util;
|
protected $util;
|
||||||
|
/** @var ImageManager */
|
||||||
|
protected $imageManager;
|
||||||
/** @var IconBuilder */
|
/** @var IconBuilder */
|
||||||
protected $iconBuilder;
|
protected $iconBuilder;
|
||||||
/** @var IAppManager */
|
/** @var IAppManager */
|
||||||
|
@ -53,13 +56,13 @@ class IconBuilderTest extends TestCase {
|
||||||
protected function setUp() {
|
protected function setUp() {
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
|
|
||||||
$this->config = $this->getMockBuilder(IConfig::class)->getMock();
|
$this->config = $this->createMock(IConfig::class);
|
||||||
$this->appData = $this->createMock(AppData::class);
|
$this->appData = $this->createMock(AppData::class);
|
||||||
$this->themingDefaults = $this->getMockBuilder('OCA\Theming\ThemingDefaults')
|
$this->themingDefaults = $this->createMock(ThemingDefaults::class);
|
||||||
->disableOriginalConstructor()->getMock();
|
$this->appManager = $this->createMock(IAppManager::class);
|
||||||
$this->appManager = $this->getMockBuilder('OCP\App\IAppManager')->getMock();
|
$this->imageManager = $this->createMock(ImageManager::class);
|
||||||
$this->util = new Util($this->config, $this->appManager, $this->appData);
|
$this->util = new Util($this->config, $this->appManager, $this->appData);
|
||||||
$this->iconBuilder = new IconBuilder($this->themingDefaults, $this->util);
|
$this->iconBuilder = new IconBuilder($this->themingDefaults, $this->util, $this->imageManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function checkImagick() {
|
private function checkImagick() {
|
||||||
|
@ -152,7 +155,7 @@ class IconBuilderTest extends TestCase {
|
||||||
*/
|
*/
|
||||||
public function testGetFavicon($app, $color, $file) {
|
public function testGetFavicon($app, $color, $file) {
|
||||||
$this->checkImagick();
|
$this->checkImagick();
|
||||||
$this->themingDefaults->expects($this->once())
|
$this->imageManager->expects($this->once())
|
||||||
->method('shouldReplaceIcons')
|
->method('shouldReplaceIcons')
|
||||||
->willReturn(true);
|
->willReturn(true);
|
||||||
$this->themingDefaults->expects($this->once())
|
$this->themingDefaults->expects($this->once())
|
||||||
|
@ -183,8 +186,8 @@ class IconBuilderTest extends TestCase {
|
||||||
$this->checkImagick();
|
$this->checkImagick();
|
||||||
$this->expectException(Warning::class);
|
$this->expectException(Warning::class);
|
||||||
$util = $this->getMockBuilder(Util::class)->disableOriginalConstructor()->getMock();
|
$util = $this->getMockBuilder(Util::class)->disableOriginalConstructor()->getMock();
|
||||||
$iconBuilder = new IconBuilder($this->themingDefaults, $util);
|
$iconBuilder = new IconBuilder($this->themingDefaults, $util, $this->imageManager);
|
||||||
$this->themingDefaults->expects($this->once())
|
$this->imageManager->expects($this->once())
|
||||||
->method('shouldReplaceIcons')
|
->method('shouldReplaceIcons')
|
||||||
->willReturn(true);
|
->willReturn(true);
|
||||||
$util->expects($this->once())
|
$util->expects($this->once())
|
||||||
|
@ -197,7 +200,7 @@ class IconBuilderTest extends TestCase {
|
||||||
$this->checkImagick();
|
$this->checkImagick();
|
||||||
$this->expectException(Warning::class);
|
$this->expectException(Warning::class);
|
||||||
$util = $this->getMockBuilder(Util::class)->disableOriginalConstructor()->getMock();
|
$util = $this->getMockBuilder(Util::class)->disableOriginalConstructor()->getMock();
|
||||||
$iconBuilder = new IconBuilder($this->themingDefaults, $util);
|
$iconBuilder = new IconBuilder($this->themingDefaults, $util, $this->imageManager);
|
||||||
$util->expects($this->once())
|
$util->expects($this->once())
|
||||||
->method('getAppIcon')
|
->method('getAppIcon')
|
||||||
->willReturn('notexistingfile');
|
->willReturn('notexistingfile');
|
||||||
|
@ -208,7 +211,7 @@ class IconBuilderTest extends TestCase {
|
||||||
$this->checkImagick();
|
$this->checkImagick();
|
||||||
$this->expectException(Warning::class);
|
$this->expectException(Warning::class);
|
||||||
$util = $this->getMockBuilder(Util::class)->disableOriginalConstructor()->getMock();
|
$util = $this->getMockBuilder(Util::class)->disableOriginalConstructor()->getMock();
|
||||||
$iconBuilder = new IconBuilder($this->themingDefaults, $util);
|
$iconBuilder = new IconBuilder($this->themingDefaults, $util, $this->imageManager);
|
||||||
$util->expects($this->once())
|
$util->expects($this->once())
|
||||||
->method('getAppImage')
|
->method('getAppImage')
|
||||||
->willReturn('notexistingfile');
|
->willReturn('notexistingfile');
|
||||||
|
|
|
@ -24,8 +24,11 @@
|
||||||
namespace OCA\Theming\Tests;
|
namespace OCA\Theming\Tests;
|
||||||
|
|
||||||
use OCA\Theming\ImageManager;
|
use OCA\Theming\ImageManager;
|
||||||
|
use OCA\Theming\ThemingDefaults;
|
||||||
use OCP\Files\SimpleFS\ISimpleFile;
|
use OCP\Files\SimpleFS\ISimpleFile;
|
||||||
|
use OCP\ICacheFactory;
|
||||||
use OCP\IConfig;
|
use OCP\IConfig;
|
||||||
|
use OCP\ILogger;
|
||||||
use OCP\IURLGenerator;
|
use OCP\IURLGenerator;
|
||||||
use Test\TestCase;
|
use Test\TestCase;
|
||||||
use OCP\Files\SimpleFS\ISimpleFolder;
|
use OCP\Files\SimpleFS\ISimpleFolder;
|
||||||
|
@ -42,19 +45,40 @@ class ImageManagerTest extends TestCase {
|
||||||
protected $imageManager;
|
protected $imageManager;
|
||||||
/** @var IURLGenerator|\PHPUnit_Framework_MockObject_MockObject */
|
/** @var IURLGenerator|\PHPUnit_Framework_MockObject_MockObject */
|
||||||
private $urlGenerator;
|
private $urlGenerator;
|
||||||
|
/** @var ICacheFactory|\PHPUnit_Framework_MockObject_MockObject */
|
||||||
|
private $cacheFactory;
|
||||||
|
/** @var ILogger|\PHPUnit_Framework_MockObject_MockObject */
|
||||||
|
private $logger;
|
||||||
|
|
||||||
protected function setUp() {
|
protected function setUp() {
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
$this->config = $this->createMock(IConfig::class);
|
$this->config = $this->createMock(IConfig::class);
|
||||||
$this->appData = $this->createMock(IAppData::class);
|
$this->appData = $this->createMock(IAppData::class);
|
||||||
$this->urlGenerator = $this->createMock(IURLGenerator::class);
|
$this->urlGenerator = $this->createMock(IURLGenerator::class);
|
||||||
|
$this->cacheFactory = $this->createMock(ICacheFactory::class);
|
||||||
|
$this->logger = $this->createMock(ILogger::class);
|
||||||
$this->imageManager = new ImageManager(
|
$this->imageManager = new ImageManager(
|
||||||
$this->config,
|
$this->config,
|
||||||
$this->appData,
|
$this->appData,
|
||||||
$this->urlGenerator
|
$this->urlGenerator,
|
||||||
|
$this->cacheFactory,
|
||||||
|
$this->logger
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function checkImagick() {
|
||||||
|
if(!extension_loaded('imagick')) {
|
||||||
|
$this->markTestSkipped('Imagemagick is required for dynamic icon generation.');
|
||||||
|
}
|
||||||
|
$checkImagick = new \Imagick();
|
||||||
|
if (empty($checkImagick->queryFormats('SVG'))) {
|
||||||
|
$this->markTestSkipped('No SVG provider present.');
|
||||||
|
}
|
||||||
|
if (empty($checkImagick->queryFormats('PNG'))) {
|
||||||
|
$this->markTestSkipped('No PNG provider present.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function mockGetImage($key, $file) {
|
public function mockGetImage($key, $file) {
|
||||||
/** @var \PHPUnit_Framework_MockObject_MockObject $folder */
|
/** @var \PHPUnit_Framework_MockObject_MockObject $folder */
|
||||||
$folder = $this->createMock(ISimpleFolder::class);
|
$folder = $this->createMock(ISimpleFolder::class);
|
||||||
|
@ -64,10 +88,28 @@ class ImageManagerTest extends TestCase {
|
||||||
->with('logo')
|
->with('logo')
|
||||||
->willThrowException(new NotFoundException());
|
->willThrowException(new NotFoundException());
|
||||||
} else {
|
} else {
|
||||||
$folder->expects($this->once())
|
$file->expects($this->once())
|
||||||
|
->method('getContent')
|
||||||
|
->willReturn(file_get_contents(__DIR__ . '/../../../tests/data/testimage.png'));
|
||||||
|
$folder->expects($this->at(0))
|
||||||
|
->method('fileExists')
|
||||||
|
->with('logo')
|
||||||
|
->willReturn(true);
|
||||||
|
$folder->expects($this->at(1))
|
||||||
|
->method('fileExists')
|
||||||
|
->with('logo.png')
|
||||||
|
->willReturn(false);
|
||||||
|
$folder->expects($this->at(2))
|
||||||
->method('getFile')
|
->method('getFile')
|
||||||
->with('logo')
|
->with('logo')
|
||||||
->willReturn($file);
|
->willReturn($file);
|
||||||
|
$newFile = $this->createMock(ISimpleFile::class);
|
||||||
|
$folder->expects($this->at(3))
|
||||||
|
->method('newFile')
|
||||||
|
->with('logo.png')
|
||||||
|
->willReturn($newFile);
|
||||||
|
$newFile->expects($this->once())
|
||||||
|
->method('putContent');
|
||||||
$this->appData->expects($this->once())
|
$this->appData->expects($this->once())
|
||||||
->method('getFolder')
|
->method('getFolder')
|
||||||
->with('images')
|
->with('images')
|
||||||
|
@ -76,19 +118,20 @@ class ImageManagerTest extends TestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetImageUrl() {
|
public function testGetImageUrl() {
|
||||||
|
$this->checkImagick();
|
||||||
$file = $this->createMock(ISimpleFile::class);
|
$file = $this->createMock(ISimpleFile::class);
|
||||||
$this->config->expects($this->exactly(2))
|
$this->config->expects($this->exactly(2))
|
||||||
->method('getAppValue')
|
->method('getAppValue')
|
||||||
->withConsecutive(
|
->withConsecutive(
|
||||||
['theming', 'cachebuster', '0'],
|
['theming', 'cachebuster', '0'],
|
||||||
['theming', 'logoMime', false]
|
['theming', 'logoMime', '']
|
||||||
)
|
)
|
||||||
->willReturn(0);
|
->willReturn(0);
|
||||||
$this->mockGetImage('logo', $file);
|
$this->mockGetImage('logo', $file);
|
||||||
$this->urlGenerator->expects($this->once())
|
$this->urlGenerator->expects($this->once())
|
||||||
->method('linkToRoute')
|
->method('linkToRoute')
|
||||||
->willReturn('url-to-image');
|
->willReturn('url-to-image');
|
||||||
$this->assertEquals('url-to-image?v=0', $this->imageManager->getImageUrl('logo'));
|
$this->assertEquals('url-to-image?v=0', $this->imageManager->getImageUrl('logo', false));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetImageUrlDefault() {
|
public function testGetImageUrlDefault() {
|
||||||
|
@ -107,33 +150,37 @@ class ImageManagerTest extends TestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetImageUrlAbsolute() {
|
public function testGetImageUrlAbsolute() {
|
||||||
|
$this->checkImagick();
|
||||||
$file = $this->createMock(ISimpleFile::class);
|
$file = $this->createMock(ISimpleFile::class);
|
||||||
$this->config->expects($this->exactly(2))
|
$this->config->expects($this->exactly(2))
|
||||||
->method('getAppValue')
|
->method('getAppValue')
|
||||||
->withConsecutive(
|
->withConsecutive(
|
||||||
['theming', 'cachebuster', '0'],
|
['theming', 'cachebuster', '0'],
|
||||||
['theming', 'logoMime', false]
|
['theming', 'logoMime', '']
|
||||||
)
|
)
|
||||||
->willReturn(0);
|
->willReturn(0);
|
||||||
$this->mockGetImage('logo', $file);
|
$this->mockGetImage('logo', $file);
|
||||||
$this->urlGenerator->expects($this->at(0))
|
$this->urlGenerator->expects($this->at(0))
|
||||||
->method('linkToRoute')
|
->method('getBaseUrl')
|
||||||
->willReturn('url-to-image');
|
->willReturn('baseurl');
|
||||||
$this->urlGenerator->expects($this->at(1))
|
$this->urlGenerator->expects($this->at(1))
|
||||||
->method('getAbsoluteUrl')
|
->method('getAbsoluteUrl')
|
||||||
->with('url-to-image?v=0')
|
|
||||||
->willReturn('url-to-image-absolute?v=0');
|
->willReturn('url-to-image-absolute?v=0');
|
||||||
$this->assertEquals('url-to-image-absolute?v=0', $this->imageManager->getImageUrlAbsolute('logo'));
|
$this->urlGenerator->expects($this->at(2))
|
||||||
|
->method('getAbsoluteUrl')
|
||||||
|
->willReturn('url-to-image-absolute?v=0');
|
||||||
|
$this->assertEquals('url-to-image-absolute?v=0', $this->imageManager->getImageUrlAbsolute('logo', false));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetImage() {
|
public function testGetImage() {
|
||||||
|
$this->checkImagick();
|
||||||
$this->config->expects($this->once())
|
$this->config->expects($this->once())
|
||||||
->method('getAppValue')->with('theming', 'logoMime', false)
|
->method('getAppValue')->with('theming', 'logoMime', false)
|
||||||
->willReturn('png');
|
->willReturn('png');
|
||||||
$file = $this->createMock(ISimpleFile::class);
|
$file = $this->createMock(ISimpleFile::class);
|
||||||
$this->mockGetImage('logo', $file);
|
$this->mockGetImage('logo', $file);
|
||||||
$this->assertEquals($file, $this->imageManager->getImage('logo'));
|
$this->assertEquals($file, $this->imageManager->getImage('logo', false));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -604,7 +604,7 @@ class ThemingDefaultsTest extends TestCase {
|
||||||
$this->urlGenerator->expects($this->once())
|
$this->urlGenerator->expects($this->once())
|
||||||
->method('linkToRoute')
|
->method('linkToRoute')
|
||||||
->with('theming.Theming.getImage')
|
->with('theming.Theming.getImage')
|
||||||
->willReturn('custom-logo');
|
->willReturn('custom-logo?v=0');
|
||||||
$this->assertEquals('custom-logo' . '?v=0', $this->template->getLogo());
|
$this->assertEquals('custom-logo' . '?v=0', $this->template->getLogo());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -954,7 +954,7 @@ class Server extends ServerContainer implements IServerContainer {
|
||||||
$c->getURLGenerator(),
|
$c->getURLGenerator(),
|
||||||
$c->getMemCacheFactory(),
|
$c->getMemCacheFactory(),
|
||||||
new Util($c->getConfig(), $this->getAppManager(), $c->getAppDataDir('theming')),
|
new Util($c->getConfig(), $this->getAppManager(), $c->getAppDataDir('theming')),
|
||||||
new ImageManager($c->getConfig(), $c->getAppDataDir('theming'), $c->getURLGenerator()),
|
new ImageManager($c->getConfig(), $c->getAppDataDir('theming'), $c->getURLGenerator(), $this->getMemCacheFactory(), $this->getLogger()),
|
||||||
$c->getAppManager()
|
$c->getAppManager()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue