Skip to content

Commit 86ac7f8

Browse files
Merge pull request #61255 from nextcloud/backport/61253/stable32
[stable32] fix(theming): preserve uploaded favicon and touch icon
2 parents 11d8361 + 7b0f83f commit 86ac7f8

2 files changed

Lines changed: 41 additions & 4 deletions

File tree

apps/theming/lib/Controller/IconController.php

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,8 @@ public function getFavicon(string $app = 'core'): Response {
103103
$response = new FileDisplayResponse($iconFile, Http::STATUS_OK, ['Content-Type' => 'image/x-icon']);
104104
} catch (NotFoundException $e) {
105105
}
106-
// retrieve or generate app specific favicon
107-
if (($this->imageManager->canConvert('PNG') || $this->imageManager->canConvert('SVG')) && $this->imageManager->canConvert('ICO')) {
106+
// retrieve or generate app specific favicon, but only if no custom favicon was uploaded
107+
if ($iconFile === null && ($this->imageManager->canConvert('PNG') || $this->imageManager->canConvert('SVG')) && $this->imageManager->canConvert('ICO')) {
108108
$color = $this->themingDefaults->getColorPrimary();
109109
try {
110110
$iconFile = $this->imageManager->getCachedImage('favIcon-' . $app . $color);
@@ -145,14 +145,15 @@ public function getTouchIcon(string $app = 'core'): Response {
145145
}
146146

147147
$response = null;
148+
$iconFile = null;
148149
// retrieve instance favicon
149150
try {
150151
$iconFile = $this->imageManager->getImage('favicon');
151152
$response = new FileDisplayResponse($iconFile, Http::STATUS_OK, ['Content-Type' => $iconFile->getMimeType()]);
152153
} catch (NotFoundException $e) {
153154
}
154-
// retrieve or generate app specific touch icon
155-
if ($this->imageManager->canConvert('PNG')) {
155+
// retrieve or generate app specific touch icon, but only if no custom favicon was uploaded
156+
if ($iconFile === null && $this->imageManager->canConvert('PNG')) {
156157
$color = $this->themingDefaults->getColorPrimary();
157158
try {
158159
$iconFile = $this->imageManager->getCachedImage('touchIcon-' . $app . $color);

apps/theming/tests/Controller/IconControllerTest.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,24 @@ public function testGetFaviconThemed(): void {
123123
$this->assertEquals($expected, $this->iconController->getFavicon());
124124
}
125125

126+
public function testGetFaviconUploaded(): void {
127+
// a custom favicon was uploaded, so it must be served as-is and the
128+
// app-specific generation path must not overwrite it
129+
$file = $this->iconFileMock('favicon.ico', 'filecontent');
130+
$this->imageManager->expects($this->once())
131+
->method('getImage')
132+
->with('favicon', false)
133+
->willReturn($file);
134+
$this->imageManager->expects($this->never())
135+
->method('getCachedImage');
136+
$this->iconBuilder->expects($this->never())
137+
->method('getFavicon');
138+
139+
$expected = new FileDisplayResponse($file, Http::STATUS_OK, ['Content-Type' => 'image/x-icon']);
140+
$expected->cacheFor(86400);
141+
$this->assertEquals($expected, $this->iconController->getFavicon());
142+
}
143+
126144
public function testGetFaviconDefault(): void {
127145
$this->imageManager->expects($this->once())
128146
->method('getImage')
@@ -178,6 +196,24 @@ public function testGetTouchIconDefault(): void {
178196
$this->assertEquals($expected, $this->iconController->getTouchIcon());
179197
}
180198

199+
public function testGetTouchIconUploaded(): void {
200+
// a custom favicon was uploaded, so it must be served as-is and the
201+
// app-specific generation path must not overwrite it
202+
$file = $this->iconFileMock('favicon.png', 'filecontent');
203+
$this->imageManager->expects($this->once())
204+
->method('getImage')
205+
->with('favicon')
206+
->willReturn($file);
207+
$this->imageManager->expects($this->never())
208+
->method('getCachedImage');
209+
$this->iconBuilder->expects($this->never())
210+
->method('getTouchIcon');
211+
212+
$expected = new FileDisplayResponse($file, Http::STATUS_OK, ['Content-Type' => 'image type']);
213+
$expected->cacheFor(86400);
214+
$this->assertEquals($expected, $this->iconController->getTouchIcon());
215+
}
216+
181217
public function testGetTouchIconFail(): void {
182218
$this->imageManager->expects($this->once())
183219
->method('getImage')

0 commit comments

Comments
 (0)