Merge pull request #6451 from nextcloud/theming-manifest-json
Theming app support for chrome manifest.json file
This commit is contained in:
commit
83508d7be3
|
@ -60,6 +60,12 @@ return ['routes' => [
|
|||
'url' => '/js/theming',
|
||||
'verb' => 'GET',
|
||||
],
|
||||
[
|
||||
'name' => 'Theming#getManifest',
|
||||
'url' => '/manifest/{app}',
|
||||
'verb' => 'GET',
|
||||
'defaults' => array('app' => 'core')
|
||||
],
|
||||
[
|
||||
'name' => 'Icon#getFavicon',
|
||||
'url' => '/favicon/{app}',
|
||||
|
|
|
@ -423,4 +423,39 @@ class ThemingController extends Controller {
|
|||
$response->cacheFor(3600);
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoCSRFRequired
|
||||
* @PublicPage
|
||||
*
|
||||
* @return Http\JSONResponse
|
||||
*/
|
||||
public function getManifest($app) {
|
||||
$cacheBusterValue = $this->config->getAppValue('theming', 'cachebuster', '0');
|
||||
$responseJS = [
|
||||
'name' => $this->themingDefaults->getName(),
|
||||
'start_url' => $this->urlGenerator->getBaseUrl(),
|
||||
'icons' =>
|
||||
[
|
||||
[
|
||||
'src' => $this->urlGenerator->linkToRoute('theming.Icon.getTouchIcon',
|
||||
['app' => $app]) . '?v=' . $cacheBusterValue,
|
||||
'type'=> 'image/png',
|
||||
'sizes'=> '128x128'
|
||||
],
|
||||
[
|
||||
'src' => $this->urlGenerator->linkToRoute('theming.Icon.getFavicon',
|
||||
['app' => $app]) . '?v=' . $cacheBusterValue,
|
||||
'type' => 'image/svg+xml',
|
||||
'sizes' => '16x16'
|
||||
]
|
||||
],
|
||||
'display' => 'standalone'
|
||||
];
|
||||
$response = new Http\JSONResponse($responseJS);
|
||||
$response->addHeader('Expires', date(\DateTime::RFC2822, $this->timeFactory->getTime()));
|
||||
$response->addHeader('Pragma', 'cache');
|
||||
$response->cacheFor(3600);
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
namespace OCA\Theming;
|
||||
|
||||
|
||||
use OCP\App\AppPathNotFoundException;
|
||||
use OCP\App\IAppManager;
|
||||
use OCP\Files\IAppData;
|
||||
use OCP\ICacheFactory;
|
||||
use OCP\IConfig;
|
||||
|
@ -41,6 +43,10 @@ class ThemingDefaults extends \OC_Defaults {
|
|||
private $appData;
|
||||
/** @var ICacheFactory */
|
||||
private $cacheFactory;
|
||||
/** @var Util */
|
||||
private $util;
|
||||
/** @var IAppManager */
|
||||
private $appManager;
|
||||
/** @var string */
|
||||
private $name;
|
||||
/** @var string */
|
||||
|
@ -49,8 +55,7 @@ class ThemingDefaults extends \OC_Defaults {
|
|||
private $slogan;
|
||||
/** @var string */
|
||||
private $color;
|
||||
/** @var Util */
|
||||
private $util;
|
||||
|
||||
/** @var string */
|
||||
private $iTunesAppId;
|
||||
/** @var string */
|
||||
|
@ -68,13 +73,15 @@ class ThemingDefaults extends \OC_Defaults {
|
|||
* @param IAppData $appData
|
||||
* @param ICacheFactory $cacheFactory
|
||||
* @param Util $util
|
||||
* @param IAppManager $appManager
|
||||
*/
|
||||
public function __construct(IConfig $config,
|
||||
IL10N $l,
|
||||
IURLGenerator $urlGenerator,
|
||||
IAppData $appData,
|
||||
ICacheFactory $cacheFactory,
|
||||
Util $util
|
||||
Util $util,
|
||||
IAppManager $appManager
|
||||
) {
|
||||
parent::__construct();
|
||||
$this->config = $config;
|
||||
|
@ -83,6 +90,7 @@ class ThemingDefaults extends \OC_Defaults {
|
|||
$this->appData = $appData;
|
||||
$this->cacheFactory = $cacheFactory;
|
||||
$this->util = $util;
|
||||
$this->appManager = $appManager;
|
||||
|
||||
$this->name = parent::getName();
|
||||
$this->url = parent::getBaseUrl();
|
||||
|
@ -248,6 +256,38 @@ class ThemingDefaults extends \OC_Defaults {
|
|||
return $variables;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the image should be replaced by the theming app
|
||||
* and return the new image location then
|
||||
*
|
||||
* @param string $app name of the app
|
||||
* @param string $image filename of the image
|
||||
* @return bool|string false if image should not replaced, otherwise the location of the image
|
||||
*/
|
||||
public function replaceImagePath($app, $image) {
|
||||
if($app==='') {
|
||||
$app = 'core';
|
||||
}
|
||||
$cacheBusterValue = $this->config->getAppValue('theming', 'cachebuster', '0');
|
||||
|
||||
if ($image === 'favicon.ico' && $this->shouldReplaceIcons()) {
|
||||
return $this->urlGenerator->linkToRoute('theming.Icon.getFavicon', ['app' => $app]) . '?v=' . $cacheBusterValue;
|
||||
}
|
||||
if ($image === 'favicon-touch.png' && $this->shouldReplaceIcons()) {
|
||||
return $this->urlGenerator->linkToRoute('theming.Icon.getTouchIcon', ['app' => $app]) . '?v=' . $cacheBusterValue;
|
||||
}
|
||||
if ($image === 'manifest.json') {
|
||||
try {
|
||||
$appPath = $this->appManager->getAppPath($app);
|
||||
if (file_exists($appPath . '/img/manifest.json')) {
|
||||
return false;
|
||||
}
|
||||
} catch (AppPathNotFoundException $e) {}
|
||||
return $this->urlGenerator->linkToRoute('theming.Theming.getManifest') . '?v=' . $cacheBusterValue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if Imagemagick is enabled and if SVG is supported
|
||||
* otherwise we can't render custom icons
|
||||
|
|
|
@ -729,4 +729,53 @@ class ThemingControllerTest extends TestCase {
|
|||
$expected->cacheFor(3600);
|
||||
@$this->assertEquals($expected, $this->themingController->getJavascript());
|
||||
}
|
||||
|
||||
public function testGetManifest() {
|
||||
$this->config
|
||||
->expects($this->once())
|
||||
->method('getAppValue')
|
||||
->with('theming', 'cachebuster', '0')
|
||||
->willReturn('0');
|
||||
$this->themingDefaults
|
||||
->expects($this->any())
|
||||
->method('getName')
|
||||
->willReturn('Nextcloud');
|
||||
$this->urlGenerator
|
||||
->expects($this->at(0))
|
||||
->method('getBaseUrl')
|
||||
->willReturn('localhost');
|
||||
$this->urlGenerator
|
||||
->expects($this->at(1))
|
||||
->method('linkToRoute')
|
||||
->with('theming.Icon.getTouchIcon', ['app' => 'core'])
|
||||
->willReturn('touchicon');
|
||||
$this->urlGenerator
|
||||
->expects($this->at(2))
|
||||
->method('linkToRoute')
|
||||
->with('theming.Icon.getFavicon', ['app' => 'core'])
|
||||
->willReturn('favicon');
|
||||
$response = new Http\JSONResponse([
|
||||
'name' => 'Nextcloud',
|
||||
'start_url' => 'localhost',
|
||||
'icons' =>
|
||||
[
|
||||
[
|
||||
'src' => 'touchicon?v=0',
|
||||
'type'=> 'image/png',
|
||||
'sizes'=> '128x128'
|
||||
],
|
||||
[
|
||||
'src' => 'favicon?v=0',
|
||||
'type' => 'image/svg+xml',
|
||||
'sizes' => '16x16'
|
||||
]
|
||||
],
|
||||
'display' => 'standalone'
|
||||
]);
|
||||
$response->addHeader('Expires', date(\DateTime::RFC2822, $this->timeFactory->getTime()));
|
||||
$response->addHeader('Pragma', 'cache');
|
||||
$response->cacheFor(3600);
|
||||
$this->assertEquals($response, $this->themingController->getManifest('core'));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
namespace OCA\Theming\Tests;
|
||||
|
||||
use OCA\Theming\ThemingDefaults;
|
||||
use OCP\App\IAppManager;
|
||||
use OCP\Files\IAppData;
|
||||
use OCA\Theming\Util;
|
||||
use OCP\Files\NotFoundException;
|
||||
|
@ -55,6 +56,8 @@ class ThemingDefaultsTest extends TestCase {
|
|||
private $util;
|
||||
/** @var ICache|\PHPUnit_Framework_MockObject_MockObject */
|
||||
private $cache;
|
||||
/** @var IAppManager|\PHPUnit_Framework_MockObject_MockObject */
|
||||
private $appManager;
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
|
@ -65,6 +68,7 @@ class ThemingDefaultsTest extends TestCase {
|
|||
$this->cacheFactory = $this->createMock(ICacheFactory::class);
|
||||
$this->cache = $this->createMock(ICache::class);
|
||||
$this->util = $this->createMock(Util::class);
|
||||
$this->appManager = $this->createMock(IAppManager::class);
|
||||
$this->defaults = new \OC_Defaults();
|
||||
$this->cacheFactory
|
||||
->expects($this->any())
|
||||
|
@ -77,7 +81,8 @@ class ThemingDefaultsTest extends TestCase {
|
|||
$this->urlGenerator,
|
||||
$this->appData,
|
||||
$this->cacheFactory,
|
||||
$this->util
|
||||
$this->util,
|
||||
$this->appManager
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -607,4 +612,31 @@ class ThemingDefaultsTest extends TestCase {
|
|||
$this->assertEquals('1234567890', $this->template->getiTunesAppId());
|
||||
}
|
||||
|
||||
public function dataReplaceImagePath() {
|
||||
return [
|
||||
['core', 'test.png', false],
|
||||
['core', 'manifest.json'],
|
||||
['core', 'favicon.ico'],
|
||||
['core', 'favicon-touch.png']
|
||||
];
|
||||
}
|
||||
|
||||
/** @dataProvider dataReplaceImagePath */
|
||||
public function testReplaceImagePath($app, $image, $result = 'themingRoute?v=0') {
|
||||
$this->cache->expects($this->any())
|
||||
->method('get')
|
||||
->with('shouldReplaceIcons')
|
||||
->willReturn(true);
|
||||
$this->config
|
||||
->expects($this->any())
|
||||
->method('getAppValue')
|
||||
->with('theming', 'cachebuster', '0')
|
||||
->willReturn('0');
|
||||
$this->urlGenerator
|
||||
->expects($this->any())
|
||||
->method('linkToRoute')
|
||||
->willReturn('themingRoute');
|
||||
$this->assertEquals($result, $this->template->replaceImagePath($app, $image));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
<link rel="icon" href="<?php print_unescaped(image_path('', 'favicon.ico')); /* IE11+ supports png */ ?>">
|
||||
<link rel="apple-touch-icon-precomposed" href="<?php print_unescaped(image_path('', 'favicon-touch.png')); ?>">
|
||||
<link rel="mask-icon" sizes="any" href="<?php print_unescaped(image_path('', 'favicon-mask.svg')); ?>" color="<?php p($theme->getColorPrimary()); ?>">
|
||||
<link rel="manifest" href="<?php print_unescaped(image_path('', 'manifest.json')); ?>">
|
||||
<?php emit_css_loading_tags($_); ?>
|
||||
<?php emit_script_loading_tags($_); ?>
|
||||
<?php print_unescaped($_['headers']); ?>
|
||||
|
|
|
@ -892,7 +892,8 @@ class Server extends ServerContainer implements IServerContainer {
|
|||
$c->getURLGenerator(),
|
||||
$c->getAppDataDir('theming'),
|
||||
$c->getMemCacheFactory(),
|
||||
new Util($c->getConfig(), $this->getAppManager(), $this->getAppDataDir('theming'))
|
||||
new Util($c->getConfig(), $this->getAppManager(), $this->getAppDataDir('theming')),
|
||||
$this->getAppManager()
|
||||
);
|
||||
}
|
||||
return new \OC_Defaults();
|
||||
|
|
|
@ -166,6 +166,11 @@ class URLGenerator implements IURLGenerator {
|
|||
// Check if the app is in the app folder
|
||||
$path = '';
|
||||
$themingEnabled = $this->config->getSystemValue('installed', false) && \OCP\App::isEnabled('theming') && \OC_App::isAppLoaded('theming');
|
||||
$themingImagePath = false;
|
||||
if($themingEnabled) {
|
||||
$themingImagePath = \OC::$server->getThemingDefaults()->replaceImagePath($app, $image);
|
||||
}
|
||||
|
||||
if (file_exists(\OC::$SERVERROOT . "/themes/$theme/apps/$app/img/$image")) {
|
||||
$path = \OC::$WEBROOT . "/themes/$theme/apps/$app/img/$image";
|
||||
} elseif (!file_exists(\OC::$SERVERROOT . "/themes/$theme/apps/$app/img/$basename.svg")
|
||||
|
@ -181,14 +186,8 @@ class URLGenerator implements IURLGenerator {
|
|||
} elseif (!file_exists(\OC::$SERVERROOT . "/themes/$theme/core/img/$basename.svg")
|
||||
&& file_exists(\OC::$SERVERROOT . "/themes/$theme/core/img/$basename.png")) {
|
||||
$path = \OC::$WEBROOT . "/themes/$theme/core/img/$basename.png";
|
||||
} elseif($themingEnabled && $image === "favicon.ico" && \OC::$server->getThemingDefaults()->shouldReplaceIcons()) {
|
||||
$cacheBusterValue = $this->config->getAppValue('theming', 'cachebuster', '0');
|
||||
if($app==="") { $app = "core"; }
|
||||
$path = $this->linkToRoute('theming.Icon.getFavicon', [ 'app' => $app ]) . '?v='. $cacheBusterValue;
|
||||
} elseif($themingEnabled && $image === "favicon-touch.png" && \OC::$server->getThemingDefaults()->shouldReplaceIcons()) {
|
||||
$cacheBusterValue = $this->config->getAppValue('theming', 'cachebuster', '0');
|
||||
if($app==="") { $app = "core"; }
|
||||
$path = $this->linkToRoute('theming.Icon.getTouchIcon', [ 'app' => $app ]) . '?v='. $cacheBusterValue;
|
||||
} elseif($themingEnabled && $themingImagePath) {
|
||||
$path = $themingImagePath;
|
||||
} elseif ($appPath && file_exists($appPath . "/img/$image")) {
|
||||
$path = \OC_App::getAppWebPath($app) . "/img/$image";
|
||||
} elseif ($appPath && !file_exists($appPath . "/img/$basename.svg")
|
||||
|
|
Loading…
Reference in New Issue