Passed
Push — master ( 8555d5...a51f0d )
by John
14:05 queued 13s
created
apps/theming/lib/Service/BackgroundService.php 1 patch
Indentation   +192 added lines, -192 removed lines patch added patch discarded remove patch
@@ -43,196 +43,196 @@
 block discarded – undo
43 43
 use OCP\PreConditionNotMetException;
44 44
 
45 45
 class BackgroundService {
46
-	// true when the background is bright and need dark icons
47
-	public const THEMING_MODE_DARK = 'dark';
48
-	public const DEFAULT_COLOR = '#0082c9';
49
-	public const DEFAULT_ACCESSIBLE_COLOR = '#006aa3';
50
-
51
-	public const BACKGROUND_SHIPPED = 'shipped';
52
-	public const BACKGROUND_CUSTOM = 'custom';
53
-	public const BACKGROUND_DEFAULT = 'default';
54
-	public const BACKGROUND_DISABLED = 'disabled';
55
-
56
-	public const DEFAULT_BACKGROUND_IMAGE = 'kamil-porembinski-clouds.jpg';
57
-	public const SHIPPED_BACKGROUNDS = [
58
-		'anatoly-mikhaltsov-butterfly-wing-scale.jpg' => [
59
-			'attribution' => 'Butterfly wing scale (Anatoly Mikhaltsov, CC BY-SA)',
60
-			'attribution_url' => 'https://commons.wikimedia.org/wiki/File:%D0%A7%D0%B5%D1%88%D1%83%D0%B9%D0%BA%D0%B8_%D0%BA%D1%80%D1%8B%D0%BB%D0%B0_%D0%B1%D0%B0%D0%B1%D0%BE%D1%87%D0%BA%D0%B8.jpg',
61
-			'primary_color' => '#a53c17',
62
-		],
63
-		'bernie-cetonia-aurata-take-off-composition.jpg' => [
64
-			'attribution' => 'Cetonia aurata take off composition (Bernie, Public Domain)',
65
-			'attribution_url' => 'https://commons.wikimedia.org/wiki/File:Cetonia_aurata_take_off_composition_05172009.jpg',
66
-			'theming' => self::THEMING_MODE_DARK,
67
-			'primary_color' => '#56633d',
68
-		],
69
-		'dejan-krsmanovic-ribbed-red-metal.jpg' => [
70
-			'attribution' => 'Ribbed red metal (Dejan Krsmanovic, CC BY)',
71
-			'attribution_url' => 'https://www.flickr.com/photos/dejankrsmanovic/42971456774/',
72
-			'primary_color' => '#9c4236',
73
-		],
74
-		'eduardo-neves-pedra-azul.jpg' => [
75
-			'attribution' => 'Pedra azul milky way (Eduardo Neves, CC BY-SA)',
76
-			'attribution_url' => 'https://commons.wikimedia.org/wiki/File:Pedra_Azul_Milky_Way.jpg',
77
-			'primary_color' => '#4f6071',
78
-		],
79
-		'european-space-agency-barents-bloom.jpg' => [
80
-			'attribution' => 'Barents bloom (European Space Agency, CC BY-SA)',
81
-			'attribution_url' => 'https://www.esa.int/ESA_Multimedia/Images/2016/08/Barents_bloom',
82
-			'primary_color' => '#396475',
83
-		],
84
-		'hannes-fritz-flippity-floppity.jpg' => [
85
-			'attribution' => 'Flippity floppity (Hannes Fritz, CC BY-SA)',
86
-			'attribution_url' => 'http://hannes.photos/flippity-floppity',
87
-			'primary_color' => '#98415a',
88
-		],
89
-		'hannes-fritz-roulette.jpg' => [
90
-			'attribution' => 'Roulette (Hannes Fritz, CC BY-SA)',
91
-			'attribution_url' => 'http://hannes.photos/roulette',
92
-			'primary_color' => '#845334',
93
-		],
94
-		'hannes-fritz-sea-spray.jpg' => [
95
-			'attribution' => 'Sea spray (Hannes Fritz, CC BY-SA)',
96
-			'attribution_url' => 'http://hannes.photos/sea-spray',
97
-			'primary_color' => '#4f6071',
98
-		],
99
-		'kamil-porembinski-clouds.jpg' => [
100
-			'attribution' => 'Clouds (Kamil Porembiński, CC BY-SA)',
101
-			'attribution_url' => 'https://www.flickr.com/photos/paszczak000/8715851521/',
102
-			'primary_color' => self::DEFAULT_COLOR,
103
-		],
104
-		'bernard-spragg-new-zealand-fern.jpg' => [
105
-			'attribution' => 'New zealand fern (Bernard Spragg, CC0)',
106
-			'attribution_url' => 'https://commons.wikimedia.org/wiki/File:NZ_Fern.(Blechnum_chambersii)_(11263534936).jpg',
107
-			'primary_color' => '#316b26',
108
-		],
109
-		'rawpixel-pink-tapioca-bubbles.jpg' => [
110
-			'attribution' => 'Pink tapioca bubbles (Rawpixel, CC BY)',
111
-			'attribution_url' => 'https://www.flickr.com/photos/byrawpixel/27665140298/in/photostream/',
112
-			'theming' => self::THEMING_MODE_DARK,
113
-			'primary_color' => '#7b4e7e',
114
-		],
115
-		'nasa-waxing-crescent-moon.jpg' => [
116
-			'attribution' => 'Waxing crescent moon (NASA, Public Domain)',
117
-			'attribution_url' => 'https://www.nasa.gov/image-feature/a-waxing-crescent-moon',
118
-			'primary_color' => '#005ac1',
119
-		],
120
-		'tommy-chau-already.jpg' => [
121
-			'attribution' => 'Cityscape (Tommy Chau, CC BY)',
122
-			'attribution_url' => 'https://www.flickr.com/photos/90975693@N05/16910999368',
123
-			'primary_color' => '#6a2af4',
124
-		],
125
-		'tommy-chau-lion-rock-hill.jpg' => [
126
-			'attribution' => 'Lion rock hill (Tommy Chau, CC BY)',
127
-			'attribution_url' => 'https://www.flickr.com/photos/90975693@N05/17136440246',
128
-			'theming' => self::THEMING_MODE_DARK,
129
-			'primary_color' => '#7f4f70',
130
-		],
131
-		'lali-masriera-yellow-bricks.jpg' => [
132
-			'attribution' => 'Yellow bricks (Lali Masriera, CC BY)',
133
-			'attribution_url' => 'https://www.flickr.com/photos/visualpanic/3982464447',
134
-			'theming' => self::THEMING_MODE_DARK,
135
-			'primary_color' => '#7f5700',
136
-		],
137
-	];
138
-
139
-	private IRootFolder $rootFolder;
140
-	private IAppData $appData;
141
-	private IConfig $config;
142
-	private string $userId;
143
-	private ThemingDefaults $themingDefaults;
144
-
145
-	public function __construct(IRootFolder $rootFolder,
146
-								IAppData $appData,
147
-								IConfig $config,
148
-								?string $userId,
149
-								ThemingDefaults $themingDefaults) {
150
-		if ($userId === null) {
151
-			return;
152
-		}
153
-
154
-		$this->rootFolder = $rootFolder;
155
-		$this->config = $config;
156
-		$this->userId = $userId;
157
-		$this->appData = $appData;
158
-		$this->themingDefaults = $themingDefaults;
159
-	}
160
-
161
-	public function setDefaultBackground(): void {
162
-		$this->config->deleteUserValue($this->userId, Application::APP_ID, 'background_image');
163
-		$this->config->deleteUserValue($this->userId, Application::APP_ID, 'background_color');
164
-	}
165
-
166
-	/**
167
-	 * @param $path
168
-	 * @throws NotFoundException
169
-	 * @throws NotPermittedException
170
-	 * @throws LockedException
171
-	 * @throws PreConditionNotMetException
172
-	 * @throws NoUserException
173
-	 */
174
-	public function setFileBackground($path): void {
175
-		$this->config->setUserValue($this->userId, Application::APP_ID, 'background_image', self::BACKGROUND_CUSTOM);
176
-		$userFolder = $this->rootFolder->getUserFolder($this->userId);
177
-
178
-		/** @var File $file */
179
-		$file = $userFolder->get($path);
180
-		$image = new \OCP\Image();
181
-
182
-		if ($image->loadFromFileHandle($file->fopen('r')) === false) {
183
-			throw new InvalidArgumentException('Invalid image file');
184
-		}
185
-
186
-		$this->getAppDataFolder()->newFile('background.jpg', $file->fopen('r'));
187
-	}
188
-
189
-	public function setShippedBackground($fileName): void {
190
-		if (!array_key_exists($fileName, self::SHIPPED_BACKGROUNDS)) {
191
-			throw new InvalidArgumentException('The given file name is invalid');
192
-		}
193
-		$this->config->setUserValue($this->userId, Application::APP_ID, 'background_image', $fileName);
194
-		$this->setColorBackground(self::SHIPPED_BACKGROUNDS[$fileName]['primary_color']);
195
-	}
196
-
197
-	public function setColorBackground(string $color): void {
198
-		if (!preg_match('/^#([0-9a-f]{3}|[0-9a-f]{6})$/i', $color)) {
199
-			throw new InvalidArgumentException('The given color is invalid');
200
-		}
201
-		$this->config->setUserValue($this->userId, Application::APP_ID, 'background_color', $color);
202
-	}
203
-
204
-	public function deleteBackgroundImage(): void {
205
-		$this->config->setUserValue($this->userId, Application::APP_ID, 'background_image', self::BACKGROUND_DISABLED);
206
-	}
207
-
208
-	public function getBackground(): ?ISimpleFile {
209
-		$background = $this->config->getUserValue($this->userId, Application::APP_ID, 'background_image', self::BACKGROUND_DEFAULT);
210
-		if ($background === self::BACKGROUND_CUSTOM) {
211
-			try {
212
-				return $this->getAppDataFolder()->getFile('background.jpg');
213
-			} catch (NotFoundException | NotPermittedException $e) {
214
-				return null;
215
-			}
216
-		}
217
-		return null;
218
-	}
219
-
220
-	/**
221
-	 * Storing the data in appdata/theming/users/USERID
222
-	 *
223
-	 * @return ISimpleFolder
224
-	 * @throws NotPermittedException
225
-	 */
226
-	private function getAppDataFolder(): ISimpleFolder {
227
-		try {
228
-			$rootFolder = $this->appData->getFolder('users');
229
-		} catch (NotFoundException $e) {
230
-			$rootFolder = $this->appData->newFolder('users');
231
-		}
232
-		try {
233
-			return $rootFolder->getFolder($this->userId);
234
-		} catch (NotFoundException $e) {
235
-			return $rootFolder->newFolder($this->userId);
236
-		}
237
-	}
46
+    // true when the background is bright and need dark icons
47
+    public const THEMING_MODE_DARK = 'dark';
48
+    public const DEFAULT_COLOR = '#0082c9';
49
+    public const DEFAULT_ACCESSIBLE_COLOR = '#006aa3';
50
+
51
+    public const BACKGROUND_SHIPPED = 'shipped';
52
+    public const BACKGROUND_CUSTOM = 'custom';
53
+    public const BACKGROUND_DEFAULT = 'default';
54
+    public const BACKGROUND_DISABLED = 'disabled';
55
+
56
+    public const DEFAULT_BACKGROUND_IMAGE = 'kamil-porembinski-clouds.jpg';
57
+    public const SHIPPED_BACKGROUNDS = [
58
+        'anatoly-mikhaltsov-butterfly-wing-scale.jpg' => [
59
+            'attribution' => 'Butterfly wing scale (Anatoly Mikhaltsov, CC BY-SA)',
60
+            'attribution_url' => 'https://commons.wikimedia.org/wiki/File:%D0%A7%D0%B5%D1%88%D1%83%D0%B9%D0%BA%D0%B8_%D0%BA%D1%80%D1%8B%D0%BB%D0%B0_%D0%B1%D0%B0%D0%B1%D0%BE%D1%87%D0%BA%D0%B8.jpg',
61
+            'primary_color' => '#a53c17',
62
+        ],
63
+        'bernie-cetonia-aurata-take-off-composition.jpg' => [
64
+            'attribution' => 'Cetonia aurata take off composition (Bernie, Public Domain)',
65
+            'attribution_url' => 'https://commons.wikimedia.org/wiki/File:Cetonia_aurata_take_off_composition_05172009.jpg',
66
+            'theming' => self::THEMING_MODE_DARK,
67
+            'primary_color' => '#56633d',
68
+        ],
69
+        'dejan-krsmanovic-ribbed-red-metal.jpg' => [
70
+            'attribution' => 'Ribbed red metal (Dejan Krsmanovic, CC BY)',
71
+            'attribution_url' => 'https://www.flickr.com/photos/dejankrsmanovic/42971456774/',
72
+            'primary_color' => '#9c4236',
73
+        ],
74
+        'eduardo-neves-pedra-azul.jpg' => [
75
+            'attribution' => 'Pedra azul milky way (Eduardo Neves, CC BY-SA)',
76
+            'attribution_url' => 'https://commons.wikimedia.org/wiki/File:Pedra_Azul_Milky_Way.jpg',
77
+            'primary_color' => '#4f6071',
78
+        ],
79
+        'european-space-agency-barents-bloom.jpg' => [
80
+            'attribution' => 'Barents bloom (European Space Agency, CC BY-SA)',
81
+            'attribution_url' => 'https://www.esa.int/ESA_Multimedia/Images/2016/08/Barents_bloom',
82
+            'primary_color' => '#396475',
83
+        ],
84
+        'hannes-fritz-flippity-floppity.jpg' => [
85
+            'attribution' => 'Flippity floppity (Hannes Fritz, CC BY-SA)',
86
+            'attribution_url' => 'http://hannes.photos/flippity-floppity',
87
+            'primary_color' => '#98415a',
88
+        ],
89
+        'hannes-fritz-roulette.jpg' => [
90
+            'attribution' => 'Roulette (Hannes Fritz, CC BY-SA)',
91
+            'attribution_url' => 'http://hannes.photos/roulette',
92
+            'primary_color' => '#845334',
93
+        ],
94
+        'hannes-fritz-sea-spray.jpg' => [
95
+            'attribution' => 'Sea spray (Hannes Fritz, CC BY-SA)',
96
+            'attribution_url' => 'http://hannes.photos/sea-spray',
97
+            'primary_color' => '#4f6071',
98
+        ],
99
+        'kamil-porembinski-clouds.jpg' => [
100
+            'attribution' => 'Clouds (Kamil Porembiński, CC BY-SA)',
101
+            'attribution_url' => 'https://www.flickr.com/photos/paszczak000/8715851521/',
102
+            'primary_color' => self::DEFAULT_COLOR,
103
+        ],
104
+        'bernard-spragg-new-zealand-fern.jpg' => [
105
+            'attribution' => 'New zealand fern (Bernard Spragg, CC0)',
106
+            'attribution_url' => 'https://commons.wikimedia.org/wiki/File:NZ_Fern.(Blechnum_chambersii)_(11263534936).jpg',
107
+            'primary_color' => '#316b26',
108
+        ],
109
+        'rawpixel-pink-tapioca-bubbles.jpg' => [
110
+            'attribution' => 'Pink tapioca bubbles (Rawpixel, CC BY)',
111
+            'attribution_url' => 'https://www.flickr.com/photos/byrawpixel/27665140298/in/photostream/',
112
+            'theming' => self::THEMING_MODE_DARK,
113
+            'primary_color' => '#7b4e7e',
114
+        ],
115
+        'nasa-waxing-crescent-moon.jpg' => [
116
+            'attribution' => 'Waxing crescent moon (NASA, Public Domain)',
117
+            'attribution_url' => 'https://www.nasa.gov/image-feature/a-waxing-crescent-moon',
118
+            'primary_color' => '#005ac1',
119
+        ],
120
+        'tommy-chau-already.jpg' => [
121
+            'attribution' => 'Cityscape (Tommy Chau, CC BY)',
122
+            'attribution_url' => 'https://www.flickr.com/photos/90975693@N05/16910999368',
123
+            'primary_color' => '#6a2af4',
124
+        ],
125
+        'tommy-chau-lion-rock-hill.jpg' => [
126
+            'attribution' => 'Lion rock hill (Tommy Chau, CC BY)',
127
+            'attribution_url' => 'https://www.flickr.com/photos/90975693@N05/17136440246',
128
+            'theming' => self::THEMING_MODE_DARK,
129
+            'primary_color' => '#7f4f70',
130
+        ],
131
+        'lali-masriera-yellow-bricks.jpg' => [
132
+            'attribution' => 'Yellow bricks (Lali Masriera, CC BY)',
133
+            'attribution_url' => 'https://www.flickr.com/photos/visualpanic/3982464447',
134
+            'theming' => self::THEMING_MODE_DARK,
135
+            'primary_color' => '#7f5700',
136
+        ],
137
+    ];
138
+
139
+    private IRootFolder $rootFolder;
140
+    private IAppData $appData;
141
+    private IConfig $config;
142
+    private string $userId;
143
+    private ThemingDefaults $themingDefaults;
144
+
145
+    public function __construct(IRootFolder $rootFolder,
146
+                                IAppData $appData,
147
+                                IConfig $config,
148
+                                ?string $userId,
149
+                                ThemingDefaults $themingDefaults) {
150
+        if ($userId === null) {
151
+            return;
152
+        }
153
+
154
+        $this->rootFolder = $rootFolder;
155
+        $this->config = $config;
156
+        $this->userId = $userId;
157
+        $this->appData = $appData;
158
+        $this->themingDefaults = $themingDefaults;
159
+    }
160
+
161
+    public function setDefaultBackground(): void {
162
+        $this->config->deleteUserValue($this->userId, Application::APP_ID, 'background_image');
163
+        $this->config->deleteUserValue($this->userId, Application::APP_ID, 'background_color');
164
+    }
165
+
166
+    /**
167
+     * @param $path
168
+     * @throws NotFoundException
169
+     * @throws NotPermittedException
170
+     * @throws LockedException
171
+     * @throws PreConditionNotMetException
172
+     * @throws NoUserException
173
+     */
174
+    public function setFileBackground($path): void {
175
+        $this->config->setUserValue($this->userId, Application::APP_ID, 'background_image', self::BACKGROUND_CUSTOM);
176
+        $userFolder = $this->rootFolder->getUserFolder($this->userId);
177
+
178
+        /** @var File $file */
179
+        $file = $userFolder->get($path);
180
+        $image = new \OCP\Image();
181
+
182
+        if ($image->loadFromFileHandle($file->fopen('r')) === false) {
183
+            throw new InvalidArgumentException('Invalid image file');
184
+        }
185
+
186
+        $this->getAppDataFolder()->newFile('background.jpg', $file->fopen('r'));
187
+    }
188
+
189
+    public function setShippedBackground($fileName): void {
190
+        if (!array_key_exists($fileName, self::SHIPPED_BACKGROUNDS)) {
191
+            throw new InvalidArgumentException('The given file name is invalid');
192
+        }
193
+        $this->config->setUserValue($this->userId, Application::APP_ID, 'background_image', $fileName);
194
+        $this->setColorBackground(self::SHIPPED_BACKGROUNDS[$fileName]['primary_color']);
195
+    }
196
+
197
+    public function setColorBackground(string $color): void {
198
+        if (!preg_match('/^#([0-9a-f]{3}|[0-9a-f]{6})$/i', $color)) {
199
+            throw new InvalidArgumentException('The given color is invalid');
200
+        }
201
+        $this->config->setUserValue($this->userId, Application::APP_ID, 'background_color', $color);
202
+    }
203
+
204
+    public function deleteBackgroundImage(): void {
205
+        $this->config->setUserValue($this->userId, Application::APP_ID, 'background_image', self::BACKGROUND_DISABLED);
206
+    }
207
+
208
+    public function getBackground(): ?ISimpleFile {
209
+        $background = $this->config->getUserValue($this->userId, Application::APP_ID, 'background_image', self::BACKGROUND_DEFAULT);
210
+        if ($background === self::BACKGROUND_CUSTOM) {
211
+            try {
212
+                return $this->getAppDataFolder()->getFile('background.jpg');
213
+            } catch (NotFoundException | NotPermittedException $e) {
214
+                return null;
215
+            }
216
+        }
217
+        return null;
218
+    }
219
+
220
+    /**
221
+     * Storing the data in appdata/theming/users/USERID
222
+     *
223
+     * @return ISimpleFolder
224
+     * @throws NotPermittedException
225
+     */
226
+    private function getAppDataFolder(): ISimpleFolder {
227
+        try {
228
+            $rootFolder = $this->appData->getFolder('users');
229
+        } catch (NotFoundException $e) {
230
+            $rootFolder = $this->appData->newFolder('users');
231
+        }
232
+        try {
233
+            return $rootFolder->getFolder($this->userId);
234
+        } catch (NotFoundException $e) {
235
+            return $rootFolder->newFolder($this->userId);
236
+        }
237
+    }
238 238
 }
Please login to merge, or discard this patch.
apps/theming/lib/ThemingDefaults.php 1 patch
Indentation   +447 added lines, -447 removed lines patch added patch discarded remove patch
@@ -55,451 +55,451 @@
 block discarded – undo
55 55
 
56 56
 class ThemingDefaults extends \OC_Defaults {
57 57
 
58
-	private IConfig $config;
59
-	private IL10N $l;
60
-	private ImageManager $imageManager;
61
-	private IUserSession $userSession;
62
-	private IURLGenerator $urlGenerator;
63
-	private ICacheFactory $cacheFactory;
64
-	private Util $util;
65
-	private IAppManager $appManager;
66
-	private INavigationManager $navigationManager;
67
-
68
-	private string $name;
69
-	private string $title;
70
-	private string $entity;
71
-	private string $productName;
72
-	private string $url;
73
-	private string $color;
74
-
75
-	private string $iTunesAppId;
76
-	private string $iOSClientUrl;
77
-	private string $AndroidClientUrl;
78
-	private string $FDroidClientUrl;
79
-
80
-	/**
81
-	 * ThemingDefaults constructor.
82
-	 *
83
-	 * @param IConfig $config
84
-	 * @param IL10N $l
85
-	 * @param ImageManager $imageManager
86
-	 * @param IUserSession $userSession
87
-	 * @param IURLGenerator $urlGenerator
88
-	 * @param ICacheFactory $cacheFactory
89
-	 * @param Util $util
90
-	 * @param IAppManager $appManager
91
-	 */
92
-	public function __construct(IConfig $config,
93
-								IL10N $l,
94
-								IUserSession $userSession,
95
-								IURLGenerator $urlGenerator,
96
-								ICacheFactory $cacheFactory,
97
-								Util $util,
98
-								ImageManager $imageManager,
99
-								IAppManager $appManager,
100
-								INavigationManager $navigationManager
101
-	) {
102
-		parent::__construct();
103
-		$this->config = $config;
104
-		$this->l = $l;
105
-		$this->imageManager = $imageManager;
106
-		$this->userSession = $userSession;
107
-		$this->urlGenerator = $urlGenerator;
108
-		$this->cacheFactory = $cacheFactory;
109
-		$this->util = $util;
110
-		$this->appManager = $appManager;
111
-		$this->navigationManager = $navigationManager;
112
-
113
-		$this->name = parent::getName();
114
-		$this->title = parent::getTitle();
115
-		$this->entity = parent::getEntity();
116
-		$this->productName = parent::getProductName();
117
-		$this->url = parent::getBaseUrl();
118
-		$this->color = parent::getColorPrimary();
119
-		$this->iTunesAppId = parent::getiTunesAppId();
120
-		$this->iOSClientUrl = parent::getiOSClientUrl();
121
-		$this->AndroidClientUrl = parent::getAndroidClientUrl();
122
-		$this->FDroidClientUrl = parent::getFDroidClientUrl();
123
-	}
124
-
125
-	public function getName() {
126
-		return strip_tags($this->config->getAppValue('theming', 'name', $this->name));
127
-	}
128
-
129
-	public function getHTMLName() {
130
-		return $this->config->getAppValue('theming', 'name', $this->name);
131
-	}
132
-
133
-	public function getTitle() {
134
-		return strip_tags($this->config->getAppValue('theming', 'name', $this->title));
135
-	}
136
-
137
-	public function getEntity() {
138
-		return strip_tags($this->config->getAppValue('theming', 'name', $this->entity));
139
-	}
140
-
141
-	public function getProductName() {
142
-		return strip_tags($this->config->getAppValue('theming', 'productName', $this->productName));
143
-	}
144
-
145
-	public function getBaseUrl() {
146
-		return $this->config->getAppValue('theming', 'url', $this->url);
147
-	}
148
-
149
-	/**
150
-	 * We pass a string and sanitizeHTML will return a string too in that case
151
-	 * @psalm-suppress InvalidReturnStatement
152
-	 * @psalm-suppress InvalidReturnType
153
-	 */
154
-	public function getSlogan(?string $lang = null) {
155
-		return \OCP\Util::sanitizeHTML($this->config->getAppValue('theming', 'slogan', parent::getSlogan($lang)));
156
-	}
157
-
158
-	public function getImprintUrl() {
159
-		return (string)$this->config->getAppValue('theming', 'imprintUrl', '');
160
-	}
161
-
162
-	public function getPrivacyUrl() {
163
-		return (string)$this->config->getAppValue('theming', 'privacyUrl', '');
164
-	}
165
-
166
-	public function getShortFooter() {
167
-		$slogan = $this->getSlogan();
168
-		$baseUrl = $this->getBaseUrl();
169
-		if ($baseUrl !== '') {
170
-			$footer = '<a href="' . $baseUrl . '" target="_blank"' .
171
-				' rel="noreferrer noopener" class="entity-name">' . $this->getEntity() . '</a>';
172
-		} else {
173
-			$footer = '<span class="entity-name">' .$this->getEntity() . '</span>';
174
-		}
175
-		$footer .= ($slogan !== '' ? ' – ' . $slogan : '');
176
-
177
-		$links = [
178
-			[
179
-				'text' => $this->l->t('Legal notice'),
180
-				'url' => (string)$this->getImprintUrl()
181
-			],
182
-			[
183
-				'text' => $this->l->t('Privacy policy'),
184
-				'url' => (string)$this->getPrivacyUrl()
185
-			],
186
-		];
187
-
188
-		$navigation = $this->navigationManager->getAll(INavigationManager::TYPE_GUEST);
189
-		$guestNavigation = array_map(function ($nav) {
190
-			return [
191
-				'text' => $nav['name'],
192
-				'url' => $nav['href']
193
-			];
194
-		}, $navigation);
195
-		$links = array_merge($links, $guestNavigation);
196
-
197
-		$legalLinks = '';
198
-		$divider = '';
199
-		foreach ($links as $link) {
200
-			if ($link['url'] !== ''
201
-				&& filter_var($link['url'], FILTER_VALIDATE_URL)
202
-			) {
203
-				$legalLinks .= $divider . '<a href="' . $link['url'] . '" class="legal" target="_blank"' .
204
-					' rel="noreferrer noopener">' . $link['text'] . '</a>';
205
-				$divider = ' · ';
206
-			}
207
-		}
208
-		if ($legalLinks !== '') {
209
-			$footer .= '<br/>' . $legalLinks;
210
-		}
211
-
212
-		return $footer;
213
-	}
214
-
215
-	/**
216
-	 * Color that is used for the header as well as for mail headers
217
-	 */
218
-	public function getColorPrimary(): string {
219
-		$user = $this->userSession->getUser();
220
-
221
-		// admin-defined primary color
222
-		$defaultColor = $this->getDefaultColorPrimary();
223
-
224
-		if ($this->isUserThemingDisabled()) {
225
-			return $defaultColor;
226
-		}
227
-
228
-		// user-defined primary color
229
-		if (!empty($user)) {
230
-			$themingBackgroundColor = $this->config->getUserValue($user->getUID(), Application::APP_ID, 'background_color', '');
231
-			// If the user selected a specific colour
232
-			if (preg_match('/^\#([0-9a-f]{3}|[0-9a-f]{6})$/i', $themingBackgroundColor)) {
233
-				return $themingBackgroundColor;
234
-			}
235
-		}
236
-
237
-		// If the default color is not valid, return the default background one
238
-		if (!preg_match('/^\#([0-9a-f]{3}|[0-9a-f]{6})$/i', $defaultColor)) {
239
-			return BackgroundService::DEFAULT_COLOR;
240
-		}
241
-
242
-		// Finally, return the system global primary color
243
-		return $defaultColor;
244
-	}
245
-
246
-	/**
247
-	 * Return the default color primary
248
-	 */
249
-	public function getDefaultColorPrimary(): string {
250
-		$color = $this->config->getAppValue(Application::APP_ID, 'color', '');
251
-		if (!preg_match('/^\#([0-9a-f]{3}|[0-9a-f]{6})$/i', $color)) {
252
-			$color = '#0082c9';
253
-		}
254
-		return $color;
255
-	}
256
-
257
-	/**
258
-	 * Themed logo url
259
-	 *
260
-	 * @param bool $useSvg Whether to point to the SVG image or a fallback
261
-	 * @return string
262
-	 */
263
-	public function getLogo($useSvg = true): string {
264
-		$logo = $this->config->getAppValue('theming', 'logoMime', '');
265
-
266
-		// short cut to avoid setting up the filesystem just to check if the logo is there
267
-		//
268
-		// explanation: if an SVG is requested and the app config value for logoMime is set then the logo is there.
269
-		// otherwise we need to check it and maybe also generate a PNG from the SVG (that's done in getImage() which
270
-		// needs to be called then)
271
-		if ($useSvg === true && $logo !== false) {
272
-			$logoExists = true;
273
-		} else {
274
-			try {
275
-				$this->imageManager->getImage('logo', $useSvg);
276
-				$logoExists = true;
277
-			} catch (\Exception $e) {
278
-				$logoExists = false;
279
-			}
280
-		}
281
-
282
-		$cacheBusterCounter = $this->config->getAppValue('theming', 'cachebuster', '0');
283
-
284
-		if (!$logo || !$logoExists) {
285
-			if ($useSvg) {
286
-				$logo = $this->urlGenerator->imagePath('core', 'logo/logo.svg');
287
-			} else {
288
-				$logo = $this->urlGenerator->imagePath('core', 'logo/logo.png');
289
-			}
290
-			return $logo . '?v=' . $cacheBusterCounter;
291
-		}
292
-
293
-		return $this->urlGenerator->linkToRoute('theming.Theming.getImage', [ 'key' => 'logo', 'useSvg' => $useSvg, 'v' => $cacheBusterCounter ]);
294
-	}
295
-
296
-	/**
297
-	 * Themed background image url
298
-	 *
299
-	 * @return string
300
-	 */
301
-	public function getBackground(): string {
302
-		return $this->imageManager->getImageUrl('background');
303
-	}
304
-
305
-	/**
306
-	 * @return string
307
-	 */
308
-	public function getiTunesAppId() {
309
-		return $this->config->getAppValue('theming', 'iTunesAppId', $this->iTunesAppId);
310
-	}
311
-
312
-	/**
313
-	 * @return string
314
-	 */
315
-	public function getiOSClientUrl() {
316
-		return $this->config->getAppValue('theming', 'iOSClientUrl', $this->iOSClientUrl);
317
-	}
318
-
319
-	/**
320
-	 * @return string
321
-	 */
322
-	public function getAndroidClientUrl() {
323
-		return $this->config->getAppValue('theming', 'AndroidClientUrl', $this->AndroidClientUrl);
324
-	}
325
-
326
-	/**
327
-	 * @return string
328
-	 */
329
-	public function getFDroidClientUrl() {
330
-		return $this->config->getAppValue('theming', 'FDroidClientUrl', $this->FDroidClientUrl);
331
-	}
332
-
333
-	/**
334
-	 * @return array scss variables to overwrite
335
-	 */
336
-	public function getScssVariables() {
337
-		$cacheBuster = $this->config->getAppValue('theming', 'cachebuster', '0');
338
-		$cache = $this->cacheFactory->createDistributed('theming-' . $cacheBuster . '-' . $this->urlGenerator->getBaseUrl());
339
-		if ($value = $cache->get('getScssVariables')) {
340
-			return $value;
341
-		}
342
-
343
-		$variables = [
344
-			'theming-cachebuster' => "'" . $cacheBuster . "'",
345
-			'theming-logo-mime' => "'" . $this->config->getAppValue('theming', 'logoMime') . "'",
346
-			'theming-background-mime' => "'" . $this->config->getAppValue('theming', 'backgroundMime') . "'",
347
-			'theming-logoheader-mime' => "'" . $this->config->getAppValue('theming', 'logoheaderMime') . "'",
348
-			'theming-favicon-mime' => "'" . $this->config->getAppValue('theming', 'faviconMime') . "'"
349
-		];
350
-
351
-		$variables['image-logo'] = "url('".$this->imageManager->getImageUrl('logo')."')";
352
-		$variables['image-logoheader'] = "url('".$this->imageManager->getImageUrl('logoheader')."')";
353
-		$variables['image-favicon'] = "url('".$this->imageManager->getImageUrl('favicon')."')";
354
-		$variables['image-login-background'] = "url('".$this->imageManager->getImageUrl('background')."')";
355
-		$variables['image-login-plain'] = 'false';
356
-
357
-		if ($this->config->getAppValue('theming', 'color', '') !== '') {
358
-			$variables['color-primary'] = $this->getColorPrimary();
359
-			$variables['color-primary-text'] = $this->getTextColorPrimary();
360
-			$variables['color-primary-element'] = $this->util->elementColor($this->getColorPrimary());
361
-		}
362
-
363
-		if ($this->config->getAppValue('theming', 'backgroundMime', '') === 'backgroundColor') {
364
-			$variables['image-login-plain'] = 'true';
365
-		}
366
-
367
-		$variables['has-legal-links'] = 'false';
368
-		if ($this->getImprintUrl() !== '' || $this->getPrivacyUrl() !== '') {
369
-			$variables['has-legal-links'] = 'true';
370
-		}
371
-
372
-		$cache->set('getScssVariables', $variables);
373
-		return $variables;
374
-	}
375
-
376
-	/**
377
-	 * Check if the image should be replaced by the theming app
378
-	 * and return the new image location then
379
-	 *
380
-	 * @param string $app name of the app
381
-	 * @param string $image filename of the image
382
-	 * @return bool|string false if image should not replaced, otherwise the location of the image
383
-	 */
384
-	public function replaceImagePath($app, $image) {
385
-		if ($app === '' || $app === 'files_sharing') {
386
-			$app = 'core';
387
-		}
388
-		$cacheBusterValue = $this->config->getAppValue('theming', 'cachebuster', '0');
389
-
390
-		$route = false;
391
-		if ($image === 'favicon.ico' && ($this->imageManager->shouldReplaceIcons() || $this->getCustomFavicon() !== null)) {
392
-			$route = $this->urlGenerator->linkToRoute('theming.Icon.getFavicon', ['app' => $app]);
393
-		}
394
-		if (($image === 'favicon-touch.png' || $image === 'favicon-fb.png') && ($this->imageManager->shouldReplaceIcons() || $this->getCustomFavicon() !== null)) {
395
-			$route = $this->urlGenerator->linkToRoute('theming.Icon.getTouchIcon', ['app' => $app]);
396
-		}
397
-		if ($image === 'manifest.json') {
398
-			try {
399
-				$appPath = $this->appManager->getAppPath($app);
400
-				if (file_exists($appPath . '/img/manifest.json')) {
401
-					return false;
402
-				}
403
-			} catch (AppPathNotFoundException $e) {
404
-			}
405
-			$route = $this->urlGenerator->linkToRoute('theming.Theming.getManifest', ['app' => $app ]);
406
-		}
407
-		if (strpos($image, 'filetypes/') === 0 && file_exists(\OC::$SERVERROOT . '/core/img/' . $image)) {
408
-			$route = $this->urlGenerator->linkToRoute('theming.Icon.getThemedIcon', ['app' => $app, 'image' => $image]);
409
-		}
410
-
411
-		if ($route) {
412
-			return $route . '?v=' . $this->util->getCacheBuster();
413
-		}
414
-
415
-		return false;
416
-	}
417
-
418
-	protected function getCustomFavicon(): ?ISimpleFile {
419
-		try {
420
-			return $this->imageManager->getImage('favicon');
421
-		} catch (NotFoundException $e) {
422
-			return null;
423
-		}
424
-	}
425
-
426
-	/**
427
-	 * Increases the cache buster key
428
-	 */
429
-	public function increaseCacheBuster(): void {
430
-		$cacheBusterKey = (int)$this->config->getAppValue('theming', 'cachebuster', '0');
431
-		$this->config->setAppValue('theming', 'cachebuster', (string)($cacheBusterKey + 1));
432
-		$this->cacheFactory->createDistributed('theming-')->clear();
433
-		$this->cacheFactory->createDistributed('imagePath')->clear();
434
-	}
435
-
436
-	/**
437
-	 * Update setting in the database
438
-	 *
439
-	 * @param string $setting
440
-	 * @param string $value
441
-	 */
442
-	public function set($setting, $value): void {
443
-		$this->config->setAppValue('theming', $setting, $value);
444
-		$this->increaseCacheBuster();
445
-	}
446
-
447
-	/**
448
-	 * Revert all settings to the default value
449
-	 */
450
-	public function undoAll(): void {
451
-		$this->config->deleteAppValues('theming');
452
-		$this->increaseCacheBuster();
453
-	}
454
-
455
-	/**
456
-	 * Revert settings to the default value
457
-	 *
458
-	 * @param string $setting setting which should be reverted
459
-	 * @return string default value
460
-	 */
461
-	public function undo($setting): string {
462
-		$this->config->deleteAppValue('theming', $setting);
463
-		$this->increaseCacheBuster();
464
-
465
-		$returnValue = '';
466
-		switch ($setting) {
467
-			case 'name':
468
-				$returnValue = $this->getEntity();
469
-				break;
470
-			case 'url':
471
-				$returnValue = $this->getBaseUrl();
472
-				break;
473
-			case 'slogan':
474
-				$returnValue = $this->getSlogan();
475
-				break;
476
-			case 'color':
477
-				$returnValue = $this->getDefaultColorPrimary();
478
-				break;
479
-			case 'logo':
480
-			case 'logoheader':
481
-			case 'background':
482
-			case 'favicon':
483
-				$this->imageManager->delete($setting);
484
-				break;
485
-		}
486
-
487
-		return $returnValue;
488
-	}
489
-
490
-	/**
491
-	 * Color of text in the header and primary buttons
492
-	 *
493
-	 * @return string
494
-	 */
495
-	public function getTextColorPrimary() {
496
-		return $this->util->invertTextColor($this->getColorPrimary()) ? '#000000' : '#ffffff';
497
-	}
498
-
499
-	/**
500
-	 * Has the admin disabled user customization
501
-	 */
502
-	public function isUserThemingDisabled(): bool {
503
-		return $this->config->getAppValue('theming', 'disable-user-theming', 'no') === 'yes';
504
-	}
58
+    private IConfig $config;
59
+    private IL10N $l;
60
+    private ImageManager $imageManager;
61
+    private IUserSession $userSession;
62
+    private IURLGenerator $urlGenerator;
63
+    private ICacheFactory $cacheFactory;
64
+    private Util $util;
65
+    private IAppManager $appManager;
66
+    private INavigationManager $navigationManager;
67
+
68
+    private string $name;
69
+    private string $title;
70
+    private string $entity;
71
+    private string $productName;
72
+    private string $url;
73
+    private string $color;
74
+
75
+    private string $iTunesAppId;
76
+    private string $iOSClientUrl;
77
+    private string $AndroidClientUrl;
78
+    private string $FDroidClientUrl;
79
+
80
+    /**
81
+     * ThemingDefaults constructor.
82
+     *
83
+     * @param IConfig $config
84
+     * @param IL10N $l
85
+     * @param ImageManager $imageManager
86
+     * @param IUserSession $userSession
87
+     * @param IURLGenerator $urlGenerator
88
+     * @param ICacheFactory $cacheFactory
89
+     * @param Util $util
90
+     * @param IAppManager $appManager
91
+     */
92
+    public function __construct(IConfig $config,
93
+                                IL10N $l,
94
+                                IUserSession $userSession,
95
+                                IURLGenerator $urlGenerator,
96
+                                ICacheFactory $cacheFactory,
97
+                                Util $util,
98
+                                ImageManager $imageManager,
99
+                                IAppManager $appManager,
100
+                                INavigationManager $navigationManager
101
+    ) {
102
+        parent::__construct();
103
+        $this->config = $config;
104
+        $this->l = $l;
105
+        $this->imageManager = $imageManager;
106
+        $this->userSession = $userSession;
107
+        $this->urlGenerator = $urlGenerator;
108
+        $this->cacheFactory = $cacheFactory;
109
+        $this->util = $util;
110
+        $this->appManager = $appManager;
111
+        $this->navigationManager = $navigationManager;
112
+
113
+        $this->name = parent::getName();
114
+        $this->title = parent::getTitle();
115
+        $this->entity = parent::getEntity();
116
+        $this->productName = parent::getProductName();
117
+        $this->url = parent::getBaseUrl();
118
+        $this->color = parent::getColorPrimary();
119
+        $this->iTunesAppId = parent::getiTunesAppId();
120
+        $this->iOSClientUrl = parent::getiOSClientUrl();
121
+        $this->AndroidClientUrl = parent::getAndroidClientUrl();
122
+        $this->FDroidClientUrl = parent::getFDroidClientUrl();
123
+    }
124
+
125
+    public function getName() {
126
+        return strip_tags($this->config->getAppValue('theming', 'name', $this->name));
127
+    }
128
+
129
+    public function getHTMLName() {
130
+        return $this->config->getAppValue('theming', 'name', $this->name);
131
+    }
132
+
133
+    public function getTitle() {
134
+        return strip_tags($this->config->getAppValue('theming', 'name', $this->title));
135
+    }
136
+
137
+    public function getEntity() {
138
+        return strip_tags($this->config->getAppValue('theming', 'name', $this->entity));
139
+    }
140
+
141
+    public function getProductName() {
142
+        return strip_tags($this->config->getAppValue('theming', 'productName', $this->productName));
143
+    }
144
+
145
+    public function getBaseUrl() {
146
+        return $this->config->getAppValue('theming', 'url', $this->url);
147
+    }
148
+
149
+    /**
150
+     * We pass a string and sanitizeHTML will return a string too in that case
151
+     * @psalm-suppress InvalidReturnStatement
152
+     * @psalm-suppress InvalidReturnType
153
+     */
154
+    public function getSlogan(?string $lang = null) {
155
+        return \OCP\Util::sanitizeHTML($this->config->getAppValue('theming', 'slogan', parent::getSlogan($lang)));
156
+    }
157
+
158
+    public function getImprintUrl() {
159
+        return (string)$this->config->getAppValue('theming', 'imprintUrl', '');
160
+    }
161
+
162
+    public function getPrivacyUrl() {
163
+        return (string)$this->config->getAppValue('theming', 'privacyUrl', '');
164
+    }
165
+
166
+    public function getShortFooter() {
167
+        $slogan = $this->getSlogan();
168
+        $baseUrl = $this->getBaseUrl();
169
+        if ($baseUrl !== '') {
170
+            $footer = '<a href="' . $baseUrl . '" target="_blank"' .
171
+                ' rel="noreferrer noopener" class="entity-name">' . $this->getEntity() . '</a>';
172
+        } else {
173
+            $footer = '<span class="entity-name">' .$this->getEntity() . '</span>';
174
+        }
175
+        $footer .= ($slogan !== '' ? ' – ' . $slogan : '');
176
+
177
+        $links = [
178
+            [
179
+                'text' => $this->l->t('Legal notice'),
180
+                'url' => (string)$this->getImprintUrl()
181
+            ],
182
+            [
183
+                'text' => $this->l->t('Privacy policy'),
184
+                'url' => (string)$this->getPrivacyUrl()
185
+            ],
186
+        ];
187
+
188
+        $navigation = $this->navigationManager->getAll(INavigationManager::TYPE_GUEST);
189
+        $guestNavigation = array_map(function ($nav) {
190
+            return [
191
+                'text' => $nav['name'],
192
+                'url' => $nav['href']
193
+            ];
194
+        }, $navigation);
195
+        $links = array_merge($links, $guestNavigation);
196
+
197
+        $legalLinks = '';
198
+        $divider = '';
199
+        foreach ($links as $link) {
200
+            if ($link['url'] !== ''
201
+                && filter_var($link['url'], FILTER_VALIDATE_URL)
202
+            ) {
203
+                $legalLinks .= $divider . '<a href="' . $link['url'] . '" class="legal" target="_blank"' .
204
+                    ' rel="noreferrer noopener">' . $link['text'] . '</a>';
205
+                $divider = ' · ';
206
+            }
207
+        }
208
+        if ($legalLinks !== '') {
209
+            $footer .= '<br/>' . $legalLinks;
210
+        }
211
+
212
+        return $footer;
213
+    }
214
+
215
+    /**
216
+     * Color that is used for the header as well as for mail headers
217
+     */
218
+    public function getColorPrimary(): string {
219
+        $user = $this->userSession->getUser();
220
+
221
+        // admin-defined primary color
222
+        $defaultColor = $this->getDefaultColorPrimary();
223
+
224
+        if ($this->isUserThemingDisabled()) {
225
+            return $defaultColor;
226
+        }
227
+
228
+        // user-defined primary color
229
+        if (!empty($user)) {
230
+            $themingBackgroundColor = $this->config->getUserValue($user->getUID(), Application::APP_ID, 'background_color', '');
231
+            // If the user selected a specific colour
232
+            if (preg_match('/^\#([0-9a-f]{3}|[0-9a-f]{6})$/i', $themingBackgroundColor)) {
233
+                return $themingBackgroundColor;
234
+            }
235
+        }
236
+
237
+        // If the default color is not valid, return the default background one
238
+        if (!preg_match('/^\#([0-9a-f]{3}|[0-9a-f]{6})$/i', $defaultColor)) {
239
+            return BackgroundService::DEFAULT_COLOR;
240
+        }
241
+
242
+        // Finally, return the system global primary color
243
+        return $defaultColor;
244
+    }
245
+
246
+    /**
247
+     * Return the default color primary
248
+     */
249
+    public function getDefaultColorPrimary(): string {
250
+        $color = $this->config->getAppValue(Application::APP_ID, 'color', '');
251
+        if (!preg_match('/^\#([0-9a-f]{3}|[0-9a-f]{6})$/i', $color)) {
252
+            $color = '#0082c9';
253
+        }
254
+        return $color;
255
+    }
256
+
257
+    /**
258
+     * Themed logo url
259
+     *
260
+     * @param bool $useSvg Whether to point to the SVG image or a fallback
261
+     * @return string
262
+     */
263
+    public function getLogo($useSvg = true): string {
264
+        $logo = $this->config->getAppValue('theming', 'logoMime', '');
265
+
266
+        // short cut to avoid setting up the filesystem just to check if the logo is there
267
+        //
268
+        // explanation: if an SVG is requested and the app config value for logoMime is set then the logo is there.
269
+        // otherwise we need to check it and maybe also generate a PNG from the SVG (that's done in getImage() which
270
+        // needs to be called then)
271
+        if ($useSvg === true && $logo !== false) {
272
+            $logoExists = true;
273
+        } else {
274
+            try {
275
+                $this->imageManager->getImage('logo', $useSvg);
276
+                $logoExists = true;
277
+            } catch (\Exception $e) {
278
+                $logoExists = false;
279
+            }
280
+        }
281
+
282
+        $cacheBusterCounter = $this->config->getAppValue('theming', 'cachebuster', '0');
283
+
284
+        if (!$logo || !$logoExists) {
285
+            if ($useSvg) {
286
+                $logo = $this->urlGenerator->imagePath('core', 'logo/logo.svg');
287
+            } else {
288
+                $logo = $this->urlGenerator->imagePath('core', 'logo/logo.png');
289
+            }
290
+            return $logo . '?v=' . $cacheBusterCounter;
291
+        }
292
+
293
+        return $this->urlGenerator->linkToRoute('theming.Theming.getImage', [ 'key' => 'logo', 'useSvg' => $useSvg, 'v' => $cacheBusterCounter ]);
294
+    }
295
+
296
+    /**
297
+     * Themed background image url
298
+     *
299
+     * @return string
300
+     */
301
+    public function getBackground(): string {
302
+        return $this->imageManager->getImageUrl('background');
303
+    }
304
+
305
+    /**
306
+     * @return string
307
+     */
308
+    public function getiTunesAppId() {
309
+        return $this->config->getAppValue('theming', 'iTunesAppId', $this->iTunesAppId);
310
+    }
311
+
312
+    /**
313
+     * @return string
314
+     */
315
+    public function getiOSClientUrl() {
316
+        return $this->config->getAppValue('theming', 'iOSClientUrl', $this->iOSClientUrl);
317
+    }
318
+
319
+    /**
320
+     * @return string
321
+     */
322
+    public function getAndroidClientUrl() {
323
+        return $this->config->getAppValue('theming', 'AndroidClientUrl', $this->AndroidClientUrl);
324
+    }
325
+
326
+    /**
327
+     * @return string
328
+     */
329
+    public function getFDroidClientUrl() {
330
+        return $this->config->getAppValue('theming', 'FDroidClientUrl', $this->FDroidClientUrl);
331
+    }
332
+
333
+    /**
334
+     * @return array scss variables to overwrite
335
+     */
336
+    public function getScssVariables() {
337
+        $cacheBuster = $this->config->getAppValue('theming', 'cachebuster', '0');
338
+        $cache = $this->cacheFactory->createDistributed('theming-' . $cacheBuster . '-' . $this->urlGenerator->getBaseUrl());
339
+        if ($value = $cache->get('getScssVariables')) {
340
+            return $value;
341
+        }
342
+
343
+        $variables = [
344
+            'theming-cachebuster' => "'" . $cacheBuster . "'",
345
+            'theming-logo-mime' => "'" . $this->config->getAppValue('theming', 'logoMime') . "'",
346
+            'theming-background-mime' => "'" . $this->config->getAppValue('theming', 'backgroundMime') . "'",
347
+            'theming-logoheader-mime' => "'" . $this->config->getAppValue('theming', 'logoheaderMime') . "'",
348
+            'theming-favicon-mime' => "'" . $this->config->getAppValue('theming', 'faviconMime') . "'"
349
+        ];
350
+
351
+        $variables['image-logo'] = "url('".$this->imageManager->getImageUrl('logo')."')";
352
+        $variables['image-logoheader'] = "url('".$this->imageManager->getImageUrl('logoheader')."')";
353
+        $variables['image-favicon'] = "url('".$this->imageManager->getImageUrl('favicon')."')";
354
+        $variables['image-login-background'] = "url('".$this->imageManager->getImageUrl('background')."')";
355
+        $variables['image-login-plain'] = 'false';
356
+
357
+        if ($this->config->getAppValue('theming', 'color', '') !== '') {
358
+            $variables['color-primary'] = $this->getColorPrimary();
359
+            $variables['color-primary-text'] = $this->getTextColorPrimary();
360
+            $variables['color-primary-element'] = $this->util->elementColor($this->getColorPrimary());
361
+        }
362
+
363
+        if ($this->config->getAppValue('theming', 'backgroundMime', '') === 'backgroundColor') {
364
+            $variables['image-login-plain'] = 'true';
365
+        }
366
+
367
+        $variables['has-legal-links'] = 'false';
368
+        if ($this->getImprintUrl() !== '' || $this->getPrivacyUrl() !== '') {
369
+            $variables['has-legal-links'] = 'true';
370
+        }
371
+
372
+        $cache->set('getScssVariables', $variables);
373
+        return $variables;
374
+    }
375
+
376
+    /**
377
+     * Check if the image should be replaced by the theming app
378
+     * and return the new image location then
379
+     *
380
+     * @param string $app name of the app
381
+     * @param string $image filename of the image
382
+     * @return bool|string false if image should not replaced, otherwise the location of the image
383
+     */
384
+    public function replaceImagePath($app, $image) {
385
+        if ($app === '' || $app === 'files_sharing') {
386
+            $app = 'core';
387
+        }
388
+        $cacheBusterValue = $this->config->getAppValue('theming', 'cachebuster', '0');
389
+
390
+        $route = false;
391
+        if ($image === 'favicon.ico' && ($this->imageManager->shouldReplaceIcons() || $this->getCustomFavicon() !== null)) {
392
+            $route = $this->urlGenerator->linkToRoute('theming.Icon.getFavicon', ['app' => $app]);
393
+        }
394
+        if (($image === 'favicon-touch.png' || $image === 'favicon-fb.png') && ($this->imageManager->shouldReplaceIcons() || $this->getCustomFavicon() !== null)) {
395
+            $route = $this->urlGenerator->linkToRoute('theming.Icon.getTouchIcon', ['app' => $app]);
396
+        }
397
+        if ($image === 'manifest.json') {
398
+            try {
399
+                $appPath = $this->appManager->getAppPath($app);
400
+                if (file_exists($appPath . '/img/manifest.json')) {
401
+                    return false;
402
+                }
403
+            } catch (AppPathNotFoundException $e) {
404
+            }
405
+            $route = $this->urlGenerator->linkToRoute('theming.Theming.getManifest', ['app' => $app ]);
406
+        }
407
+        if (strpos($image, 'filetypes/') === 0 && file_exists(\OC::$SERVERROOT . '/core/img/' . $image)) {
408
+            $route = $this->urlGenerator->linkToRoute('theming.Icon.getThemedIcon', ['app' => $app, 'image' => $image]);
409
+        }
410
+
411
+        if ($route) {
412
+            return $route . '?v=' . $this->util->getCacheBuster();
413
+        }
414
+
415
+        return false;
416
+    }
417
+
418
+    protected function getCustomFavicon(): ?ISimpleFile {
419
+        try {
420
+            return $this->imageManager->getImage('favicon');
421
+        } catch (NotFoundException $e) {
422
+            return null;
423
+        }
424
+    }
425
+
426
+    /**
427
+     * Increases the cache buster key
428
+     */
429
+    public function increaseCacheBuster(): void {
430
+        $cacheBusterKey = (int)$this->config->getAppValue('theming', 'cachebuster', '0');
431
+        $this->config->setAppValue('theming', 'cachebuster', (string)($cacheBusterKey + 1));
432
+        $this->cacheFactory->createDistributed('theming-')->clear();
433
+        $this->cacheFactory->createDistributed('imagePath')->clear();
434
+    }
435
+
436
+    /**
437
+     * Update setting in the database
438
+     *
439
+     * @param string $setting
440
+     * @param string $value
441
+     */
442
+    public function set($setting, $value): void {
443
+        $this->config->setAppValue('theming', $setting, $value);
444
+        $this->increaseCacheBuster();
445
+    }
446
+
447
+    /**
448
+     * Revert all settings to the default value
449
+     */
450
+    public function undoAll(): void {
451
+        $this->config->deleteAppValues('theming');
452
+        $this->increaseCacheBuster();
453
+    }
454
+
455
+    /**
456
+     * Revert settings to the default value
457
+     *
458
+     * @param string $setting setting which should be reverted
459
+     * @return string default value
460
+     */
461
+    public function undo($setting): string {
462
+        $this->config->deleteAppValue('theming', $setting);
463
+        $this->increaseCacheBuster();
464
+
465
+        $returnValue = '';
466
+        switch ($setting) {
467
+            case 'name':
468
+                $returnValue = $this->getEntity();
469
+                break;
470
+            case 'url':
471
+                $returnValue = $this->getBaseUrl();
472
+                break;
473
+            case 'slogan':
474
+                $returnValue = $this->getSlogan();
475
+                break;
476
+            case 'color':
477
+                $returnValue = $this->getDefaultColorPrimary();
478
+                break;
479
+            case 'logo':
480
+            case 'logoheader':
481
+            case 'background':
482
+            case 'favicon':
483
+                $this->imageManager->delete($setting);
484
+                break;
485
+        }
486
+
487
+        return $returnValue;
488
+    }
489
+
490
+    /**
491
+     * Color of text in the header and primary buttons
492
+     *
493
+     * @return string
494
+     */
495
+    public function getTextColorPrimary() {
496
+        return $this->util->invertTextColor($this->getColorPrimary()) ? '#000000' : '#ffffff';
497
+    }
498
+
499
+    /**
500
+     * Has the admin disabled user customization
501
+     */
502
+    public function isUserThemingDisabled(): bool {
503
+        return $this->config->getAppValue('theming', 'disable-user-theming', 'no') === 'yes';
504
+    }
505 505
 }
Please login to merge, or discard this patch.
apps/theming/lib/Controller/ThemingController.php 1 patch
Indentation   +334 added lines, -334 removed lines patch added patch discarded remove patch
@@ -65,361 +65,361 @@
 block discarded – undo
65 65
  * @package OCA\Theming\Controller
66 66
  */
67 67
 class ThemingController extends Controller {
68
-	private ThemingDefaults $themingDefaults;
69
-	private IL10N $l10n;
70
-	private IConfig $config;
71
-	private ITempManager $tempManager;
72
-	private IAppData $appData;
73
-	private IURLGenerator $urlGenerator;
74
-	private IAppManager $appManager;
75
-	private ImageManager $imageManager;
76
-	private ThemesService $themesService;
68
+    private ThemingDefaults $themingDefaults;
69
+    private IL10N $l10n;
70
+    private IConfig $config;
71
+    private ITempManager $tempManager;
72
+    private IAppData $appData;
73
+    private IURLGenerator $urlGenerator;
74
+    private IAppManager $appManager;
75
+    private ImageManager $imageManager;
76
+    private ThemesService $themesService;
77 77
 
78
-	public function __construct(
79
-		$appName,
80
-		IRequest $request,
81
-		IConfig $config,
82
-		ThemingDefaults $themingDefaults,
83
-		IL10N $l,
84
-		ITempManager $tempManager,
85
-		IAppData $appData,
86
-		IURLGenerator $urlGenerator,
87
-		IAppManager $appManager,
88
-		ImageManager $imageManager,
89
-		ThemesService $themesService
90
-	) {
91
-		parent::__construct($appName, $request);
78
+    public function __construct(
79
+        $appName,
80
+        IRequest $request,
81
+        IConfig $config,
82
+        ThemingDefaults $themingDefaults,
83
+        IL10N $l,
84
+        ITempManager $tempManager,
85
+        IAppData $appData,
86
+        IURLGenerator $urlGenerator,
87
+        IAppManager $appManager,
88
+        ImageManager $imageManager,
89
+        ThemesService $themesService
90
+    ) {
91
+        parent::__construct($appName, $request);
92 92
 
93
-		$this->themingDefaults = $themingDefaults;
94
-		$this->l10n = $l;
95
-		$this->config = $config;
96
-		$this->tempManager = $tempManager;
97
-		$this->appData = $appData;
98
-		$this->urlGenerator = $urlGenerator;
99
-		$this->appManager = $appManager;
100
-		$this->imageManager = $imageManager;
101
-		$this->themesService = $themesService;
102
-	}
93
+        $this->themingDefaults = $themingDefaults;
94
+        $this->l10n = $l;
95
+        $this->config = $config;
96
+        $this->tempManager = $tempManager;
97
+        $this->appData = $appData;
98
+        $this->urlGenerator = $urlGenerator;
99
+        $this->appManager = $appManager;
100
+        $this->imageManager = $imageManager;
101
+        $this->themesService = $themesService;
102
+    }
103 103
 
104
-	/**
105
-	 * @AuthorizedAdminSetting(settings=OCA\Theming\Settings\Admin)
106
-	 * @param string $setting
107
-	 * @param string $value
108
-	 * @return DataResponse
109
-	 * @throws NotPermittedException
110
-	 */
111
-	public function updateStylesheet($setting, $value) {
112
-		$value = trim($value);
113
-		$error = null;
114
-		switch ($setting) {
115
-			case 'name':
116
-				if (strlen($value) > 250) {
117
-					$error = $this->l10n->t('The given name is too long');
118
-				}
119
-				break;
120
-			case 'url':
121
-				if (strlen($value) > 500) {
122
-					$error = $this->l10n->t('The given web address is too long');
123
-				}
124
-				if (!$this->isValidUrl($value)) {
125
-					$error = $this->l10n->t('The given web address is not a valid URL');
126
-				}
127
-				break;
128
-			case 'imprintUrl':
129
-				if (strlen($value) > 500) {
130
-					$error = $this->l10n->t('The given legal notice address is too long');
131
-				}
132
-				if (!$this->isValidUrl($value)) {
133
-					$error = $this->l10n->t('The given legal notice address is not a valid URL');
134
-				}
135
-				break;
136
-			case 'privacyUrl':
137
-				if (strlen($value) > 500) {
138
-					$error = $this->l10n->t('The given privacy policy address is too long');
139
-				}
140
-				if (!$this->isValidUrl($value)) {
141
-					$error = $this->l10n->t('The given privacy policy address is not a valid URL');
142
-				}
143
-				break;
144
-			case 'slogan':
145
-				if (strlen($value) > 500) {
146
-					$error = $this->l10n->t('The given slogan is too long');
147
-				}
148
-				break;
149
-			case 'color':
150
-				if (!preg_match('/^\#([0-9a-f]{3}|[0-9a-f]{6})$/i', $value)) {
151
-					$error = $this->l10n->t('The given color is invalid');
152
-				}
153
-				break;
154
-			case 'disable-user-theming':
155
-				if ($value !== "yes" && $value !== "no") {
156
-					$error = $this->l10n->t('Disable-user-theming should be true or false');
157
-				}
158
-				break;
159
-		}
160
-		if ($error !== null) {
161
-			return new DataResponse([
162
-				'data' => [
163
-					'message' => $error,
164
-				],
165
-				'status' => 'error'
166
-			], Http::STATUS_BAD_REQUEST);
167
-		}
104
+    /**
105
+     * @AuthorizedAdminSetting(settings=OCA\Theming\Settings\Admin)
106
+     * @param string $setting
107
+     * @param string $value
108
+     * @return DataResponse
109
+     * @throws NotPermittedException
110
+     */
111
+    public function updateStylesheet($setting, $value) {
112
+        $value = trim($value);
113
+        $error = null;
114
+        switch ($setting) {
115
+            case 'name':
116
+                if (strlen($value) > 250) {
117
+                    $error = $this->l10n->t('The given name is too long');
118
+                }
119
+                break;
120
+            case 'url':
121
+                if (strlen($value) > 500) {
122
+                    $error = $this->l10n->t('The given web address is too long');
123
+                }
124
+                if (!$this->isValidUrl($value)) {
125
+                    $error = $this->l10n->t('The given web address is not a valid URL');
126
+                }
127
+                break;
128
+            case 'imprintUrl':
129
+                if (strlen($value) > 500) {
130
+                    $error = $this->l10n->t('The given legal notice address is too long');
131
+                }
132
+                if (!$this->isValidUrl($value)) {
133
+                    $error = $this->l10n->t('The given legal notice address is not a valid URL');
134
+                }
135
+                break;
136
+            case 'privacyUrl':
137
+                if (strlen($value) > 500) {
138
+                    $error = $this->l10n->t('The given privacy policy address is too long');
139
+                }
140
+                if (!$this->isValidUrl($value)) {
141
+                    $error = $this->l10n->t('The given privacy policy address is not a valid URL');
142
+                }
143
+                break;
144
+            case 'slogan':
145
+                if (strlen($value) > 500) {
146
+                    $error = $this->l10n->t('The given slogan is too long');
147
+                }
148
+                break;
149
+            case 'color':
150
+                if (!preg_match('/^\#([0-9a-f]{3}|[0-9a-f]{6})$/i', $value)) {
151
+                    $error = $this->l10n->t('The given color is invalid');
152
+                }
153
+                break;
154
+            case 'disable-user-theming':
155
+                if ($value !== "yes" && $value !== "no") {
156
+                    $error = $this->l10n->t('Disable-user-theming should be true or false');
157
+                }
158
+                break;
159
+        }
160
+        if ($error !== null) {
161
+            return new DataResponse([
162
+                'data' => [
163
+                    'message' => $error,
164
+                ],
165
+                'status' => 'error'
166
+            ], Http::STATUS_BAD_REQUEST);
167
+        }
168 168
 
169
-		$this->themingDefaults->set($setting, $value);
169
+        $this->themingDefaults->set($setting, $value);
170 170
 
171
-		return new DataResponse([
172
-			'data' => [
173
-				'message' => $this->l10n->t('Saved'),
174
-			],
175
-			'status' => 'success'
176
-		]);
177
-	}
171
+        return new DataResponse([
172
+            'data' => [
173
+                'message' => $this->l10n->t('Saved'),
174
+            ],
175
+            'status' => 'success'
176
+        ]);
177
+    }
178 178
 
179
-	/**
180
-	 * Check that a string is a valid http/https url
181
-	 */
182
-	private function isValidUrl(string $url): bool {
183
-		return ((strpos($url, 'http://') === 0 || strpos($url, 'https://') === 0) &&
184
-			filter_var($url, FILTER_VALIDATE_URL) !== false);
185
-	}
179
+    /**
180
+     * Check that a string is a valid http/https url
181
+     */
182
+    private function isValidUrl(string $url): bool {
183
+        return ((strpos($url, 'http://') === 0 || strpos($url, 'https://') === 0) &&
184
+            filter_var($url, FILTER_VALIDATE_URL) !== false);
185
+    }
186 186
 
187
-	/**
188
-	 * @AuthorizedAdminSetting(settings=OCA\Theming\Settings\Admin)
189
-	 * @return DataResponse
190
-	 * @throws NotPermittedException
191
-	 */
192
-	public function uploadImage(): DataResponse {
193
-		$key = $this->request->getParam('key');
194
-		$image = $this->request->getUploadedFile('image');
195
-		$error = null;
196
-		$phpFileUploadErrors = [
197
-			UPLOAD_ERR_OK => $this->l10n->t('The file was uploaded'),
198
-			UPLOAD_ERR_INI_SIZE => $this->l10n->t('The uploaded file exceeds the upload_max_filesize directive in php.ini'),
199
-			UPLOAD_ERR_FORM_SIZE => $this->l10n->t('The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form'),
200
-			UPLOAD_ERR_PARTIAL => $this->l10n->t('The file was only partially uploaded'),
201
-			UPLOAD_ERR_NO_FILE => $this->l10n->t('No file was uploaded'),
202
-			UPLOAD_ERR_NO_TMP_DIR => $this->l10n->t('Missing a temporary folder'),
203
-			UPLOAD_ERR_CANT_WRITE => $this->l10n->t('Could not write file to disk'),
204
-			UPLOAD_ERR_EXTENSION => $this->l10n->t('A PHP extension stopped the file upload'),
205
-		];
206
-		if (empty($image)) {
207
-			$error = $this->l10n->t('No file uploaded');
208
-		}
209
-		if (!empty($image) && array_key_exists('error', $image) && $image['error'] !== UPLOAD_ERR_OK) {
210
-			$error = $phpFileUploadErrors[$image['error']];
211
-		}
187
+    /**
188
+     * @AuthorizedAdminSetting(settings=OCA\Theming\Settings\Admin)
189
+     * @return DataResponse
190
+     * @throws NotPermittedException
191
+     */
192
+    public function uploadImage(): DataResponse {
193
+        $key = $this->request->getParam('key');
194
+        $image = $this->request->getUploadedFile('image');
195
+        $error = null;
196
+        $phpFileUploadErrors = [
197
+            UPLOAD_ERR_OK => $this->l10n->t('The file was uploaded'),
198
+            UPLOAD_ERR_INI_SIZE => $this->l10n->t('The uploaded file exceeds the upload_max_filesize directive in php.ini'),
199
+            UPLOAD_ERR_FORM_SIZE => $this->l10n->t('The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form'),
200
+            UPLOAD_ERR_PARTIAL => $this->l10n->t('The file was only partially uploaded'),
201
+            UPLOAD_ERR_NO_FILE => $this->l10n->t('No file was uploaded'),
202
+            UPLOAD_ERR_NO_TMP_DIR => $this->l10n->t('Missing a temporary folder'),
203
+            UPLOAD_ERR_CANT_WRITE => $this->l10n->t('Could not write file to disk'),
204
+            UPLOAD_ERR_EXTENSION => $this->l10n->t('A PHP extension stopped the file upload'),
205
+        ];
206
+        if (empty($image)) {
207
+            $error = $this->l10n->t('No file uploaded');
208
+        }
209
+        if (!empty($image) && array_key_exists('error', $image) && $image['error'] !== UPLOAD_ERR_OK) {
210
+            $error = $phpFileUploadErrors[$image['error']];
211
+        }
212 212
 
213
-		if ($error !== null) {
214
-			return new DataResponse(
215
-				[
216
-					'data' => [
217
-						'message' => $error
218
-					],
219
-					'status' => 'failure',
220
-				],
221
-				Http::STATUS_UNPROCESSABLE_ENTITY
222
-			);
223
-		}
213
+        if ($error !== null) {
214
+            return new DataResponse(
215
+                [
216
+                    'data' => [
217
+                        'message' => $error
218
+                    ],
219
+                    'status' => 'failure',
220
+                ],
221
+                Http::STATUS_UNPROCESSABLE_ENTITY
222
+            );
223
+        }
224 224
 
225
-		try {
226
-			$mime = $this->imageManager->updateImage($key, $image['tmp_name']);
227
-			$this->themingDefaults->set($key . 'Mime', $mime);
228
-		} catch (\Exception $e) {
229
-			return new DataResponse(
230
-				[
231
-					'data' => [
232
-						'message' => $e->getMessage()
233
-					],
234
-					'status' => 'failure',
235
-				],
236
-				Http::STATUS_UNPROCESSABLE_ENTITY
237
-			);
238
-		}
225
+        try {
226
+            $mime = $this->imageManager->updateImage($key, $image['tmp_name']);
227
+            $this->themingDefaults->set($key . 'Mime', $mime);
228
+        } catch (\Exception $e) {
229
+            return new DataResponse(
230
+                [
231
+                    'data' => [
232
+                        'message' => $e->getMessage()
233
+                    ],
234
+                    'status' => 'failure',
235
+                ],
236
+                Http::STATUS_UNPROCESSABLE_ENTITY
237
+            );
238
+        }
239 239
 
240
-		$name = $image['name'];
240
+        $name = $image['name'];
241 241
 
242
-		return new DataResponse(
243
-			[
244
-				'data' =>
245
-					[
246
-						'name' => $name,
247
-						'url' => $this->imageManager->getImageUrl($key),
248
-						'message' => $this->l10n->t('Saved'),
249
-					],
250
-				'status' => 'success'
251
-			]
252
-		);
253
-	}
242
+        return new DataResponse(
243
+            [
244
+                'data' =>
245
+                    [
246
+                        'name' => $name,
247
+                        'url' => $this->imageManager->getImageUrl($key),
248
+                        'message' => $this->l10n->t('Saved'),
249
+                    ],
250
+                'status' => 'success'
251
+            ]
252
+        );
253
+    }
254 254
 
255
-	/**
256
-	 * Revert setting to default value
257
-	 * @AuthorizedAdminSetting(settings=OCA\Theming\Settings\Admin)
258
-	 *
259
-	 * @param string $setting setting which should be reverted
260
-	 * @return DataResponse
261
-	 * @throws NotPermittedException
262
-	 */
263
-	public function undo(string $setting): DataResponse {
264
-		$value = $this->themingDefaults->undo($setting);
255
+    /**
256
+     * Revert setting to default value
257
+     * @AuthorizedAdminSetting(settings=OCA\Theming\Settings\Admin)
258
+     *
259
+     * @param string $setting setting which should be reverted
260
+     * @return DataResponse
261
+     * @throws NotPermittedException
262
+     */
263
+    public function undo(string $setting): DataResponse {
264
+        $value = $this->themingDefaults->undo($setting);
265 265
 
266
-		return new DataResponse(
267
-			[
268
-				'data' =>
269
-					[
270
-						'value' => $value,
271
-						'message' => $this->l10n->t('Saved'),
272
-					],
273
-				'status' => 'success'
274
-			]
275
-		);
276
-	}
266
+        return new DataResponse(
267
+            [
268
+                'data' =>
269
+                    [
270
+                        'value' => $value,
271
+                        'message' => $this->l10n->t('Saved'),
272
+                    ],
273
+                'status' => 'success'
274
+            ]
275
+        );
276
+    }
277 277
 
278
-	/**
279
-	 * Revert all theming settings to their default values
280
-	 * @AuthorizedAdminSetting(settings=OCA\Theming\Settings\Admin)
281
-	 *
282
-	 * @return DataResponse
283
-	 * @throws NotPermittedException
284
-	 */
285
-	public function undoAll(): DataResponse {
286
-		$this->themingDefaults->undoAll();
278
+    /**
279
+     * Revert all theming settings to their default values
280
+     * @AuthorizedAdminSetting(settings=OCA\Theming\Settings\Admin)
281
+     *
282
+     * @return DataResponse
283
+     * @throws NotPermittedException
284
+     */
285
+    public function undoAll(): DataResponse {
286
+        $this->themingDefaults->undoAll();
287 287
 
288
-		return new DataResponse(
289
-			[
290
-				'data' =>
291
-					[
292
-						'message' => $this->l10n->t('Saved'),
293
-					],
294
-				'status' => 'success'
295
-			]
296
-		);
297
-	}
288
+        return new DataResponse(
289
+            [
290
+                'data' =>
291
+                    [
292
+                        'message' => $this->l10n->t('Saved'),
293
+                    ],
294
+                'status' => 'success'
295
+            ]
296
+        );
297
+    }
298 298
 
299
-	/**
300
-	 * @PublicPage
301
-	 * @NoCSRFRequired
302
-	 * @NoSameSiteCookieRequired
303
-	 *
304
-	 * @param string $key
305
-	 * @param bool $useSvg
306
-	 * @return FileDisplayResponse|NotFoundResponse
307
-	 * @throws NotPermittedException
308
-	 */
309
-	public function getImage(string $key, bool $useSvg = true) {
310
-		try {
311
-			$file = $this->imageManager->getImage($key, $useSvg);
312
-		} catch (NotFoundException $e) {
313
-			return new NotFoundResponse();
314
-		}
299
+    /**
300
+     * @PublicPage
301
+     * @NoCSRFRequired
302
+     * @NoSameSiteCookieRequired
303
+     *
304
+     * @param string $key
305
+     * @param bool $useSvg
306
+     * @return FileDisplayResponse|NotFoundResponse
307
+     * @throws NotPermittedException
308
+     */
309
+    public function getImage(string $key, bool $useSvg = true) {
310
+        try {
311
+            $file = $this->imageManager->getImage($key, $useSvg);
312
+        } catch (NotFoundException $e) {
313
+            return new NotFoundResponse();
314
+        }
315 315
 
316
-		$response = new FileDisplayResponse($file);
317
-		$csp = new Http\ContentSecurityPolicy();
318
-		$csp->allowInlineStyle();
319
-		$response->setContentSecurityPolicy($csp);
320
-		$response->cacheFor(3600);
321
-		$response->addHeader('Content-Type', $this->config->getAppValue($this->appName, $key . 'Mime', ''));
322
-		$response->addHeader('Content-Disposition', 'attachment; filename="' . $key . '"');
323
-		if (!$useSvg) {
324
-			$response->addHeader('Content-Type', 'image/png');
325
-		} else {
326
-			$response->addHeader('Content-Type', $this->config->getAppValue($this->appName, $key . 'Mime', ''));
327
-		}
328
-		return $response;
329
-	}
316
+        $response = new FileDisplayResponse($file);
317
+        $csp = new Http\ContentSecurityPolicy();
318
+        $csp->allowInlineStyle();
319
+        $response->setContentSecurityPolicy($csp);
320
+        $response->cacheFor(3600);
321
+        $response->addHeader('Content-Type', $this->config->getAppValue($this->appName, $key . 'Mime', ''));
322
+        $response->addHeader('Content-Disposition', 'attachment; filename="' . $key . '"');
323
+        if (!$useSvg) {
324
+            $response->addHeader('Content-Type', 'image/png');
325
+        } else {
326
+            $response->addHeader('Content-Type', $this->config->getAppValue($this->appName, $key . 'Mime', ''));
327
+        }
328
+        return $response;
329
+    }
330 330
 
331
-	/**
332
-	 * @NoCSRFRequired
333
-	 * @PublicPage
334
-	 * @NoSameSiteCookieRequired
335
-	 * @NoTwoFactorRequired
336
-	 *
337
-	 * @return DataDisplayResponse|NotFoundResponse
338
-	 */
339
-	public function getThemeStylesheet(string $themeId, bool $plain = false, bool $withCustomCss = false) {
340
-		$themes = $this->themesService->getThemes();
341
-		if (!in_array($themeId, array_keys($themes))) {
342
-			return new NotFoundResponse();
343
-		}
331
+    /**
332
+     * @NoCSRFRequired
333
+     * @PublicPage
334
+     * @NoSameSiteCookieRequired
335
+     * @NoTwoFactorRequired
336
+     *
337
+     * @return DataDisplayResponse|NotFoundResponse
338
+     */
339
+    public function getThemeStylesheet(string $themeId, bool $plain = false, bool $withCustomCss = false) {
340
+        $themes = $this->themesService->getThemes();
341
+        if (!in_array($themeId, array_keys($themes))) {
342
+            return new NotFoundResponse();
343
+        }
344 344
 
345
-		$theme = $themes[$themeId];
346
-		$customCss  = $theme->getCustomCss();
345
+        $theme = $themes[$themeId];
346
+        $customCss  = $theme->getCustomCss();
347 347
 
348
-		// Generate variables
349
-		$variables = '';
350
-		foreach ($theme->getCSSVariables() as $variable => $value) {
351
-			$variables .= "$variable:$value; ";
352
-		};
348
+        // Generate variables
349
+        $variables = '';
350
+        foreach ($theme->getCSSVariables() as $variable => $value) {
351
+            $variables .= "$variable:$value; ";
352
+        };
353 353
 
354
-		// If plain is set, the browser decides of the css priority
355
-		if ($plain) {
356
-			$css = ":root { $variables } " . $customCss;
357
-		} else { 
358
-			// If not set, we'll rely on the body class
359
-			$compiler = new Compiler();
360
-			$compiledCss = $compiler->compileString("[data-theme-$themeId] { $variables $customCss }");
361
-			$css = $compiledCss->getCss();;
362
-		}
354
+        // If plain is set, the browser decides of the css priority
355
+        if ($plain) {
356
+            $css = ":root { $variables } " . $customCss;
357
+        } else { 
358
+            // If not set, we'll rely on the body class
359
+            $compiler = new Compiler();
360
+            $compiledCss = $compiler->compileString("[data-theme-$themeId] { $variables $customCss }");
361
+            $css = $compiledCss->getCss();;
362
+        }
363 363
 
364
-		try {
365
-			$response = new DataDisplayResponse($css, Http::STATUS_OK, ['Content-Type' => 'text/css']);
366
-			$response->cacheFor(86400);
367
-			return $response;
368
-		} catch (NotFoundException $e) {
369
-			return new NotFoundResponse();
370
-		}
371
-	}
364
+        try {
365
+            $response = new DataDisplayResponse($css, Http::STATUS_OK, ['Content-Type' => 'text/css']);
366
+            $response->cacheFor(86400);
367
+            return $response;
368
+        } catch (NotFoundException $e) {
369
+            return new NotFoundResponse();
370
+        }
371
+    }
372 372
 
373
-	/**
374
-	 * @NoCSRFRequired
375
-	 * @PublicPage
376
-	 *
377
-	 * @return Http\JSONResponse
378
-	 */
379
-	public function getManifest($app) {
380
-		$cacheBusterValue = $this->config->getAppValue('theming', 'cachebuster', '0');
381
-		if ($app === 'core' || $app === 'settings') {
382
-			$name = $this->themingDefaults->getName();
383
-			$shortName = $this->themingDefaults->getName();
384
-			$startUrl = $this->urlGenerator->getBaseUrl();
385
-			$description = $this->themingDefaults->getSlogan();
386
-		} else {
387
-			$info = $this->appManager->getAppInfo($app, false, $this->l10n->getLanguageCode());
388
-			$name = $info['name'] . ' - ' . $this->themingDefaults->getName();
389
-			$shortName = $info['name'];
390
-			if (strpos($this->request->getRequestUri(), '/index.php/') !== false) {
391
-				$startUrl = $this->urlGenerator->getBaseUrl() . '/index.php/apps/' . $app . '/';
392
-			} else {
393
-				$startUrl = $this->urlGenerator->getBaseUrl() . '/apps/' . $app . '/';
394
-			}
395
-			$description = $info['summary'] ?? '';
396
-		}
397
-		$responseJS = [
398
-			'name' => $name,
399
-			'short_name' => $shortName,
400
-			'start_url' => $startUrl,
401
-			'theme_color' => $this->themingDefaults->getColorPrimary(),
402
-			'background_color' => $this->themingDefaults->getColorPrimary(),
403
-			'description' => $description,
404
-			'icons' =>
405
-				[
406
-					[
407
-						'src' => $this->urlGenerator->linkToRoute('theming.Icon.getTouchIcon',
408
-								['app' => $app]) . '?v=' . $cacheBusterValue,
409
-						'type' => 'image/png',
410
-						'sizes' => '512x512'
411
-					],
412
-					[
413
-						'src' => $this->urlGenerator->linkToRoute('theming.Icon.getFavicon',
414
-								['app' => $app]) . '?v=' . $cacheBusterValue,
415
-						'type' => 'image/svg+xml',
416
-						'sizes' => '16x16'
417
-					]
418
-				],
419
-			'display' => 'standalone'
420
-		];
421
-		$response = new Http\JSONResponse($responseJS);
422
-		$response->cacheFor(3600);
423
-		return $response;
424
-	}
373
+    /**
374
+     * @NoCSRFRequired
375
+     * @PublicPage
376
+     *
377
+     * @return Http\JSONResponse
378
+     */
379
+    public function getManifest($app) {
380
+        $cacheBusterValue = $this->config->getAppValue('theming', 'cachebuster', '0');
381
+        if ($app === 'core' || $app === 'settings') {
382
+            $name = $this->themingDefaults->getName();
383
+            $shortName = $this->themingDefaults->getName();
384
+            $startUrl = $this->urlGenerator->getBaseUrl();
385
+            $description = $this->themingDefaults->getSlogan();
386
+        } else {
387
+            $info = $this->appManager->getAppInfo($app, false, $this->l10n->getLanguageCode());
388
+            $name = $info['name'] . ' - ' . $this->themingDefaults->getName();
389
+            $shortName = $info['name'];
390
+            if (strpos($this->request->getRequestUri(), '/index.php/') !== false) {
391
+                $startUrl = $this->urlGenerator->getBaseUrl() . '/index.php/apps/' . $app . '/';
392
+            } else {
393
+                $startUrl = $this->urlGenerator->getBaseUrl() . '/apps/' . $app . '/';
394
+            }
395
+            $description = $info['summary'] ?? '';
396
+        }
397
+        $responseJS = [
398
+            'name' => $name,
399
+            'short_name' => $shortName,
400
+            'start_url' => $startUrl,
401
+            'theme_color' => $this->themingDefaults->getColorPrimary(),
402
+            'background_color' => $this->themingDefaults->getColorPrimary(),
403
+            'description' => $description,
404
+            'icons' =>
405
+                [
406
+                    [
407
+                        'src' => $this->urlGenerator->linkToRoute('theming.Icon.getTouchIcon',
408
+                                ['app' => $app]) . '?v=' . $cacheBusterValue,
409
+                        'type' => 'image/png',
410
+                        'sizes' => '512x512'
411
+                    ],
412
+                    [
413
+                        'src' => $this->urlGenerator->linkToRoute('theming.Icon.getFavicon',
414
+                                ['app' => $app]) . '?v=' . $cacheBusterValue,
415
+                        'type' => 'image/svg+xml',
416
+                        'sizes' => '16x16'
417
+                    ]
418
+                ],
419
+            'display' => 'standalone'
420
+        ];
421
+        $response = new Http\JSONResponse($responseJS);
422
+        $response->cacheFor(3600);
423
+        return $response;
424
+    }
425 425
 }
Please login to merge, or discard this patch.
apps/theming/lib/Controller/UserThemeController.php 1 patch
Indentation   +159 added lines, -159 removed lines patch added patch discarded remove patch
@@ -50,163 +50,163 @@
 block discarded – undo
50 50
 
51 51
 class UserThemeController extends OCSController {
52 52
 
53
-	protected string $userId;
54
-	private IConfig $config;
55
-	private IUserSession $userSession;
56
-	private ThemesService $themesService;
57
-	private ThemingDefaults $themingDefaults;
58
-	private BackgroundService $backgroundService;
59
-
60
-	/**
61
-	 * Config constructor.
62
-	 */
63
-	public function __construct(string $appName,
64
-								IRequest $request,
65
-								IConfig $config,
66
-								IUserSession $userSession,
67
-								ThemesService $themesService,
68
-								ThemingDefaults $themingDefaults,
69
-								BackgroundService $backgroundService) {
70
-		parent::__construct($appName, $request);
71
-		$this->config = $config;
72
-		$this->userSession = $userSession;
73
-		$this->themesService = $themesService;
74
-		$this->themingDefaults = $themingDefaults;
75
-		$this->backgroundService = $backgroundService;
76
-		$this->userId = $userSession->getUser()->getUID();
77
-	}
78
-
79
-	/**
80
-	 * @NoAdminRequired
81
-	 *
82
-	 * Enable theme
83
-	 *
84
-	 * @param string $themeId the theme ID
85
-	 * @return DataResponse
86
-	 * @throws OCSBadRequestException|PreConditionNotMetException
87
-	 */
88
-	public function enableTheme(string $themeId): DataResponse {
89
-		$theme = $this->validateTheme($themeId);
90
-
91
-		// Enable selected theme
92
-		$this->themesService->enableTheme($theme);
93
-		return new DataResponse();
94
-	}
95
-
96
-	/**
97
-	 * @NoAdminRequired
98
-	 *
99
-	 * Disable theme
100
-	 *
101
-	 * @param string $themeId the theme ID
102
-	 * @return DataResponse
103
-	 * @throws OCSBadRequestException|PreConditionNotMetException
104
-	 */
105
-	public function disableTheme(string $themeId): DataResponse {
106
-		$theme = $this->validateTheme($themeId);
107
-
108
-		// Enable selected theme
109
-		$this->themesService->disableTheme($theme);
110
-		return new DataResponse();
111
-	}
112
-
113
-	/**
114
-	 * Validate and return the matching ITheme
115
-	 *
116
-	 * Disable theme
117
-	 *
118
-	 * @param string $themeId the theme ID
119
-	 * @return ITheme
120
-	 * @throws OCSBadRequestException|PreConditionNotMetException
121
-	 */
122
-	private function validateTheme(string $themeId): ITheme {
123
-		if ($themeId === '' || !$themeId) {
124
-			throw new OCSBadRequestException('Invalid theme id: ' . $themeId);
125
-		}
126
-
127
-		$themes = $this->themesService->getThemes();
128
-		if (!isset($themes[$themeId])) {
129
-			throw new OCSBadRequestException('Invalid theme id: ' . $themeId);
130
-		}
131
-
132
-		// If trying to toggle another theme but this is enforced
133
-		if ($this->config->getSystemValueString('enforce_theme', '') !== ''
134
-			&& $themes[$themeId]->getType() === ITheme::TYPE_THEME) {
135
-			throw new OCSForbiddenException('Theme switching is disabled');
136
-		}
137
-
138
-		return $themes[$themeId];
139
-	}
140
-
141
-	/**
142
-	 * @NoAdminRequired
143
-	 * @NoCSRFRequired
144
-	 */
145
-	public function getBackground(): Http\Response {
146
-		$file = $this->backgroundService->getBackground();
147
-		if ($file !== null) {
148
-			$response = new FileDisplayResponse($file, Http::STATUS_OK, ['Content-Type' => $file->getMimeType()]);
149
-			$response->cacheFor(24 * 60 * 60, false, true);
150
-			return $response;
151
-		}
152
-		return new NotFoundResponse();
153
-	}
154
-
155
-	/**
156
-	 * @NoAdminRequired
157
-	 */
158
-	public function deleteBackground(): JSONResponse {
159
-		$currentVersion = (int)$this->config->getUserValue($this->userId, Application::APP_ID, 'userCacheBuster', '0');
160
-		$this->backgroundService->deleteBackgroundImage();
161
-		return new JSONResponse([
162
-			'backgroundImage' => null,
163
-			'backgroundColor' => $this->themingDefaults->getColorPrimary(),
164
-			'version' => $currentVersion,
165
-		]);
166
-	}
167
-
168
-	/**
169
-	 * @NoAdminRequired
170
-	 */
171
-	public function setBackground(string $type = BackgroundService::BACKGROUND_DEFAULT, string $value = '', string $color = null): JSONResponse {
172
-		$currentVersion = (int)$this->config->getUserValue($this->userId, Application::APP_ID, 'userCacheBuster', '0');
173
-
174
-		// Set color if provided
175
-		if ($color) {
176
-			$this->backgroundService->setColorBackground($color);
177
-		}
178
-
179
-		// Set background image if provided
180
-		try {
181
-			switch ($type) {
182
-				case BackgroundService::BACKGROUND_SHIPPED:
183
-					$this->backgroundService->setShippedBackground($value);
184
-					break;
185
-				case BackgroundService::BACKGROUND_CUSTOM:
186
-					$this->backgroundService->setFileBackground($value);
187
-					break;
188
-				case BackgroundService::BACKGROUND_DEFAULT:
189
-					// Delete both background and color keys
190
-					$this->backgroundService->setDefaultBackground();
191
-					break;
192
-				default:
193
-					if (!$color) {
194
-						return new JSONResponse(['error' => 'Invalid type provided'], Http::STATUS_BAD_REQUEST);
195
-					}
196
-			}
197
-		} catch (\InvalidArgumentException $e) {
198
-			return new JSONResponse(['error' => $e->getMessage()], Http::STATUS_BAD_REQUEST);
199
-		} catch (\Throwable $e) {
200
-			return new JSONResponse(['error' => $e->getMessage()], Http::STATUS_INTERNAL_SERVER_ERROR);
201
-		}
202
-
203
-		$currentVersion++;
204
-		$this->config->setUserValue($this->userId, Application::APP_ID, 'userCacheBuster', (string)$currentVersion);
205
-
206
-		return new JSONResponse([
207
-			'backgroundImage' => $this->config->getUserValue($this->userId, Application::APP_ID, 'background_image', BackgroundService::BACKGROUND_DEFAULT),
208
-			'backgroundColor' => $this->themingDefaults->getColorPrimary(),
209
-			'version' => $currentVersion,
210
-		]);
211
-	}
53
+    protected string $userId;
54
+    private IConfig $config;
55
+    private IUserSession $userSession;
56
+    private ThemesService $themesService;
57
+    private ThemingDefaults $themingDefaults;
58
+    private BackgroundService $backgroundService;
59
+
60
+    /**
61
+     * Config constructor.
62
+     */
63
+    public function __construct(string $appName,
64
+                                IRequest $request,
65
+                                IConfig $config,
66
+                                IUserSession $userSession,
67
+                                ThemesService $themesService,
68
+                                ThemingDefaults $themingDefaults,
69
+                                BackgroundService $backgroundService) {
70
+        parent::__construct($appName, $request);
71
+        $this->config = $config;
72
+        $this->userSession = $userSession;
73
+        $this->themesService = $themesService;
74
+        $this->themingDefaults = $themingDefaults;
75
+        $this->backgroundService = $backgroundService;
76
+        $this->userId = $userSession->getUser()->getUID();
77
+    }
78
+
79
+    /**
80
+     * @NoAdminRequired
81
+     *
82
+     * Enable theme
83
+     *
84
+     * @param string $themeId the theme ID
85
+     * @return DataResponse
86
+     * @throws OCSBadRequestException|PreConditionNotMetException
87
+     */
88
+    public function enableTheme(string $themeId): DataResponse {
89
+        $theme = $this->validateTheme($themeId);
90
+
91
+        // Enable selected theme
92
+        $this->themesService->enableTheme($theme);
93
+        return new DataResponse();
94
+    }
95
+
96
+    /**
97
+     * @NoAdminRequired
98
+     *
99
+     * Disable theme
100
+     *
101
+     * @param string $themeId the theme ID
102
+     * @return DataResponse
103
+     * @throws OCSBadRequestException|PreConditionNotMetException
104
+     */
105
+    public function disableTheme(string $themeId): DataResponse {
106
+        $theme = $this->validateTheme($themeId);
107
+
108
+        // Enable selected theme
109
+        $this->themesService->disableTheme($theme);
110
+        return new DataResponse();
111
+    }
112
+
113
+    /**
114
+     * Validate and return the matching ITheme
115
+     *
116
+     * Disable theme
117
+     *
118
+     * @param string $themeId the theme ID
119
+     * @return ITheme
120
+     * @throws OCSBadRequestException|PreConditionNotMetException
121
+     */
122
+    private function validateTheme(string $themeId): ITheme {
123
+        if ($themeId === '' || !$themeId) {
124
+            throw new OCSBadRequestException('Invalid theme id: ' . $themeId);
125
+        }
126
+
127
+        $themes = $this->themesService->getThemes();
128
+        if (!isset($themes[$themeId])) {
129
+            throw new OCSBadRequestException('Invalid theme id: ' . $themeId);
130
+        }
131
+
132
+        // If trying to toggle another theme but this is enforced
133
+        if ($this->config->getSystemValueString('enforce_theme', '') !== ''
134
+            && $themes[$themeId]->getType() === ITheme::TYPE_THEME) {
135
+            throw new OCSForbiddenException('Theme switching is disabled');
136
+        }
137
+
138
+        return $themes[$themeId];
139
+    }
140
+
141
+    /**
142
+     * @NoAdminRequired
143
+     * @NoCSRFRequired
144
+     */
145
+    public function getBackground(): Http\Response {
146
+        $file = $this->backgroundService->getBackground();
147
+        if ($file !== null) {
148
+            $response = new FileDisplayResponse($file, Http::STATUS_OK, ['Content-Type' => $file->getMimeType()]);
149
+            $response->cacheFor(24 * 60 * 60, false, true);
150
+            return $response;
151
+        }
152
+        return new NotFoundResponse();
153
+    }
154
+
155
+    /**
156
+     * @NoAdminRequired
157
+     */
158
+    public function deleteBackground(): JSONResponse {
159
+        $currentVersion = (int)$this->config->getUserValue($this->userId, Application::APP_ID, 'userCacheBuster', '0');
160
+        $this->backgroundService->deleteBackgroundImage();
161
+        return new JSONResponse([
162
+            'backgroundImage' => null,
163
+            'backgroundColor' => $this->themingDefaults->getColorPrimary(),
164
+            'version' => $currentVersion,
165
+        ]);
166
+    }
167
+
168
+    /**
169
+     * @NoAdminRequired
170
+     */
171
+    public function setBackground(string $type = BackgroundService::BACKGROUND_DEFAULT, string $value = '', string $color = null): JSONResponse {
172
+        $currentVersion = (int)$this->config->getUserValue($this->userId, Application::APP_ID, 'userCacheBuster', '0');
173
+
174
+        // Set color if provided
175
+        if ($color) {
176
+            $this->backgroundService->setColorBackground($color);
177
+        }
178
+
179
+        // Set background image if provided
180
+        try {
181
+            switch ($type) {
182
+                case BackgroundService::BACKGROUND_SHIPPED:
183
+                    $this->backgroundService->setShippedBackground($value);
184
+                    break;
185
+                case BackgroundService::BACKGROUND_CUSTOM:
186
+                    $this->backgroundService->setFileBackground($value);
187
+                    break;
188
+                case BackgroundService::BACKGROUND_DEFAULT:
189
+                    // Delete both background and color keys
190
+                    $this->backgroundService->setDefaultBackground();
191
+                    break;
192
+                default:
193
+                    if (!$color) {
194
+                        return new JSONResponse(['error' => 'Invalid type provided'], Http::STATUS_BAD_REQUEST);
195
+                    }
196
+            }
197
+        } catch (\InvalidArgumentException $e) {
198
+            return new JSONResponse(['error' => $e->getMessage()], Http::STATUS_BAD_REQUEST);
199
+        } catch (\Throwable $e) {
200
+            return new JSONResponse(['error' => $e->getMessage()], Http::STATUS_INTERNAL_SERVER_ERROR);
201
+        }
202
+
203
+        $currentVersion++;
204
+        $this->config->setUserValue($this->userId, Application::APP_ID, 'userCacheBuster', (string)$currentVersion);
205
+
206
+        return new JSONResponse([
207
+            'backgroundImage' => $this->config->getUserValue($this->userId, Application::APP_ID, 'background_image', BackgroundService::BACKGROUND_DEFAULT),
208
+            'backgroundColor' => $this->themingDefaults->getColorPrimary(),
209
+            'version' => $currentVersion,
210
+        ]);
211
+    }
212 212
 }
Please login to merge, or discard this patch.
apps/theming/appinfo/routes.php 1 patch
Indentation   +83 added lines, -83 removed lines patch added patch discarded remove patch
@@ -28,87 +28,87 @@
 block discarded – undo
28 28
  *
29 29
  */
30 30
 return [
31
-	'routes' => [
32
-		[
33
-			'name' => 'Theming#updateStylesheet',
34
-			'url' => '/ajax/updateStylesheet',
35
-			'verb' => 'POST'
36
-		],
37
-		[
38
-			'name' => 'Theming#undo',
39
-			'url' => '/ajax/undoChanges',
40
-			'verb' => 'POST'
41
-		],
42
-		[
43
-			'name' => 'Theming#undoAll',
44
-			'url' => '/ajax/undoAllChanges',
45
-			'verb' => 'POST'
46
-		],
47
-		[
48
-			'name' => 'Theming#uploadImage',
49
-			'url' => '/ajax/uploadImage',
50
-			'verb' => 'POST'
51
-		],
52
-		[
53
-			'name' => 'Theming#getThemeStylesheet',
54
-			'url' => '/theme/{themeId}.css',
55
-			'verb' => 'GET',
56
-		],
57
-		[
58
-			'name' => 'Theming#getImage',
59
-			'url' => '/image/{key}',
60
-			'verb' => 'GET',
61
-		],
62
-		[
63
-			'name' => 'Theming#getManifest',
64
-			'url' => '/manifest/{app}',
65
-			'verb' => 'GET',
66
-			'defaults' => ['app' => 'core']
67
-		],
68
-		[
69
-			'name' => 'Icon#getFavicon',
70
-			'url' => '/favicon/{app}',
71
-			'verb' => 'GET',
72
-			'defaults' => ['app' => 'core'],
73
-		],
74
-		[
75
-			'name' => 'Icon#getTouchIcon',
76
-			'url' => '/icon/{app}',
77
-			'verb' => 'GET',
78
-			'defaults' => ['app' => 'core'],
79
-		],
80
-		[
81
-			'name' => 'Icon#getThemedIcon',
82
-			'url' => '/img/{app}/{image}',
83
-			'verb' => 'GET',
84
-			'requirements' => ['image' => '.+']
85
-		],
86
-		[
87
-			'name' => 'userTheme#getBackground',
88
-			'url' => '/background',
89
-			'verb' => 'GET',
90
-		],
91
-		[
92
-			'name' => 'userTheme#setBackground',
93
-			'url' => '/background/{type}',
94
-			'verb' => 'POST',
95
-		],
96
-		[
97
-			'name' => 'userTheme#deleteBackground',
98
-			'url' => '/background/custom',
99
-			'verb' => 'DELETE',
100
-		],
101
-	],
102
-	'ocs' => [
103
-		[
104
-			'name' => 'userTheme#enableTheme',
105
-			'url' => '/api/v1/theme/{themeId}/enable',
106
-			'verb' => 'PUT',
107
-		],
108
-		[
109
-			'name' => 'userTheme#disableTheme',
110
-			'url' => '/api/v1/theme/{themeId}',
111
-			'verb' => 'DELETE',
112
-		],
113
-	]
31
+    'routes' => [
32
+        [
33
+            'name' => 'Theming#updateStylesheet',
34
+            'url' => '/ajax/updateStylesheet',
35
+            'verb' => 'POST'
36
+        ],
37
+        [
38
+            'name' => 'Theming#undo',
39
+            'url' => '/ajax/undoChanges',
40
+            'verb' => 'POST'
41
+        ],
42
+        [
43
+            'name' => 'Theming#undoAll',
44
+            'url' => '/ajax/undoAllChanges',
45
+            'verb' => 'POST'
46
+        ],
47
+        [
48
+            'name' => 'Theming#uploadImage',
49
+            'url' => '/ajax/uploadImage',
50
+            'verb' => 'POST'
51
+        ],
52
+        [
53
+            'name' => 'Theming#getThemeStylesheet',
54
+            'url' => '/theme/{themeId}.css',
55
+            'verb' => 'GET',
56
+        ],
57
+        [
58
+            'name' => 'Theming#getImage',
59
+            'url' => '/image/{key}',
60
+            'verb' => 'GET',
61
+        ],
62
+        [
63
+            'name' => 'Theming#getManifest',
64
+            'url' => '/manifest/{app}',
65
+            'verb' => 'GET',
66
+            'defaults' => ['app' => 'core']
67
+        ],
68
+        [
69
+            'name' => 'Icon#getFavicon',
70
+            'url' => '/favicon/{app}',
71
+            'verb' => 'GET',
72
+            'defaults' => ['app' => 'core'],
73
+        ],
74
+        [
75
+            'name' => 'Icon#getTouchIcon',
76
+            'url' => '/icon/{app}',
77
+            'verb' => 'GET',
78
+            'defaults' => ['app' => 'core'],
79
+        ],
80
+        [
81
+            'name' => 'Icon#getThemedIcon',
82
+            'url' => '/img/{app}/{image}',
83
+            'verb' => 'GET',
84
+            'requirements' => ['image' => '.+']
85
+        ],
86
+        [
87
+            'name' => 'userTheme#getBackground',
88
+            'url' => '/background',
89
+            'verb' => 'GET',
90
+        ],
91
+        [
92
+            'name' => 'userTheme#setBackground',
93
+            'url' => '/background/{type}',
94
+            'verb' => 'POST',
95
+        ],
96
+        [
97
+            'name' => 'userTheme#deleteBackground',
98
+            'url' => '/background/custom',
99
+            'verb' => 'DELETE',
100
+        ],
101
+    ],
102
+    'ocs' => [
103
+        [
104
+            'name' => 'userTheme#enableTheme',
105
+            'url' => '/api/v1/theme/{themeId}/enable',
106
+            'verb' => 'PUT',
107
+        ],
108
+        [
109
+            'name' => 'userTheme#disableTheme',
110
+            'url' => '/api/v1/theme/{themeId}',
111
+            'verb' => 'DELETE',
112
+        ],
113
+    ]
114 114
 ];
Please login to merge, or discard this patch.