Browse Source
Remove old legacy SvgController and IconsCacher
Remove old legacy SvgController and IconsCacher
Signed-off-by: John Molakvoæ <skjnldsv@protonmail.com>pull/32326/head
No known key found for this signature in database
GPG Key ID: 60C25B8C072916CF
8 changed files with 1 additions and 835 deletions
-
151core/Controller/SvgController.php
-
2core/routes.php
-
263lib/private/Template/IconsCacher.php
-
32lib/private/Template/SCSSCacher.php
-
198tests/Core/Controller/SvgControllerTest.php
-
5tests/lib/Template/CSSResourceLocatorTest.php
-
149tests/lib/Template/IconsCacherTest.php
-
36tests/lib/Template/SCSSCacherTest.php
@ -1,151 +0,0 @@ |
|||
<?php |
|||
|
|||
declare(strict_types=1); |
|||
|
|||
/** |
|||
* @copyright Copyright (c) 2018, John Molakvoæ (skjnldsv@protonmail.com) |
|||
* |
|||
* @author Christoph Wurst <christoph@winzerhof-wurst.at> |
|||
* @author Daniel Kesselberg <mail@danielkesselberg.de> |
|||
* @author Joas Schilling <coding@schilljs.com> |
|||
* @author John Molakvoæ <skjnldsv@protonmail.com> |
|||
* @author Julius Härtl <jus@bitgrid.net> |
|||
* @author Roeland Jago Douma <roeland@famdouma.nl> |
|||
* @author Thomas Citharel <nextcloud@tcit.fr> |
|||
* |
|||
* @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 OC\Files\Filesystem; |
|||
use OC\Template\IconsCacher; |
|||
use OCP\App\AppPathNotFoundException; |
|||
use OCP\App\IAppManager; |
|||
use OCP\AppFramework\Controller; |
|||
use OCP\AppFramework\Http; |
|||
use OCP\AppFramework\Http\DataDisplayResponse; |
|||
use OCP\AppFramework\Http\NotFoundResponse; |
|||
use OCP\AppFramework\Utility\ITimeFactory; |
|||
use OCP\IRequest; |
|||
|
|||
class SvgController extends Controller { |
|||
|
|||
/** @var string */ |
|||
protected $serverRoot; |
|||
|
|||
/** @var ITimeFactory */ |
|||
protected $timeFactory; |
|||
|
|||
/** @var IAppManager */ |
|||
protected $appManager; |
|||
|
|||
/** @var IconsCacher */ |
|||
private $iconsCacher; |
|||
|
|||
public function __construct(string $appName, |
|||
IRequest $request, |
|||
ITimeFactory $timeFactory, |
|||
IAppManager $appManager, |
|||
IconsCacher $iconsCacher) { |
|||
parent::__construct($appName, $request); |
|||
|
|||
$this->serverRoot = \OC::$SERVERROOT; |
|||
$this->timeFactory = $timeFactory; |
|||
$this->appManager = $appManager; |
|||
$this->iconsCacher = $iconsCacher; |
|||
} |
|||
|
|||
/** |
|||
* @PublicPage |
|||
* @NoCSRFRequired |
|||
* @NoSameSiteCookieRequired |
|||
* |
|||
* Generate svg from filename with the requested color |
|||
* |
|||
* @param string $folder |
|||
* @param string $fileName |
|||
* @param string $color |
|||
* @return DataDisplayResponse|NotFoundResponse |
|||
*/ |
|||
public function getSvgFromCore(string $folder, string $fileName, string $color = 'ffffff') { |
|||
$path = $this->serverRoot . "/core/img/$folder/$fileName.svg"; |
|||
return $this->getSvg($path, $color, $fileName); |
|||
} |
|||
|
|||
/** |
|||
* @PublicPage |
|||
* @NoCSRFRequired |
|||
* @NoSameSiteCookieRequired |
|||
* |
|||
* Generate svg from filename with the requested color |
|||
* |
|||
* @param string $app |
|||
* @param string $fileName |
|||
* @param string $color |
|||
* @return DataDisplayResponse|NotFoundResponse |
|||
*/ |
|||
public function getSvgFromApp(string $app, string $fileName, string $color = 'ffffff') { |
|||
try { |
|||
$appPath = $this->appManager->getAppPath($app); |
|||
} catch (AppPathNotFoundException $e) { |
|||
return new NotFoundResponse(); |
|||
} |
|||
|
|||
$path = $appPath . "/img/$fileName.svg"; |
|||
return $this->getSvg($path, $color, $fileName); |
|||
} |
|||
|
|||
/** |
|||
* Generate svg from filename with the requested color |
|||
* |
|||
* @param string $path |
|||
* @param string $color |
|||
* @param string $fileName |
|||
* @return DataDisplayResponse|NotFoundResponse |
|||
*/ |
|||
private function getSvg(string $path, string $color, string $fileName) { |
|||
if (!Filesystem::isValidPath($path)) { |
|||
return new NotFoundResponse(); |
|||
} |
|||
|
|||
if (!file_exists($path)) { |
|||
return new NotFoundResponse(); |
|||
} |
|||
|
|||
$svg = file_get_contents($path); |
|||
|
|||
if ($svg === null) { |
|||
return new NotFoundResponse(); |
|||
} |
|||
|
|||
$svg = $this->iconsCacher->colorizeSvg($svg, $color); |
|||
|
|||
$response = new DataDisplayResponse($svg, Http::STATUS_OK, ['Content-Type' => 'image/svg+xml']); |
|||
|
|||
// Set cache control
|
|||
$ttl = 31536000; |
|||
$response->cacheFor($ttl); |
|||
$response->addHeader('Content-Disposition', 'inline; filename="' . $fileName . '.svg"'); |
|||
$expires = new \DateTime(); |
|||
$expires->setTimestamp($this->timeFactory->getTime()); |
|||
$expires->add(new \DateInterval('PT' . $ttl . 'S')); |
|||
$response->addHeader('Expires', $expires->format(\DateTime::RFC1123)); |
|||
$response->addHeader('Pragma', 'cache'); |
|||
|
|||
return $response; |
|||
} |
|||
} |
|||
@ -1,263 +0,0 @@ |
|||
<?php |
|||
|
|||
declare(strict_types=1); |
|||
|
|||
/** |
|||
* @copyright Copyright (c) 2018, John Molakvoæ (skjnldsv@protonmail.com) |
|||
* |
|||
* @author Christoph Wurst <christoph@winzerhof-wurst.at> |
|||
* @author Joas Schilling <coding@schilljs.com> |
|||
* @author John Molakvoæ <skjnldsv@protonmail.com> |
|||
* @author Julius Härtl <jus@bitgrid.net> |
|||
* @author Robin Appelman <robin@icewind.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\Template; |
|||
|
|||
use OC\Files\AppData\Factory; |
|||
use OCP\AppFramework\Utility\ITimeFactory; |
|||
use OCP\Files\IAppData; |
|||
use OCP\Files\NotFoundException; |
|||
use OCP\Files\SimpleFS\ISimpleFile; |
|||
use OCP\Files\SimpleFS\ISimpleFolder; |
|||
use OCP\IURLGenerator; |
|||
use Psr\Log\LoggerInterface; |
|||
|
|||
class IconsCacher { |
|||
protected LoggerInterface $logger; |
|||
|
|||
/** @var IAppData */ |
|||
protected $appData; |
|||
|
|||
/** @var ISimpleFolder */ |
|||
private $folder; |
|||
|
|||
/** @var IURLGenerator */ |
|||
protected $urlGenerator; |
|||
|
|||
/** @var ITimeFactory */ |
|||
protected $timeFactory; |
|||
|
|||
/** @var string */ |
|||
private $iconVarRE = '/--(icon-[a-zA-Z0-9-]+):\s?url\(["\']?([a-zA-Z0-9-_\~\/\.\?\&\=\:\;\+\,]+)[^;]+;/m'; |
|||
|
|||
/** @var string */ |
|||
private $fileName = 'icons-vars.css'; |
|||
|
|||
private $iconList = 'icons-list.template'; |
|||
|
|||
private $cachedCss; |
|||
private $cachedList; |
|||
|
|||
/** |
|||
* @throws \OCP\Files\NotPermittedException |
|||
*/ |
|||
public function __construct(LoggerInterface $logger, |
|||
Factory $appDataFactory, |
|||
IURLGenerator $urlGenerator, |
|||
ITimeFactory $timeFactory) { |
|||
$this->logger = $logger; |
|||
$this->appData = $appDataFactory->get('css'); |
|||
$this->urlGenerator = $urlGenerator; |
|||
$this->timeFactory = $timeFactory; |
|||
|
|||
try { |
|||
$this->folder = $this->appData->getFolder('icons'); |
|||
} catch (NotFoundException $e) { |
|||
$this->folder = $this->appData->newFolder('icons'); |
|||
} |
|||
} |
|||
|
|||
private function getIconsFromCss(string $css): array { |
|||
preg_match_all($this->iconVarRE, $css, $matches, PREG_SET_ORDER); |
|||
$icons = []; |
|||
foreach ($matches as $icon) { |
|||
$icons[$icon[1]] = $icon[2]; |
|||
} |
|||
|
|||
return $icons; |
|||
} |
|||
|
|||
/** |
|||
* @param string $css |
|||
* @return string |
|||
* @throws NotFoundException |
|||
* @throws \OCP\Files\NotPermittedException |
|||
*/ |
|||
public function setIconsCss(string $css): string { |
|||
$cachedFile = $this->getCachedList(); |
|||
if (!$cachedFile) { |
|||
$currentData = ''; |
|||
$cachedFile = $this->folder->newFile($this->iconList); |
|||
} else { |
|||
$currentData = $cachedFile->getContent(); |
|||
} |
|||
|
|||
$cachedVarsCssFile = $this->getCachedCSS(); |
|||
if (!$cachedVarsCssFile) { |
|||
$cachedVarsCssFile = $this->folder->newFile($this->fileName); |
|||
} |
|||
|
|||
$icons = $this->getIconsFromCss($currentData . $css); |
|||
|
|||
$data = ''; |
|||
$list = ''; |
|||
foreach ($icons as $icon => $url) { |
|||
$list .= "--$icon: url('$url');"; |
|||
[$location,$color] = $this->parseUrl($url); |
|||
$svg = false; |
|||
if ($location !== '' && \file_exists($location)) { |
|||
$svg = \file_get_contents($location); |
|||
} |
|||
if ($svg === false) { |
|||
$this->logger->debug('Failed to get icon file ' . $location); |
|||
$data .= "--$icon: url('$url');"; |
|||
continue; |
|||
} |
|||
$encode = base64_encode($this->colorizeSvg($svg, $color)); |
|||
$data .= '--' . $icon . ': url(data:image/svg+xml;base64,' . $encode . ');'; |
|||
} |
|||
|
|||
if (\strlen($data) > 0 && \strlen($list) > 0) { |
|||
$data = ":root {\n$data\n}"; |
|||
$cachedVarsCssFile->putContent($data); |
|||
$list = ":root {\n$list\n}"; |
|||
$cachedFile->putContent($list); |
|||
$this->cachedList = null; |
|||
$this->cachedCss = null; |
|||
} |
|||
|
|||
return preg_replace($this->iconVarRE, '', $css); |
|||
} |
|||
|
|||
/** |
|||
* @param $url |
|||
* @return array |
|||
*/ |
|||
private function parseUrl($url): array { |
|||
$location = ''; |
|||
$color = ''; |
|||
$base = $this->getRoutePrefix() . '/svg/'; |
|||
$cleanUrl = \substr($url, \strlen($base)); |
|||
if (\strpos($url, $base . 'core') === 0) { |
|||
$cleanUrl = \substr($cleanUrl, \strlen('core')); |
|||
if (\preg_match('/\/([a-zA-Z0-9-_\~\/\.\=\:\;\+\,]+)\?color=([0-9a-fA-F]{3,6})/', $cleanUrl, $matches)) { |
|||
[,$cleanUrl,$color] = $matches; |
|||
$location = \OC::$SERVERROOT . '/core/img/' . $cleanUrl . '.svg'; |
|||
} |
|||
} elseif (\strpos($url, $base) === 0) { |
|||
if (\preg_match('/([A-z0-9\_\-]+)\/([a-zA-Z0-9-_\~\/\.\=\:\;\+\,]+)\?color=([0-9a-fA-F]{3,6})/', $cleanUrl, $matches)) { |
|||
[,$app,$cleanUrl, $color] = $matches; |
|||
$appPath = \OC_App::getAppPath($app); |
|||
if ($appPath !== false) { |
|||
$location = $appPath . '/img/' . $cleanUrl . '.svg'; |
|||
} |
|||
if ($app === 'settings') { |
|||
$location = \OC::$SERVERROOT . '/settings/img/' . $cleanUrl . '.svg'; |
|||
} |
|||
} |
|||
} |
|||
return [ |
|||
$location, |
|||
$color |
|||
]; |
|||
} |
|||
|
|||
/** |
|||
* @param $svg |
|||
* @param $color |
|||
* @return string |
|||
*/ |
|||
public function colorizeSvg($svg, $color): string { |
|||
if (!preg_match('/^[0-9a-f]{3,6}$/i', $color)) { |
|||
// Prevent not-sane colors from being written into the SVG
|
|||
$color = '000'; |
|||
} |
|||
|
|||
// add fill (fill is not present on black elements)
|
|||
$fillRe = '/<((circle|rect|path)((?!fill)[a-z0-9 =".\-#():;,])+)\/>/mi'; |
|||
$svg = preg_replace($fillRe, '<$1 fill="#' . $color . '"/>', $svg); |
|||
|
|||
// replace any fill or stroke colors
|
|||
$svg = preg_replace('/stroke="#([a-z0-9]{3,6})"/mi', 'stroke="#' . $color . '"', $svg); |
|||
$svg = preg_replace('/fill="#([a-z0-9]{3,6})"/mi', 'fill="#' . $color . '"', $svg); |
|||
return $svg; |
|||
} |
|||
|
|||
private function getRoutePrefix() { |
|||
$frontControllerActive = (\OC::$server->getConfig()->getSystemValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true'); |
|||
$prefix = \OC::$WEBROOT . '/index.php'; |
|||
if ($frontControllerActive) { |
|||
$prefix = \OC::$WEBROOT; |
|||
} |
|||
return $prefix; |
|||
} |
|||
|
|||
/** |
|||
* Get icons css file |
|||
* @return ISimpleFile|boolean |
|||
*/ |
|||
public function getCachedCSS() { |
|||
try { |
|||
if (!$this->cachedCss) { |
|||
$this->cachedCss = $this->folder->getFile($this->fileName); |
|||
} |
|||
return $this->cachedCss; |
|||
} catch (NotFoundException $e) { |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Get icon-vars list template |
|||
* @return ISimpleFile|boolean |
|||
*/ |
|||
public function getCachedList() { |
|||
try { |
|||
if (!$this->cachedList) { |
|||
$this->cachedList = $this->folder->getFile($this->iconList); |
|||
} |
|||
return $this->cachedList; |
|||
} catch (NotFoundException $e) { |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Add the icons cache css into the header |
|||
*/ |
|||
public function injectCss() { |
|||
$mtime = $this->timeFactory->getTime(); |
|||
$file = $this->getCachedList(); |
|||
if ($file) { |
|||
$mtime = $file->getMTime(); |
|||
} |
|||
// Only inject once
|
|||
foreach (\OC_Util::$headers as $header) { |
|||
if ( |
|||
array_key_exists('attributes', $header) && |
|||
array_key_exists('href', $header['attributes']) && |
|||
strpos($header['attributes']['href'], $this->fileName) !== false) { |
|||
return; |
|||
} |
|||
} |
|||
$linkToCSS = $this->urlGenerator->linkToRoute('core.Css.getCss', ['appName' => 'icons', 'fileName' => $this->fileName, 'v' => $mtime]); |
|||
\OC_Util::addHeader('link', ['rel' => 'stylesheet', 'href' => $linkToCSS], null, true); |
|||
} |
|||
} |
|||
@ -1,198 +0,0 @@ |
|||
<?php |
|||
|
|||
declare(strict_types = 1); |
|||
/** |
|||
* @copyright Copyright (c) 2018 Michael Weimann <mail@michael-weimann.eu> |
|||
* |
|||
* @author Michael Weimann <mail@michael-weimann.eu> |
|||
* |
|||
* @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\AppFramework\Http; |
|||
use OC\Core\Controller\SvgController; |
|||
use OC\Template\IconsCacher; |
|||
use OCP\App\AppPathNotFoundException; |
|||
use OCP\App\IAppManager; |
|||
use OCP\AppFramework\Utility\ITimeFactory; |
|||
use OCP\IRequest; |
|||
use Test\TestCase; |
|||
|
|||
/** |
|||
* This class provides test cases for the svg controller |
|||
*/ |
|||
class SvgControllerTest extends TestCase { |
|||
public const TEST_IMAGES_SOURCE_PATH = __DIR__ . '/../../data/svg'; |
|||
public const TEST_IMAGES_PATH = __DIR__ . '/../../../core/img/testImages'; |
|||
public const TEST_IMAGE_MIXED = 'mixed-source.svg'; |
|||
public const TEST_IMAGE_RECT = 'rect-black.svg'; |
|||
public const TEST_IMAGES = [ |
|||
self::TEST_IMAGE_MIXED, |
|||
self::TEST_IMAGE_RECT, |
|||
]; |
|||
|
|||
/** @var IAppManager|\PHPUnit\Framework\MockObject\MockObject */ |
|||
private $appManager; |
|||
|
|||
/** |
|||
* @var SvgController |
|||
*/ |
|||
private $svgController; |
|||
|
|||
/** |
|||
* Copy test svgs into the core img "test" directory. |
|||
* |
|||
* @beforeClass |
|||
* @return void |
|||
*/ |
|||
public static function copyTestImagesIntoPlace() { |
|||
mkdir(self::TEST_IMAGES_PATH); |
|||
foreach (self::TEST_IMAGES as $testImage) { |
|||
copy( |
|||
self::TEST_IMAGES_SOURCE_PATH .'/' . $testImage, |
|||
self::TEST_IMAGES_PATH . '/' . $testImage |
|||
); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Removes the test svgs from the core img "test" directory. |
|||
* |
|||
* @afterClass |
|||
* @return void |
|||
*/ |
|||
public static function removeTestImages() { |
|||
foreach (self::TEST_IMAGES as $testImage) { |
|||
unlink(self::TEST_IMAGES_PATH . '/' . $testImage); |
|||
} |
|||
rmdir(self::TEST_IMAGES_PATH); |
|||
} |
|||
|
|||
/** |
|||
* Setups a SVG controller instance for tests. |
|||
* |
|||
* @before |
|||
* @return void |
|||
*/ |
|||
public function setupSvgController() { |
|||
/** @var IRequest */ |
|||
$request = $this->getMockBuilder(IRequest::class)->getMock(); |
|||
/** @var ITimeFactory $timeFactory */ |
|||
$timeFactory = $this->getMockBuilder(ITimeFactory::class)->getMock(); |
|||
/** @var IAppManager */ |
|||
$this->appManager = $this->getMockBuilder(IAppManager::class)->getMock(); |
|||
/** @var IconsCacher $iconsCacher */ |
|||
$iconsCacher = $this->getMockBuilder(IconsCacher::class)->disableOriginalConstructor()->setMethods(['__construct'])->getMock(); |
|||
$this->svgController = new SvgController('core', $request, $timeFactory, $this->appManager, $iconsCacher); |
|||
} |
|||
|
|||
/** |
|||
* Checks that requesting an unknown image results in a 404. |
|||
* |
|||
* @return void |
|||
*/ |
|||
public function testGetSvgFromCoreNotFound() { |
|||
$response = $this->svgController->getSvgFromCore('huhuu', '2342', '#ff0000'); |
|||
self::assertEquals(Http::STATUS_NOT_FOUND, $response->getStatus()); |
|||
} |
|||
|
|||
/** |
|||
* Provides svg coloring test data. |
|||
* |
|||
* @return array |
|||
*/ |
|||
public function provideGetSvgFromCoreTestData(): array { |
|||
return [ |
|||
'mixed' => ['mixed-source', 'f00', file_get_contents(self::TEST_IMAGES_SOURCE_PATH . '/mixed-red.svg')], |
|||
'black rect' => ['rect-black', 'f00', file_get_contents(self::TEST_IMAGES_SOURCE_PATH . '/rect-red.svg')], |
|||
]; |
|||
} |
|||
|
|||
/** |
|||
* Tests that retrieving a colored SVG works. |
|||
* |
|||
* @dataProvider provideGetSvgFromCoreTestData |
|||
* @param string $name The requested svg name |
|||
* @param string $color The requested color |
|||
* @param string $expected The expected svg |
|||
* @return void |
|||
*/ |
|||
public function testGetSvgFromCore(string $name, string $color, string $expected) { |
|||
$response = $this->svgController->getSvgFromCore('testImages', $name, $color); |
|||
|
|||
self::assertEquals(Http::STATUS_OK, $response->getStatus()); |
|||
|
|||
$headers = $response->getHeaders(); |
|||
self::assertArrayHasKey('Content-Type', $headers); |
|||
self::assertEquals($headers['Content-Type'], 'image/svg+xml'); |
|||
|
|||
self::assertEquals($expected, $response->getData()); |
|||
} |
|||
|
|||
/** |
|||
* Checks that requesting an unknown image results in a 404. |
|||
*/ |
|||
public function testGetSvgFromAppNotFound(): void { |
|||
$this->appManager->expects($this->once()) |
|||
->method('getAppPath') |
|||
->with('invalid_app') |
|||
->willThrowException(new AppPathNotFoundException('Could not find path for invalid_app')); |
|||
|
|||
$response = $this->svgController->getSvgFromApp('invalid_app', 'some-icon', '#ff0000'); |
|||
self::assertEquals(Http::STATUS_NOT_FOUND, $response->getStatus()); |
|||
} |
|||
|
|||
/** |
|||
* Provides svg coloring test data. |
|||
* |
|||
* @return array |
|||
*/ |
|||
public function provideGetSvgFromAppTestData(): array { |
|||
return [ |
|||
'settings admin' => ['settings', 'admin', 'f00', file_get_contents(self::TEST_IMAGES_SOURCE_PATH . '/settings-admin-red.svg')], |
|||
'files app' => ['files', 'app', 'f00', file_get_contents(self::TEST_IMAGES_SOURCE_PATH . '/files-app-red.svg')], |
|||
]; |
|||
} |
|||
|
|||
/** |
|||
* Tests that retrieving a colored SVG works. |
|||
* |
|||
* @dataProvider provideGetSvgFromAppTestData |
|||
* @param string $appName |
|||
* @param string $name The requested svg name |
|||
* @param string $color The requested color |
|||
* @param string $expected |
|||
*/ |
|||
public function testGetSvgFromApp(string $appName, string $name, string $color, string $expected): void { |
|||
$this->appManager->expects($this->once()) |
|||
->method('getAppPath') |
|||
->with($appName) |
|||
->willReturn(realpath(__DIR__ . '/../../../apps/') . '/' . $appName); |
|||
|
|||
$response = $this->svgController->getSvgFromApp($appName, $name, $color); |
|||
|
|||
self::assertEquals(Http::STATUS_OK, $response->getStatus()); |
|||
|
|||
$headers = $response->getHeaders(); |
|||
self::assertArrayHasKey('Content-Type', $headers); |
|||
self::assertEquals($headers['Content-Type'], 'image/svg+xml'); |
|||
|
|||
self::assertEquals($expected, $response->getData()); |
|||
} |
|||
} |
|||
@ -1,149 +0,0 @@ |
|||
<?php |
|||
|
|||
declare(strict_types = 1); |
|||
/** |
|||
* @copyright Copyright (c) 2018, John Molakvoæ (skjnldsv@protonmail.com) |
|||
* |
|||
* @author John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com> |
|||
* |
|||
* @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\Template; |
|||
|
|||
use OC\Files\AppData\AppData; |
|||
use OC\Files\AppData\Factory; |
|||
use OC\Template\IconsCacher; |
|||
use OCP\AppFramework\Utility\ITimeFactory; |
|||
use OCP\Files\IAppData; |
|||
use OCP\Files\SimpleFS\ISimpleFile; |
|||
use OCP\Files\SimpleFS\ISimpleFolder; |
|||
use OCP\IURLGenerator; |
|||
use Psr\Log\LoggerInterface; |
|||
|
|||
class IconsCacherTest extends \Test\TestCase { |
|||
/** @var LoggerInterface|\PHPUnit\Framework\MockObject\MockObject */ |
|||
protected $logger; |
|||
/** @var IAppData|\PHPUnit\Framework\MockObject\MockObject */ |
|||
protected $appData; |
|||
/** @var IURLGenerator|\PHPUnit\Framework\MockObject\MockObject */ |
|||
protected $urlGenerator; |
|||
/** @var ITimeFactory|\PHPUnit\Framework\MockObject\MockObject */ |
|||
private $timeFactory; |
|||
|
|||
protected function setUp(): void { |
|||
$this->logger = $this->createMock(LoggerInterface::class); |
|||
$this->appData = $this->createMock(AppData::class); |
|||
$this->timeFactory = $this->createMock(ITimeFactory::class); |
|||
|
|||
/** @var Factory|\PHPUnit\Framework\MockObject\MockObject $factory */ |
|||
$factory = $this->createMock(Factory::class); |
|||
$factory->method('get')->with('css')->willReturn($this->appData); |
|||
|
|||
$this->folder = $this->createMock(ISimpleFolder::class); |
|||
$this->appData->method('getFolder')->willReturn($this->folder); |
|||
|
|||
$this->urlGenerator = $this->createMock(IURLGenerator::class); |
|||
|
|||
$this->iconsCacher = new IconsCacher( |
|||
$this->logger, |
|||
$factory, |
|||
$this->urlGenerator, |
|||
$this->timeFactory |
|||
); |
|||
} |
|||
|
|||
public function testGetIconsFromEmptyCss() { |
|||
$css = "
|
|||
icon.test { |
|||
color: #aaa;
|
|||
} |
|||
";
|
|||
$icons = self::invokePrivate($this->iconsCacher, 'getIconsFromCss', [$css]); |
|||
$this->assertTrue(empty($icons)); |
|||
} |
|||
|
|||
public function testGetIconsFromValidCss() { |
|||
$css = "
|
|||
icon.test { |
|||
--icon-test: url('/svg/core/actions/add/000?v=1'); |
|||
background-image: var(--icon-test); |
|||
} |
|||
";
|
|||
$actual = self::invokePrivate($this->iconsCacher, 'getIconsFromCss', [$css]); |
|||
$expected = [ |
|||
'icon-test' => '/svg/core/actions/add/000?v=1' |
|||
]; |
|||
$this->assertEquals($expected, $actual); |
|||
} |
|||
|
|||
public function testSetIconsFromEmptyCss() { |
|||
$expected = "
|
|||
icon.test { |
|||
color: #aaa;
|
|||
} |
|||
";
|
|||
$actual = $this->iconsCacher->setIconsCss($expected); |
|||
$this->assertEquals($expected, $actual); |
|||
} |
|||
|
|||
public function testSetIconsFromValidCss() { |
|||
$css = "
|
|||
icon.test { |
|||
--icon-test: url('/index.php/svg/core/actions/add?color=000&v=1'); |
|||
background-image: var(--icon-test); |
|||
} |
|||
";
|
|||
$expected = "
|
|||
icon.test { |
|||
\n background-image: var(--icon-test); |
|||
} |
|||
";
|
|||
|
|||
$iconsFile = $this->createMock(ISimpleFile::class); |
|||
$this->folder->expects($this->exactly(2)) |
|||
->method('getFile') |
|||
->willReturn($iconsFile); |
|||
|
|||
$actual = $this->iconsCacher->setIconsCss($css); |
|||
$this->assertEquals($expected, $actual); |
|||
} |
|||
|
|||
public function testSetIconsFromValidCssMultipleTimes() { |
|||
$css = "
|
|||
icon.test { |
|||
--icon-test: url('/index.php/svg/core/actions/add?color=000&v=1'); |
|||
background-image: var(--icon-test); |
|||
} |
|||
";
|
|||
$expected = "
|
|||
icon.test { |
|||
\n background-image: var(--icon-test); |
|||
} |
|||
";
|
|||
|
|||
$iconsFile = $this->createMock(ISimpleFile::class); |
|||
$this->folder->expects($this->exactly(4)) |
|||
->method('getFile') |
|||
->willReturn($iconsFile); |
|||
|
|||
$actual = $this->iconsCacher->setIconsCss($css); |
|||
$actual = $this->iconsCacher->setIconsCss($actual); |
|||
$actual = $this->iconsCacher->setIconsCss($actual); |
|||
$this->assertEquals($expected, $actual); |
|||
} |
|||
} |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue