Passed
Push — master ( a884f3...785682 )
by
unknown
14:57 queued 14s
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->setUserValue($this->userId, Application::APP_ID, 'background_color', $this->themingDefaults->getDefaultColorPrimary());
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->setUserValue($this->userId, Application::APP_ID, 'background_color', $this->themingDefaults->getDefaultColorPrimary());
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/Command/UpdateConfig.php 2 patches
Indentation   +102 added lines, -102 removed lines patch added patch discarded remove patch
@@ -32,106 +32,106 @@
 block discarded – undo
32 32
 use Symfony\Component\Console\Output\OutputInterface;
33 33
 
34 34
 class UpdateConfig extends Command {
35
-	public const SUPPORTED_KEYS = [
36
-		'name', 'url', 'imprintUrl', 'privacyUrl', 'slogan', 'color', 'disable-user-theming'
37
-	];
38
-
39
-	private $themingDefaults;
40
-	private $imageManager;
41
-	private $config;
42
-
43
-	public function __construct(ThemingDefaults $themingDefaults, ImageManager $imageManager, IConfig $config) {
44
-		parent::__construct();
45
-
46
-		$this->themingDefaults = $themingDefaults;
47
-		$this->imageManager = $imageManager;
48
-		$this->config = $config;
49
-	}
50
-
51
-	protected function configure() {
52
-		$this
53
-			->setName('theming:config')
54
-			->setDescription('Set theming app config values')
55
-			->addArgument(
56
-				'key',
57
-				InputArgument::OPTIONAL,
58
-				'Key to update the theming app configuration (leave empty to get a list of all configured values)' . PHP_EOL .
59
-				'One of: ' . implode(', ', self::SUPPORTED_KEYS)
60
-			)
61
-			->addArgument(
62
-				'value',
63
-				InputArgument::OPTIONAL,
64
-				'Value to set (leave empty to obtain the current value)'
65
-			)
66
-			->addOption(
67
-				'reset',
68
-				'r',
69
-				InputOption::VALUE_NONE,
70
-				'Reset the given config key to default'
71
-			);
72
-	}
73
-
74
-
75
-	protected function execute(InputInterface $input, OutputInterface $output): int {
76
-		$key = $input->getArgument('key');
77
-		$value = $input->getArgument('value');
78
-		assert(is_string($value) || $value === null, 'At most one value should be provided.');
79
-
80
-		if ($key === null) {
81
-			$output->writeln('Current theming config:');
82
-			foreach (self::SUPPORTED_KEYS as $key) {
83
-				$value = $this->config->getAppValue('theming', $key, '');
84
-				$output->writeln('- ' . $key . ': ' . $value . '');
85
-			}
86
-			foreach (ImageManager::SUPPORTED_IMAGE_KEYS as $key) {
87
-				$value = $this->config->getAppValue('theming', $key . 'Mime', '');
88
-				$output->writeln('- ' . $key . ': ' . $value . '');
89
-			}
90
-			return 0;
91
-		}
92
-
93
-		if (!in_array($key, self::SUPPORTED_KEYS, true) && !in_array($key, ImageManager::SUPPORTED_IMAGE_KEYS, true)) {
94
-			$output->writeln('<error>Invalid config key provided</error>');
95
-			return 1;
96
-		}
97
-
98
-		if ($input->getOption('reset')) {
99
-			$defaultValue = $this->themingDefaults->undo($key);
100
-			$output->writeln('<info>Reset ' . $key . ' to ' . $defaultValue . '</info>');
101
-			return 0;
102
-		}
103
-
104
-		if ($value === null) {
105
-			$value = $this->config->getAppValue('theming', $key, '');
106
-			if ($value !== '') {
107
-				$output->writeln('<info>' . $key . ' is currently set to ' . $value . '</info>');
108
-			} else {
109
-				$output->writeln('<info>' . $key . ' is currently not set</info>');
110
-			}
111
-			return 0;
112
-		}
113
-
114
-		if (in_array($key, ImageManager::SUPPORTED_IMAGE_KEYS, true)) {
115
-			if (strpos($value, '/') !== 0) {
116
-				$output->writeln('<error>The image file needs to be provided as an absolute path: ' . $value . '.</error>');
117
-				return 1;
118
-			}
119
-			if (!file_exists($value)) {
120
-				$output->writeln('<error>File could not be found: ' . $value . '.</error>');
121
-				return 1;
122
-			}
123
-			$value = $this->imageManager->updateImage($key, $value);
124
-			$key = $key . 'Mime';
125
-		}
126
-
127
-		if ($key === 'color' && !preg_match('/^\#([0-9a-f]{3}|[0-9a-f]{6})$/i', $value)) {
128
-			$output->writeln('<error>The given color is invalid: ' . $value . '</error>');
129
-			return 1;
130
-		}
131
-
132
-		$this->themingDefaults->set($key, $value);
133
-		$output->writeln('<info>Updated ' . $key . ' to ' . $value . '</info>');
134
-
135
-		return 0;
136
-	}
35
+    public const SUPPORTED_KEYS = [
36
+        'name', 'url', 'imprintUrl', 'privacyUrl', 'slogan', 'color', 'disable-user-theming'
37
+    ];
38
+
39
+    private $themingDefaults;
40
+    private $imageManager;
41
+    private $config;
42
+
43
+    public function __construct(ThemingDefaults $themingDefaults, ImageManager $imageManager, IConfig $config) {
44
+        parent::__construct();
45
+
46
+        $this->themingDefaults = $themingDefaults;
47
+        $this->imageManager = $imageManager;
48
+        $this->config = $config;
49
+    }
50
+
51
+    protected function configure() {
52
+        $this
53
+            ->setName('theming:config')
54
+            ->setDescription('Set theming app config values')
55
+            ->addArgument(
56
+                'key',
57
+                InputArgument::OPTIONAL,
58
+                'Key to update the theming app configuration (leave empty to get a list of all configured values)' . PHP_EOL .
59
+                'One of: ' . implode(', ', self::SUPPORTED_KEYS)
60
+            )
61
+            ->addArgument(
62
+                'value',
63
+                InputArgument::OPTIONAL,
64
+                'Value to set (leave empty to obtain the current value)'
65
+            )
66
+            ->addOption(
67
+                'reset',
68
+                'r',
69
+                InputOption::VALUE_NONE,
70
+                'Reset the given config key to default'
71
+            );
72
+    }
73
+
74
+
75
+    protected function execute(InputInterface $input, OutputInterface $output): int {
76
+        $key = $input->getArgument('key');
77
+        $value = $input->getArgument('value');
78
+        assert(is_string($value) || $value === null, 'At most one value should be provided.');
79
+
80
+        if ($key === null) {
81
+            $output->writeln('Current theming config:');
82
+            foreach (self::SUPPORTED_KEYS as $key) {
83
+                $value = $this->config->getAppValue('theming', $key, '');
84
+                $output->writeln('- ' . $key . ': ' . $value . '');
85
+            }
86
+            foreach (ImageManager::SUPPORTED_IMAGE_KEYS as $key) {
87
+                $value = $this->config->getAppValue('theming', $key . 'Mime', '');
88
+                $output->writeln('- ' . $key . ': ' . $value . '');
89
+            }
90
+            return 0;
91
+        }
92
+
93
+        if (!in_array($key, self::SUPPORTED_KEYS, true) && !in_array($key, ImageManager::SUPPORTED_IMAGE_KEYS, true)) {
94
+            $output->writeln('<error>Invalid config key provided</error>');
95
+            return 1;
96
+        }
97
+
98
+        if ($input->getOption('reset')) {
99
+            $defaultValue = $this->themingDefaults->undo($key);
100
+            $output->writeln('<info>Reset ' . $key . ' to ' . $defaultValue . '</info>');
101
+            return 0;
102
+        }
103
+
104
+        if ($value === null) {
105
+            $value = $this->config->getAppValue('theming', $key, '');
106
+            if ($value !== '') {
107
+                $output->writeln('<info>' . $key . ' is currently set to ' . $value . '</info>');
108
+            } else {
109
+                $output->writeln('<info>' . $key . ' is currently not set</info>');
110
+            }
111
+            return 0;
112
+        }
113
+
114
+        if (in_array($key, ImageManager::SUPPORTED_IMAGE_KEYS, true)) {
115
+            if (strpos($value, '/') !== 0) {
116
+                $output->writeln('<error>The image file needs to be provided as an absolute path: ' . $value . '.</error>');
117
+                return 1;
118
+            }
119
+            if (!file_exists($value)) {
120
+                $output->writeln('<error>File could not be found: ' . $value . '.</error>');
121
+                return 1;
122
+            }
123
+            $value = $this->imageManager->updateImage($key, $value);
124
+            $key = $key . 'Mime';
125
+        }
126
+
127
+        if ($key === 'color' && !preg_match('/^\#([0-9a-f]{3}|[0-9a-f]{6})$/i', $value)) {
128
+            $output->writeln('<error>The given color is invalid: ' . $value . '</error>');
129
+            return 1;
130
+        }
131
+
132
+        $this->themingDefaults->set($key, $value);
133
+        $output->writeln('<info>Updated ' . $key . ' to ' . $value . '</info>');
134
+
135
+        return 0;
136
+    }
137 137
 }
Please login to merge, or discard this patch.
Spacing   +13 added lines, -13 removed lines patch added patch discarded remove patch
@@ -55,8 +55,8 @@  discard block
 block discarded – undo
55 55
 			->addArgument(
56 56
 				'key',
57 57
 				InputArgument::OPTIONAL,
58
-				'Key to update the theming app configuration (leave empty to get a list of all configured values)' . PHP_EOL .
59
-				'One of: ' . implode(', ', self::SUPPORTED_KEYS)
58
+				'Key to update the theming app configuration (leave empty to get a list of all configured values)'.PHP_EOL.
59
+				'One of: '.implode(', ', self::SUPPORTED_KEYS)
60 60
 			)
61 61
 			->addArgument(
62 62
 				'value',
@@ -81,11 +81,11 @@  discard block
 block discarded – undo
81 81
 			$output->writeln('Current theming config:');
82 82
 			foreach (self::SUPPORTED_KEYS as $key) {
83 83
 				$value = $this->config->getAppValue('theming', $key, '');
84
-				$output->writeln('- ' . $key . ': ' . $value . '');
84
+				$output->writeln('- '.$key.': '.$value.'');
85 85
 			}
86 86
 			foreach (ImageManager::SUPPORTED_IMAGE_KEYS as $key) {
87
-				$value = $this->config->getAppValue('theming', $key . 'Mime', '');
88
-				$output->writeln('- ' . $key . ': ' . $value . '');
87
+				$value = $this->config->getAppValue('theming', $key.'Mime', '');
88
+				$output->writeln('- '.$key.': '.$value.'');
89 89
 			}
90 90
 			return 0;
91 91
 		}
@@ -97,40 +97,40 @@  discard block
 block discarded – undo
97 97
 
98 98
 		if ($input->getOption('reset')) {
99 99
 			$defaultValue = $this->themingDefaults->undo($key);
100
-			$output->writeln('<info>Reset ' . $key . ' to ' . $defaultValue . '</info>');
100
+			$output->writeln('<info>Reset '.$key.' to '.$defaultValue.'</info>');
101 101
 			return 0;
102 102
 		}
103 103
 
104 104
 		if ($value === null) {
105 105
 			$value = $this->config->getAppValue('theming', $key, '');
106 106
 			if ($value !== '') {
107
-				$output->writeln('<info>' . $key . ' is currently set to ' . $value . '</info>');
107
+				$output->writeln('<info>'.$key.' is currently set to '.$value.'</info>');
108 108
 			} else {
109
-				$output->writeln('<info>' . $key . ' is currently not set</info>');
109
+				$output->writeln('<info>'.$key.' is currently not set</info>');
110 110
 			}
111 111
 			return 0;
112 112
 		}
113 113
 
114 114
 		if (in_array($key, ImageManager::SUPPORTED_IMAGE_KEYS, true)) {
115 115
 			if (strpos($value, '/') !== 0) {
116
-				$output->writeln('<error>The image file needs to be provided as an absolute path: ' . $value . '.</error>');
116
+				$output->writeln('<error>The image file needs to be provided as an absolute path: '.$value.'.</error>');
117 117
 				return 1;
118 118
 			}
119 119
 			if (!file_exists($value)) {
120
-				$output->writeln('<error>File could not be found: ' . $value . '.</error>');
120
+				$output->writeln('<error>File could not be found: '.$value.'.</error>');
121 121
 				return 1;
122 122
 			}
123 123
 			$value = $this->imageManager->updateImage($key, $value);
124
-			$key = $key . 'Mime';
124
+			$key = $key.'Mime';
125 125
 		}
126 126
 
127 127
 		if ($key === 'color' && !preg_match('/^\#([0-9a-f]{3}|[0-9a-f]{6})$/i', $value)) {
128
-			$output->writeln('<error>The given color is invalid: ' . $value . '</error>');
128
+			$output->writeln('<error>The given color is invalid: '.$value.'</error>');
129 129
 			return 1;
130 130
 		}
131 131
 
132 132
 		$this->themingDefaults->set($key, $value);
133
-		$output->writeln('<info>Updated ' . $key . ' to ' . $value . '</info>');
133
+		$output->writeln('<info>Updated '.$key.' to '.$value.'</info>');
134 134
 
135 135
 		return 0;
136 136
 	}
Please login to merge, or discard this patch.
apps/theming/lib/Themes/CommonThemeTrait.php 2 patches
Indentation   +132 added lines, -132 removed lines patch added patch discarded remove patch
@@ -30,136 +30,136 @@
 block discarded – undo
30 30
 use OCA\Theming\Util;
31 31
 
32 32
 trait CommonThemeTrait {
33
-	public Util $util;
34
-
35
-	/**
36
-	 * Generate primary-related variables
37
-	 * This is shared between multiple themes because colorMainBackground and colorMainText
38
-	 * will change in between.
39
-	 */
40
-	protected function generatePrimaryVariables(string $colorMainBackground, string $colorMainText): array {
41
-		$colorPrimaryLight = $this->util->mix($this->primaryColor, $colorMainBackground, -80);
42
-		$colorPrimaryElement = $this->util->elementColor($this->primaryColor);
43
-		$colorPrimaryElementDefault = $this->util->elementColor($this->defaultPrimaryColor);
44
-		$colorPrimaryElementLight = $this->util->mix($colorPrimaryElement, $colorMainBackground, -80);
45
-
46
-		// primary related colours
47
-		return [
48
-			// invert filter if primary is too bright
49
-			// to be used for legacy reasons only. Use inline
50
-			// svg with proper css variable instead or material
51
-			// design icons.
52
-			// ⚠️ Using 'no' as a value to make sure we specify an
53
-			// invalid one with no fallback. 'unset' could here fallback to some
54
-			// other theme with media queries
55
-			'--primary-invert-if-bright' => $this->util->invertTextColor($this->primaryColor) ? 'invert(100%)' : 'no',
56
-
57
-			'--color-primary' => $this->primaryColor,
58
-			'--color-primary-default' => $this->defaultPrimaryColor,
59
-			'--color-primary-text' => $this->util->invertTextColor($this->primaryColor) ? '#000000' : '#ffffff',
60
-			'--color-primary-hover' => $this->util->mix($this->primaryColor, $colorMainBackground, 60),
61
-			'--color-primary-light' => $colorPrimaryLight,
62
-			'--color-primary-light-text' => $this->util->mix($this->primaryColor, $this->util->invertTextColor($colorPrimaryLight) ? '#000000' : '#ffffff', -20),
63
-			'--color-primary-light-hover' => $this->util->mix($colorPrimaryLight, $colorMainText, 90),
64
-			'--color-primary-text-dark' => $this->util->darken($this->util->invertTextColor($this->primaryColor) ? '#000000' : '#ffffff', 7),
65
-
66
-			// used for buttons, inputs...
67
-			'--color-primary-element' => $colorPrimaryElement,
68
-			'--color-primary-element-default-hover' => $this->util->mix($colorPrimaryElementDefault, $colorMainBackground, 60),
69
-			'--color-primary-element-text' => $this->util->invertTextColor($colorPrimaryElement) ? '#000000' : '#ffffff',
70
-			'--color-primary-element-hover' => $this->util->mix($colorPrimaryElement, $colorMainBackground, 60),
71
-			'--color-primary-element-light' => $colorPrimaryElementLight,
72
-			'--color-primary-element-light-text' => $this->util->mix($colorPrimaryElement, $this->util->invertTextColor($colorPrimaryElementLight) ? '#000000' : '#ffffff', -20),
73
-			'--color-primary-element-light-hover' => $this->util->mix($colorPrimaryElementLight, $colorMainText, 90),
74
-			'--color-primary-element-text-dark' => $this->util->darken($this->util->invertTextColor($colorPrimaryElement) ? '#000000' : '#ffffff', 7),
75
-
76
-			// to use like this: background-image: var(--gradient-primary-background);
77
-			'--gradient-primary-background' => 'linear-gradient(40deg, var(--color-primary) 0%, var(--color-primary-hover) 100%)',
78
-		];
79
-	}
80
-
81
-	/**
82
-	 * Generate admin theming background-related variables
83
-	 */
84
-	protected function generateGlobalBackgroundVariables(): array {
85
-		$user = $this->userSession->getUser();
86
-		$backgroundDeleted = $this->config->getAppValue(Application::APP_ID, 'backgroundMime', '') === 'backgroundColor';
87
-		$hasCustomLogoHeader = $this->util->isLogoThemed();
88
-
89
-		$variables = [];
90
-
91
-		// Default last fallback values
92
-		$variables['--image-background-default'] = "url('" . $this->themingDefaults->getBackground() . "')";
93
-		$variables['--color-background-plain'] = $this->defaultPrimaryColor;
94
-
95
-		// If primary as background has been request or if we have a custom primary colour
96
-		// let's not define the background image
97
-		if ($backgroundDeleted) {
98
-			$variables['--color-background-plain'] = $this->themingDefaults->getColorPrimary();
99
-			$variables['--image-background-plain'] = 'yes';
100
-		}
101
-
102
-		// Register image variables only if custom-defined
103
-		foreach (ImageManager::SUPPORTED_IMAGE_KEYS as $image) {
104
-			if ($this->imageManager->hasImage($image)) {
105
-				$imageUrl = $this->imageManager->getImageUrl($image);
106
-				if ($image === 'background') {
107
-					// If background deleted is set, ignoring variable
108
-					if ($backgroundDeleted) {
109
-						continue;
110
-					}
111
-					$variables['--image-background-size'] = 'cover';
112
-				}
113
-				// --image-background is overridden by user theming
114
-				$variables["--image-$image"] = "url('" . $imageUrl . "')";
115
-			}
116
-		}
117
-
118
-		if ($hasCustomLogoHeader) {
119
-			$variables["--image-logoheader-custom"] = 'true';
120
-		}
121
-
122
-		return $variables;
123
-	}
124
-
125
-	/**
126
-	 * Generate user theming background-related variables
127
-	 */
128
-	protected function generateUserBackgroundVariables(): array {
129
-		$user = $this->userSession->getUser();
130
-		if ($user !== null
131
-			&& !$this->themingDefaults->isUserThemingDisabled()
132
-			&& $this->appManager->isEnabledForUser(Application::APP_ID)) {
133
-			$backgroundImage = $this->config->getUserValue($user->getUID(), Application::APP_ID, 'background_image', BackgroundService::BACKGROUND_DEFAULT);
134
-			$currentVersion = (int)$this->config->getUserValue($user->getUID(), Application::APP_ID, 'userCacheBuster', '0');
135
-
136
-			// The user removed the background
137
-			if ($backgroundImage === BackgroundService::BACKGROUND_DISABLED) {
138
-				return [
139
-					'--image-background' => 'no',
140
-					'--color-background-plain' => $this->themingDefaults->getColorPrimary(),
141
-				];
142
-			}
143
-
144
-			// The user uploaded a custom background
145
-			if ($backgroundImage === BackgroundService::BACKGROUND_CUSTOM) {
146
-				$cacheBuster = substr(sha1($user->getUID() . '_' . $currentVersion), 0, 8);
147
-				return [
148
-					'--image-background' => "url('" . $this->urlGenerator->linkToRouteAbsolute('theming.userTheme.getBackground') . "?v=$cacheBuster')",
149
-					'--color-background-plain' => $this->themingDefaults->getColorPrimary(),
150
-				];
151
-			}
152
-
153
-			// The user picked a shipped background
154
-			if (isset(BackgroundService::SHIPPED_BACKGROUNDS[$backgroundImage])) {
155
-				return [
156
-					'--image-background' => "url('" . $this->urlGenerator->linkTo(Application::APP_ID, "img/background/$backgroundImage") . "')",
157
-					'--color-background-plain' => $this->themingDefaults->getColorPrimary(),
158
-					'--background-image-invert-if-bright' => BackgroundService::SHIPPED_BACKGROUNDS[$backgroundImage]['theming'] ?? null === BackgroundService::THEMING_MODE_DARK ? 'invert(100%)' : 'no',
159
-				];
160
-			}
161
-		}
162
-
163
-		return [];
164
-	}
33
+    public Util $util;
34
+
35
+    /**
36
+     * Generate primary-related variables
37
+     * This is shared between multiple themes because colorMainBackground and colorMainText
38
+     * will change in between.
39
+     */
40
+    protected function generatePrimaryVariables(string $colorMainBackground, string $colorMainText): array {
41
+        $colorPrimaryLight = $this->util->mix($this->primaryColor, $colorMainBackground, -80);
42
+        $colorPrimaryElement = $this->util->elementColor($this->primaryColor);
43
+        $colorPrimaryElementDefault = $this->util->elementColor($this->defaultPrimaryColor);
44
+        $colorPrimaryElementLight = $this->util->mix($colorPrimaryElement, $colorMainBackground, -80);
45
+
46
+        // primary related colours
47
+        return [
48
+            // invert filter if primary is too bright
49
+            // to be used for legacy reasons only. Use inline
50
+            // svg with proper css variable instead or material
51
+            // design icons.
52
+            // ⚠️ Using 'no' as a value to make sure we specify an
53
+            // invalid one with no fallback. 'unset' could here fallback to some
54
+            // other theme with media queries
55
+            '--primary-invert-if-bright' => $this->util->invertTextColor($this->primaryColor) ? 'invert(100%)' : 'no',
56
+
57
+            '--color-primary' => $this->primaryColor,
58
+            '--color-primary-default' => $this->defaultPrimaryColor,
59
+            '--color-primary-text' => $this->util->invertTextColor($this->primaryColor) ? '#000000' : '#ffffff',
60
+            '--color-primary-hover' => $this->util->mix($this->primaryColor, $colorMainBackground, 60),
61
+            '--color-primary-light' => $colorPrimaryLight,
62
+            '--color-primary-light-text' => $this->util->mix($this->primaryColor, $this->util->invertTextColor($colorPrimaryLight) ? '#000000' : '#ffffff', -20),
63
+            '--color-primary-light-hover' => $this->util->mix($colorPrimaryLight, $colorMainText, 90),
64
+            '--color-primary-text-dark' => $this->util->darken($this->util->invertTextColor($this->primaryColor) ? '#000000' : '#ffffff', 7),
65
+
66
+            // used for buttons, inputs...
67
+            '--color-primary-element' => $colorPrimaryElement,
68
+            '--color-primary-element-default-hover' => $this->util->mix($colorPrimaryElementDefault, $colorMainBackground, 60),
69
+            '--color-primary-element-text' => $this->util->invertTextColor($colorPrimaryElement) ? '#000000' : '#ffffff',
70
+            '--color-primary-element-hover' => $this->util->mix($colorPrimaryElement, $colorMainBackground, 60),
71
+            '--color-primary-element-light' => $colorPrimaryElementLight,
72
+            '--color-primary-element-light-text' => $this->util->mix($colorPrimaryElement, $this->util->invertTextColor($colorPrimaryElementLight) ? '#000000' : '#ffffff', -20),
73
+            '--color-primary-element-light-hover' => $this->util->mix($colorPrimaryElementLight, $colorMainText, 90),
74
+            '--color-primary-element-text-dark' => $this->util->darken($this->util->invertTextColor($colorPrimaryElement) ? '#000000' : '#ffffff', 7),
75
+
76
+            // to use like this: background-image: var(--gradient-primary-background);
77
+            '--gradient-primary-background' => 'linear-gradient(40deg, var(--color-primary) 0%, var(--color-primary-hover) 100%)',
78
+        ];
79
+    }
80
+
81
+    /**
82
+     * Generate admin theming background-related variables
83
+     */
84
+    protected function generateGlobalBackgroundVariables(): array {
85
+        $user = $this->userSession->getUser();
86
+        $backgroundDeleted = $this->config->getAppValue(Application::APP_ID, 'backgroundMime', '') === 'backgroundColor';
87
+        $hasCustomLogoHeader = $this->util->isLogoThemed();
88
+
89
+        $variables = [];
90
+
91
+        // Default last fallback values
92
+        $variables['--image-background-default'] = "url('" . $this->themingDefaults->getBackground() . "')";
93
+        $variables['--color-background-plain'] = $this->defaultPrimaryColor;
94
+
95
+        // If primary as background has been request or if we have a custom primary colour
96
+        // let's not define the background image
97
+        if ($backgroundDeleted) {
98
+            $variables['--color-background-plain'] = $this->themingDefaults->getColorPrimary();
99
+            $variables['--image-background-plain'] = 'yes';
100
+        }
101
+
102
+        // Register image variables only if custom-defined
103
+        foreach (ImageManager::SUPPORTED_IMAGE_KEYS as $image) {
104
+            if ($this->imageManager->hasImage($image)) {
105
+                $imageUrl = $this->imageManager->getImageUrl($image);
106
+                if ($image === 'background') {
107
+                    // If background deleted is set, ignoring variable
108
+                    if ($backgroundDeleted) {
109
+                        continue;
110
+                    }
111
+                    $variables['--image-background-size'] = 'cover';
112
+                }
113
+                // --image-background is overridden by user theming
114
+                $variables["--image-$image"] = "url('" . $imageUrl . "')";
115
+            }
116
+        }
117
+
118
+        if ($hasCustomLogoHeader) {
119
+            $variables["--image-logoheader-custom"] = 'true';
120
+        }
121
+
122
+        return $variables;
123
+    }
124
+
125
+    /**
126
+     * Generate user theming background-related variables
127
+     */
128
+    protected function generateUserBackgroundVariables(): array {
129
+        $user = $this->userSession->getUser();
130
+        if ($user !== null
131
+            && !$this->themingDefaults->isUserThemingDisabled()
132
+            && $this->appManager->isEnabledForUser(Application::APP_ID)) {
133
+            $backgroundImage = $this->config->getUserValue($user->getUID(), Application::APP_ID, 'background_image', BackgroundService::BACKGROUND_DEFAULT);
134
+            $currentVersion = (int)$this->config->getUserValue($user->getUID(), Application::APP_ID, 'userCacheBuster', '0');
135
+
136
+            // The user removed the background
137
+            if ($backgroundImage === BackgroundService::BACKGROUND_DISABLED) {
138
+                return [
139
+                    '--image-background' => 'no',
140
+                    '--color-background-plain' => $this->themingDefaults->getColorPrimary(),
141
+                ];
142
+            }
143
+
144
+            // The user uploaded a custom background
145
+            if ($backgroundImage === BackgroundService::BACKGROUND_CUSTOM) {
146
+                $cacheBuster = substr(sha1($user->getUID() . '_' . $currentVersion), 0, 8);
147
+                return [
148
+                    '--image-background' => "url('" . $this->urlGenerator->linkToRouteAbsolute('theming.userTheme.getBackground') . "?v=$cacheBuster')",
149
+                    '--color-background-plain' => $this->themingDefaults->getColorPrimary(),
150
+                ];
151
+            }
152
+
153
+            // The user picked a shipped background
154
+            if (isset(BackgroundService::SHIPPED_BACKGROUNDS[$backgroundImage])) {
155
+                return [
156
+                    '--image-background' => "url('" . $this->urlGenerator->linkTo(Application::APP_ID, "img/background/$backgroundImage") . "')",
157
+                    '--color-background-plain' => $this->themingDefaults->getColorPrimary(),
158
+                    '--background-image-invert-if-bright' => BackgroundService::SHIPPED_BACKGROUNDS[$backgroundImage]['theming'] ?? null === BackgroundService::THEMING_MODE_DARK ? 'invert(100%)' : 'no',
159
+                ];
160
+            }
161
+        }
162
+
163
+        return [];
164
+    }
165 165
 }
Please login to merge, or discard this patch.
Spacing   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -89,7 +89,7 @@  discard block
 block discarded – undo
89 89
 		$variables = [];
90 90
 
91 91
 		// Default last fallback values
92
-		$variables['--image-background-default'] = "url('" . $this->themingDefaults->getBackground() . "')";
92
+		$variables['--image-background-default'] = "url('".$this->themingDefaults->getBackground()."')";
93 93
 		$variables['--color-background-plain'] = $this->defaultPrimaryColor;
94 94
 
95 95
 		// If primary as background has been request or if we have a custom primary colour
@@ -111,7 +111,7 @@  discard block
 block discarded – undo
111 111
 					$variables['--image-background-size'] = 'cover';
112 112
 				}
113 113
 				// --image-background is overridden by user theming
114
-				$variables["--image-$image"] = "url('" . $imageUrl . "')";
114
+				$variables["--image-$image"] = "url('".$imageUrl."')";
115 115
 			}
116 116
 		}
117 117
 
@@ -131,7 +131,7 @@  discard block
 block discarded – undo
131 131
 			&& !$this->themingDefaults->isUserThemingDisabled()
132 132
 			&& $this->appManager->isEnabledForUser(Application::APP_ID)) {
133 133
 			$backgroundImage = $this->config->getUserValue($user->getUID(), Application::APP_ID, 'background_image', BackgroundService::BACKGROUND_DEFAULT);
134
-			$currentVersion = (int)$this->config->getUserValue($user->getUID(), Application::APP_ID, 'userCacheBuster', '0');
134
+			$currentVersion = (int) $this->config->getUserValue($user->getUID(), Application::APP_ID, 'userCacheBuster', '0');
135 135
 
136 136
 			// The user removed the background
137 137
 			if ($backgroundImage === BackgroundService::BACKGROUND_DISABLED) {
@@ -143,9 +143,9 @@  discard block
 block discarded – undo
143 143
 
144 144
 			// The user uploaded a custom background
145 145
 			if ($backgroundImage === BackgroundService::BACKGROUND_CUSTOM) {
146
-				$cacheBuster = substr(sha1($user->getUID() . '_' . $currentVersion), 0, 8);
146
+				$cacheBuster = substr(sha1($user->getUID().'_'.$currentVersion), 0, 8);
147 147
 				return [
148
-					'--image-background' => "url('" . $this->urlGenerator->linkToRouteAbsolute('theming.userTheme.getBackground') . "?v=$cacheBuster')",
148
+					'--image-background' => "url('".$this->urlGenerator->linkToRouteAbsolute('theming.userTheme.getBackground')."?v=$cacheBuster')",
149 149
 					'--color-background-plain' => $this->themingDefaults->getColorPrimary(),
150 150
 				];
151 151
 			}
@@ -153,7 +153,7 @@  discard block
 block discarded – undo
153 153
 			// The user picked a shipped background
154 154
 			if (isset(BackgroundService::SHIPPED_BACKGROUNDS[$backgroundImage])) {
155 155
 				return [
156
-					'--image-background' => "url('" . $this->urlGenerator->linkTo(Application::APP_ID, "img/background/$backgroundImage") . "')",
156
+					'--image-background' => "url('".$this->urlGenerator->linkTo(Application::APP_ID, "img/background/$backgroundImage")."')",
157 157
 					'--color-background-plain' => $this->themingDefaults->getColorPrimary(),
158 158
 					'--background-image-invert-if-bright' => BackgroundService::SHIPPED_BACKGROUNDS[$backgroundImage]['theming'] ?? null === BackgroundService::THEMING_MODE_DARK ? 'invert(100%)' : 'no',
159 159
 				];
Please login to merge, or discard this patch.
apps/theming/lib/Themes/DefaultTheme.php 2 patches
Indentation   +167 added lines, -167 removed lines patch added patch discarded remove patch
@@ -36,171 +36,171 @@
 block discarded – undo
36 36
 use OCP\IUserSession;
37 37
 
38 38
 class DefaultTheme implements ITheme {
39
-	use CommonThemeTrait;
40
-
41
-	public Util $util;
42
-	public ThemingDefaults $themingDefaults;
43
-	public IUserSession $userSession;
44
-	public IURLGenerator $urlGenerator;
45
-	public ImageManager $imageManager;
46
-	public IConfig $config;
47
-	public IL10N $l;
48
-	public IAppManager $appManager;
49
-
50
-	public string $defaultPrimaryColor;
51
-	public string $primaryColor;
52
-
53
-	public function __construct(Util $util,
54
-								ThemingDefaults $themingDefaults,
55
-								IUserSession $userSession,
56
-								IURLGenerator $urlGenerator,
57
-								ImageManager $imageManager,
58
-								IConfig $config,
59
-								IL10N $l,
60
-								IAppManager $appManager) {
61
-		$this->util = $util;
62
-		$this->themingDefaults = $themingDefaults;
63
-		$this->userSession = $userSession;
64
-		$this->urlGenerator = $urlGenerator;
65
-		$this->imageManager = $imageManager;
66
-		$this->config = $config;
67
-		$this->l = $l;
68
-		$this->appManager = $appManager;
69
-
70
-		$this->defaultPrimaryColor = $this->themingDefaults->getDefaultColorPrimary();
71
-		$this->primaryColor = $this->themingDefaults->getColorPrimary();
72
-
73
-		// Override default defaultPrimaryColor if set to improve accessibility
74
-		if ($this->primaryColor === BackgroundService::DEFAULT_COLOR) {
75
-			$this->primaryColor = BackgroundService::DEFAULT_ACCESSIBLE_COLOR;
76
-		}
77
-	}
78
-
79
-	public function getId(): string {
80
-		return 'default';
81
-	}
82
-
83
-	public function getType(): int {
84
-		return ITheme::TYPE_THEME;
85
-	}
86
-
87
-	public function getTitle(): string {
88
-		return $this->l->t('System default theme');
89
-	}
90
-
91
-	public function getEnableLabel(): string {
92
-		return $this->l->t('Enable the system default');
93
-	}
94
-
95
-	public function getDescription(): string {
96
-		return $this->l->t('Using the default system appearance.');
97
-	}
98
-
99
-	public function getMediaQuery(): string {
100
-		return '';
101
-	}
102
-
103
-	public function getCSSVariables(): array {
104
-		$colorMainText = '#222222';
105
-		$colorMainTextRgb = join(',', $this->util->hexToRGB($colorMainText));
106
-		$colorTextMaxcontrast = $this->util->lighten($colorMainText, 33);
107
-		$colorMainBackground = '#ffffff';
108
-		$colorMainBackgroundRGB = join(',', $this->util->hexToRGB($colorMainBackground));
109
-		$colorBoxShadow = $this->util->darken($colorMainBackground, 70);
110
-		$colorBoxShadowRGB = join(',', $this->util->hexToRGB($colorBoxShadow));
111
-
112
-		$variables = [
113
-			'--color-main-background' => $colorMainBackground,
114
-			'--color-main-background-rgb' => $colorMainBackgroundRGB,
115
-			'--color-main-background-translucent' => 'rgba(var(--color-main-background-rgb), .97)',
116
-			'--color-main-background-blur' => 'rgba(var(--color-main-background-rgb), .8)',
117
-			'--filter-background-blur' => 'blur(25px)',
118
-
119
-			// to use like this: background-image: linear-gradient(0, var('--gradient-main-background));
120
-			'--gradient-main-background' => 'var(--color-main-background) 0%, var(--color-main-background-translucent) 85%, transparent 100%',
121
-
122
-			// used for different active/hover/focus/disabled states
123
-			'--color-background-hover' => $this->util->darken($colorMainBackground, 4),
124
-			'--color-background-dark' => $this->util->darken($colorMainBackground, 7),
125
-			'--color-background-darker' => $this->util->darken($colorMainBackground, 14),
126
-
127
-			'--color-placeholder-light' => $this->util->darken($colorMainBackground, 10),
128
-			'--color-placeholder-dark' => $this->util->darken($colorMainBackground, 20),
129
-
130
-			// max contrast for WCAG compliance
131
-			'--color-main-text' => $colorMainText,
132
-			'--color-text-maxcontrast' => $colorTextMaxcontrast,
133
-			'--color-text-maxcontrast-default' => $colorTextMaxcontrast,
134
-			'--color-text-maxcontrast-background-blur' => $this->util->darken($colorTextMaxcontrast, 7),
135
-			'--color-text-light' => $colorMainText,
136
-			'--color-text-lighter' => $this->util->lighten($colorMainText, 33),
137
-
138
-			'--color-scrollbar' => 'rgba(' . $colorMainTextRgb . ', .15)',
139
-
140
-			// info/warning/success feedback colours
141
-			'--color-error' => '#e9322d',
142
-			'--color-error-rgb' => join(',', $this->util->hexToRGB('#e9322d')),
143
-			'--color-error-hover' => $this->util->mix('#e9322d', $colorMainBackground, 60),
144
-			'--color-warning' => '#eca700',
145
-			'--color-warning-rgb' => join(',', $this->util->hexToRGB('#eca700')),
146
-			'--color-warning-hover' => $this->util->mix('#eca700', $colorMainBackground, 60),
147
-			'--color-success' => '#46ba61',
148
-			'--color-success-rgb' => join(',', $this->util->hexToRGB('#46ba61')),
149
-			'--color-success-hover' => $this->util->mix('#46ba61', $colorMainBackground, 60),
150
-
151
-			// used for the icon loading animation
152
-			'--color-loading-light' => '#cccccc',
153
-			'--color-loading-dark' => '#444444',
154
-
155
-			'--color-box-shadow-rgb' => $colorBoxShadowRGB,
156
-			'--color-box-shadow' => "rgba(var(--color-box-shadow-rgb), 0.5)",
157
-
158
-			'--color-border' => $this->util->darken($colorMainBackground, 42),
159
-			'--color-border-dark' => $this->util->darken($colorMainBackground, 50),
160
-
161
-			'--font-face' => "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Cantarell, Ubuntu, 'Helvetica Neue', Arial, sans-serif, 'Noto Color Emoji', 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'",
162
-			'--default-font-size' => '15px',
163
-
164
-			// TODO: support "(prefers-reduced-motion)"
165
-			'--animation-quick' => '100ms',
166
-			'--animation-slow' => '300ms',
167
-
168
-			// Default variables --------------------------------------------
169
-			'--border-radius' => '3px',
170
-			'--border-radius-large' => '10px',
171
-			// pill-style button, value is large so big buttons also have correct roundness
172
-			'--border-radius-pill' => '100px',
173
-
174
-			'--default-clickable-area' => '44px',
175
-			'--default-line-height' => '24px',
176
-			'--default-grid-baseline' => '4px',
177
-
178
-			// various structure data
179
-			'--header-height' => '50px',
180
-			'--navigation-width' => '300px',
181
-			'--sidebar-min-width' => '300px',
182
-			'--sidebar-max-width' => '500px',
183
-			'--list-min-width' => '200px',
184
-			'--list-max-width' => '300px',
185
-			'--header-menu-item-height' => '44px',
186
-			'--header-menu-profile-item-height' => '66px',
187
-
188
-			// mobile. Keep in sync with core/js/js.js
189
-			'--breakpoint-mobile' => '1024px',
190
-			'--background-invert-if-dark' => 'no',
191
-			'--background-invert-if-bright' => 'invert(100%)',
192
-			'--background-image-invert-if-bright' => 'no',
193
-		];
194
-
195
-		// Primary variables
196
-		$variables = array_merge($variables, $this->generatePrimaryVariables($colorMainBackground, $colorMainText));
197
-		$variables = array_merge($variables, $this->generateGlobalBackgroundVariables());
198
-		$variables = array_merge($variables, $this->generateUserBackgroundVariables());
199
-
200
-		return $variables;
201
-	}
202
-
203
-	public function getCustomCss(): string {
204
-		return '';
205
-	}
39
+    use CommonThemeTrait;
40
+
41
+    public Util $util;
42
+    public ThemingDefaults $themingDefaults;
43
+    public IUserSession $userSession;
44
+    public IURLGenerator $urlGenerator;
45
+    public ImageManager $imageManager;
46
+    public IConfig $config;
47
+    public IL10N $l;
48
+    public IAppManager $appManager;
49
+
50
+    public string $defaultPrimaryColor;
51
+    public string $primaryColor;
52
+
53
+    public function __construct(Util $util,
54
+                                ThemingDefaults $themingDefaults,
55
+                                IUserSession $userSession,
56
+                                IURLGenerator $urlGenerator,
57
+                                ImageManager $imageManager,
58
+                                IConfig $config,
59
+                                IL10N $l,
60
+                                IAppManager $appManager) {
61
+        $this->util = $util;
62
+        $this->themingDefaults = $themingDefaults;
63
+        $this->userSession = $userSession;
64
+        $this->urlGenerator = $urlGenerator;
65
+        $this->imageManager = $imageManager;
66
+        $this->config = $config;
67
+        $this->l = $l;
68
+        $this->appManager = $appManager;
69
+
70
+        $this->defaultPrimaryColor = $this->themingDefaults->getDefaultColorPrimary();
71
+        $this->primaryColor = $this->themingDefaults->getColorPrimary();
72
+
73
+        // Override default defaultPrimaryColor if set to improve accessibility
74
+        if ($this->primaryColor === BackgroundService::DEFAULT_COLOR) {
75
+            $this->primaryColor = BackgroundService::DEFAULT_ACCESSIBLE_COLOR;
76
+        }
77
+    }
78
+
79
+    public function getId(): string {
80
+        return 'default';
81
+    }
82
+
83
+    public function getType(): int {
84
+        return ITheme::TYPE_THEME;
85
+    }
86
+
87
+    public function getTitle(): string {
88
+        return $this->l->t('System default theme');
89
+    }
90
+
91
+    public function getEnableLabel(): string {
92
+        return $this->l->t('Enable the system default');
93
+    }
94
+
95
+    public function getDescription(): string {
96
+        return $this->l->t('Using the default system appearance.');
97
+    }
98
+
99
+    public function getMediaQuery(): string {
100
+        return '';
101
+    }
102
+
103
+    public function getCSSVariables(): array {
104
+        $colorMainText = '#222222';
105
+        $colorMainTextRgb = join(',', $this->util->hexToRGB($colorMainText));
106
+        $colorTextMaxcontrast = $this->util->lighten($colorMainText, 33);
107
+        $colorMainBackground = '#ffffff';
108
+        $colorMainBackgroundRGB = join(',', $this->util->hexToRGB($colorMainBackground));
109
+        $colorBoxShadow = $this->util->darken($colorMainBackground, 70);
110
+        $colorBoxShadowRGB = join(',', $this->util->hexToRGB($colorBoxShadow));
111
+
112
+        $variables = [
113
+            '--color-main-background' => $colorMainBackground,
114
+            '--color-main-background-rgb' => $colorMainBackgroundRGB,
115
+            '--color-main-background-translucent' => 'rgba(var(--color-main-background-rgb), .97)',
116
+            '--color-main-background-blur' => 'rgba(var(--color-main-background-rgb), .8)',
117
+            '--filter-background-blur' => 'blur(25px)',
118
+
119
+            // to use like this: background-image: linear-gradient(0, var('--gradient-main-background));
120
+            '--gradient-main-background' => 'var(--color-main-background) 0%, var(--color-main-background-translucent) 85%, transparent 100%',
121
+
122
+            // used for different active/hover/focus/disabled states
123
+            '--color-background-hover' => $this->util->darken($colorMainBackground, 4),
124
+            '--color-background-dark' => $this->util->darken($colorMainBackground, 7),
125
+            '--color-background-darker' => $this->util->darken($colorMainBackground, 14),
126
+
127
+            '--color-placeholder-light' => $this->util->darken($colorMainBackground, 10),
128
+            '--color-placeholder-dark' => $this->util->darken($colorMainBackground, 20),
129
+
130
+            // max contrast for WCAG compliance
131
+            '--color-main-text' => $colorMainText,
132
+            '--color-text-maxcontrast' => $colorTextMaxcontrast,
133
+            '--color-text-maxcontrast-default' => $colorTextMaxcontrast,
134
+            '--color-text-maxcontrast-background-blur' => $this->util->darken($colorTextMaxcontrast, 7),
135
+            '--color-text-light' => $colorMainText,
136
+            '--color-text-lighter' => $this->util->lighten($colorMainText, 33),
137
+
138
+            '--color-scrollbar' => 'rgba(' . $colorMainTextRgb . ', .15)',
139
+
140
+            // info/warning/success feedback colours
141
+            '--color-error' => '#e9322d',
142
+            '--color-error-rgb' => join(',', $this->util->hexToRGB('#e9322d')),
143
+            '--color-error-hover' => $this->util->mix('#e9322d', $colorMainBackground, 60),
144
+            '--color-warning' => '#eca700',
145
+            '--color-warning-rgb' => join(',', $this->util->hexToRGB('#eca700')),
146
+            '--color-warning-hover' => $this->util->mix('#eca700', $colorMainBackground, 60),
147
+            '--color-success' => '#46ba61',
148
+            '--color-success-rgb' => join(',', $this->util->hexToRGB('#46ba61')),
149
+            '--color-success-hover' => $this->util->mix('#46ba61', $colorMainBackground, 60),
150
+
151
+            // used for the icon loading animation
152
+            '--color-loading-light' => '#cccccc',
153
+            '--color-loading-dark' => '#444444',
154
+
155
+            '--color-box-shadow-rgb' => $colorBoxShadowRGB,
156
+            '--color-box-shadow' => "rgba(var(--color-box-shadow-rgb), 0.5)",
157
+
158
+            '--color-border' => $this->util->darken($colorMainBackground, 42),
159
+            '--color-border-dark' => $this->util->darken($colorMainBackground, 50),
160
+
161
+            '--font-face' => "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Cantarell, Ubuntu, 'Helvetica Neue', Arial, sans-serif, 'Noto Color Emoji', 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'",
162
+            '--default-font-size' => '15px',
163
+
164
+            // TODO: support "(prefers-reduced-motion)"
165
+            '--animation-quick' => '100ms',
166
+            '--animation-slow' => '300ms',
167
+
168
+            // Default variables --------------------------------------------
169
+            '--border-radius' => '3px',
170
+            '--border-radius-large' => '10px',
171
+            // pill-style button, value is large so big buttons also have correct roundness
172
+            '--border-radius-pill' => '100px',
173
+
174
+            '--default-clickable-area' => '44px',
175
+            '--default-line-height' => '24px',
176
+            '--default-grid-baseline' => '4px',
177
+
178
+            // various structure data
179
+            '--header-height' => '50px',
180
+            '--navigation-width' => '300px',
181
+            '--sidebar-min-width' => '300px',
182
+            '--sidebar-max-width' => '500px',
183
+            '--list-min-width' => '200px',
184
+            '--list-max-width' => '300px',
185
+            '--header-menu-item-height' => '44px',
186
+            '--header-menu-profile-item-height' => '66px',
187
+
188
+            // mobile. Keep in sync with core/js/js.js
189
+            '--breakpoint-mobile' => '1024px',
190
+            '--background-invert-if-dark' => 'no',
191
+            '--background-invert-if-bright' => 'invert(100%)',
192
+            '--background-image-invert-if-bright' => 'no',
193
+        ];
194
+
195
+        // Primary variables
196
+        $variables = array_merge($variables, $this->generatePrimaryVariables($colorMainBackground, $colorMainText));
197
+        $variables = array_merge($variables, $this->generateGlobalBackgroundVariables());
198
+        $variables = array_merge($variables, $this->generateUserBackgroundVariables());
199
+
200
+        return $variables;
201
+    }
202
+
203
+    public function getCustomCss(): string {
204
+        return '';
205
+    }
206 206
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -135,7 +135,7 @@
 block discarded – undo
135 135
 			'--color-text-light' => $colorMainText,
136 136
 			'--color-text-lighter' => $this->util->lighten($colorMainText, 33),
137 137
 
138
-			'--color-scrollbar' => 'rgba(' . $colorMainTextRgb . ', .15)',
138
+			'--color-scrollbar' => 'rgba('.$colorMainTextRgb.', .15)',
139 139
 
140 140
 			// info/warning/success feedback colours
141 141
 			'--color-error' => '#e9322d',
Please login to merge, or discard this patch.
apps/theming/lib/Listener/BeforeTemplateRenderedListener.php 1 patch
Indentation   +79 added lines, -79 removed lines patch added patch discarded remove patch
@@ -40,83 +40,83 @@
 block discarded – undo
40 40
 
41 41
 class BeforeTemplateRenderedListener implements IEventListener {
42 42
 
43
-	private IInitialState $initialState;
44
-	private ContainerInterface $container;
45
-	private ThemeInjectionService $themeInjectionService;
46
-	private IUserSession $userSession;
47
-	private IConfig $config;
48
-
49
-	public function __construct(
50
-		IInitialState $initialState,
51
-		ContainerInterface $container,
52
-		ThemeInjectionService $themeInjectionService,
53
-		IUserSession $userSession,
54
-		IConfig $config
55
-	) {
56
-		$this->initialState = $initialState;
57
-		$this->container = $container;
58
-		$this->themeInjectionService = $themeInjectionService;
59
-		$this->userSession = $userSession;
60
-		$this->config = $config;
61
-	}
62
-
63
-	public function handle(Event $event): void {
64
-		$this->initialState->provideLazyInitialState(
65
-			'data',
66
-			fn () => $this->container->get(JSDataService::class),
67
-		);
68
-
69
-		/** @var BeforeTemplateRenderedEvent $event */
70
-		if ($event->getResponse()->getRenderAs() === TemplateResponse::RENDER_AS_USER) {
71
-			$this->initialState->provideLazyInitialState('shortcutsDisabled', function () {
72
-				if ($this->userSession->getUser()) {
73
-					$uid = $this->userSession->getUser()->getUID();
74
-					return $this->config->getUserValue($uid, Application::APP_ID, 'shortcuts_disabled', 'no') === 'yes';
75
-				}
76
-				return false;
77
-			});
78
-		}
79
-
80
-		$this->themeInjectionService->injectHeaders();
81
-
82
-		$user = $this->userSession->getUser();
83
-
84
-		if (!empty($user)) {
85
-			$userId = $user->getUID();
86
-
87
-			/** User background */
88
-			$this->initialState->provideInitialState(
89
-				'backgroundImage',
90
-				$this->config->getUserValue($userId, Application::APP_ID, 'background_image', BackgroundService::BACKGROUND_DEFAULT),
91
-			);
92
-
93
-			/** User color */
94
-			$this->initialState->provideInitialState(
95
-				'backgroundColor',
96
-				$this->config->getUserValue($userId, Application::APP_ID, 'background_color', BackgroundService::DEFAULT_COLOR),
97
-			);
98
-
99
-			/** 
100
-			 * Admin background. `backgroundColor` if disabled,
101
-			 * mime type if defined and empty by default
102
-			 */
103
-			$this->initialState->provideInitialState(
104
-				'themingDefaultBackground',
105
-				 $this->config->getAppValue('theming', 'backgroundMime', ''),
106
-			);
107
-			$this->initialState->provideInitialState(
108
-				'defaultShippedBackground',
109
-				 BackgroundService::DEFAULT_BACKGROUND_IMAGE,
110
-			);
111
-
112
-			/** List of all shipped backgrounds */
113
-			$this->initialState->provideInitialState(
114
-				'shippedBackgrounds',
115
-				 BackgroundService::SHIPPED_BACKGROUNDS,
116
-			);
117
-		}
118
-
119
-		// Making sure to inject just after core
120
-		\OCP\Util::addScript('theming', 'theming', 'core');
121
-	}
43
+    private IInitialState $initialState;
44
+    private ContainerInterface $container;
45
+    private ThemeInjectionService $themeInjectionService;
46
+    private IUserSession $userSession;
47
+    private IConfig $config;
48
+
49
+    public function __construct(
50
+        IInitialState $initialState,
51
+        ContainerInterface $container,
52
+        ThemeInjectionService $themeInjectionService,
53
+        IUserSession $userSession,
54
+        IConfig $config
55
+    ) {
56
+        $this->initialState = $initialState;
57
+        $this->container = $container;
58
+        $this->themeInjectionService = $themeInjectionService;
59
+        $this->userSession = $userSession;
60
+        $this->config = $config;
61
+    }
62
+
63
+    public function handle(Event $event): void {
64
+        $this->initialState->provideLazyInitialState(
65
+            'data',
66
+            fn () => $this->container->get(JSDataService::class),
67
+        );
68
+
69
+        /** @var BeforeTemplateRenderedEvent $event */
70
+        if ($event->getResponse()->getRenderAs() === TemplateResponse::RENDER_AS_USER) {
71
+            $this->initialState->provideLazyInitialState('shortcutsDisabled', function () {
72
+                if ($this->userSession->getUser()) {
73
+                    $uid = $this->userSession->getUser()->getUID();
74
+                    return $this->config->getUserValue($uid, Application::APP_ID, 'shortcuts_disabled', 'no') === 'yes';
75
+                }
76
+                return false;
77
+            });
78
+        }
79
+
80
+        $this->themeInjectionService->injectHeaders();
81
+
82
+        $user = $this->userSession->getUser();
83
+
84
+        if (!empty($user)) {
85
+            $userId = $user->getUID();
86
+
87
+            /** User background */
88
+            $this->initialState->provideInitialState(
89
+                'backgroundImage',
90
+                $this->config->getUserValue($userId, Application::APP_ID, 'background_image', BackgroundService::BACKGROUND_DEFAULT),
91
+            );
92
+
93
+            /** User color */
94
+            $this->initialState->provideInitialState(
95
+                'backgroundColor',
96
+                $this->config->getUserValue($userId, Application::APP_ID, 'background_color', BackgroundService::DEFAULT_COLOR),
97
+            );
98
+
99
+            /** 
100
+             * Admin background. `backgroundColor` if disabled,
101
+             * mime type if defined and empty by default
102
+             */
103
+            $this->initialState->provideInitialState(
104
+                'themingDefaultBackground',
105
+                    $this->config->getAppValue('theming', 'backgroundMime', ''),
106
+            );
107
+            $this->initialState->provideInitialState(
108
+                'defaultShippedBackground',
109
+                    BackgroundService::DEFAULT_BACKGROUND_IMAGE,
110
+            );
111
+
112
+            /** List of all shipped backgrounds */
113
+            $this->initialState->provideInitialState(
114
+                'shippedBackgrounds',
115
+                    BackgroundService::SHIPPED_BACKGROUNDS,
116
+            );
117
+        }
118
+
119
+        // Making sure to inject just after core
120
+        \OCP\Util::addScript('theming', 'theming', 'core');
121
+    }
122 122
 }
Please login to merge, or discard this patch.
apps/theming/lib/ImageManager.php 2 patches
Indentation   +289 added lines, -289 removed lines patch added patch discarded remove patch
@@ -47,293 +47,293 @@
 block discarded – undo
47 47
 use OCP\IURLGenerator;
48 48
 
49 49
 class ImageManager {
50
-	public const SUPPORTED_IMAGE_KEYS = ['background', 'logo', 'logoheader', 'favicon'];
51
-
52
-	/** @var IConfig */
53
-	private $config;
54
-	/** @var IAppData */
55
-	private $appData;
56
-	/** @var IURLGenerator */
57
-	private $urlGenerator;
58
-	/** @var ICacheFactory */
59
-	private $cacheFactory;
60
-	/** @var ILogger */
61
-	private $logger;
62
-	/** @var ITempManager */
63
-	private $tempManager;
64
-
65
-	public function __construct(IConfig $config,
66
-								IAppData $appData,
67
-								IURLGenerator $urlGenerator,
68
-								ICacheFactory $cacheFactory,
69
-								ILogger $logger,
70
-								ITempManager $tempManager) {
71
-		$this->config = $config;
72
-		$this->urlGenerator = $urlGenerator;
73
-		$this->cacheFactory = $cacheFactory;
74
-		$this->logger = $logger;
75
-		$this->tempManager = $tempManager;
76
-		$this->appData = $appData;
77
-	}
78
-
79
-	/**
80
-	 * Get a globally defined image (admin theming settings)
81
-	 *
82
-	 * @param string $key the image key
83
-	 * @return string the image url
84
-	 */
85
-	public function getImageUrl(string $key): string {
86
-		$cacheBusterCounter = $this->config->getAppValue(Application::APP_ID, 'cachebuster', '0');
87
-		if ($this->hasImage($key)) {
88
-			return $this->urlGenerator->linkToRoute('theming.Theming.getImage', [ 'key' => $key ]) . '?v=' . $cacheBusterCounter;
89
-		}
90
-
91
-		switch ($key) {
92
-			case 'logo':
93
-			case 'logoheader':
94
-			case 'favicon':
95
-				return $this->urlGenerator->imagePath('core', 'logo/logo.png') . '?v=' . $cacheBusterCounter;
96
-			case 'background':
97
-				return $this->urlGenerator->linkTo(Application::APP_ID, 'img/background/' . BackgroundService::DEFAULT_BACKGROUND_IMAGE);
98
-		}
99
-		return '';
100
-	}
101
-
102
-	/**
103
-	 * Get the absolute url. See getImageUrl
104
-	 */
105
-	public function getImageUrlAbsolute(string $key): string {
106
-		return $this->urlGenerator->getAbsoluteURL($this->getImageUrl($key));
107
-	}
108
-
109
-	/**
110
-	 * @param string $key
111
-	 * @param bool $useSvg
112
-	 * @return ISimpleFile
113
-	 * @throws NotFoundException
114
-	 * @throws NotPermittedException
115
-	 */
116
-	public function getImage(string $key, bool $useSvg = true): ISimpleFile {
117
-		$logo = $this->config->getAppValue('theming', $key . 'Mime', '');
118
-		$folder = $this->getRootFolder()->getFolder('images');
119
-
120
-		if ($logo === '' || !$folder->fileExists($key)) {
121
-			throw new NotFoundException();
122
-		}
123
-
124
-		if (!$useSvg && $this->shouldReplaceIcons()) {
125
-			if (!$folder->fileExists($key . '.png')) {
126
-				try {
127
-					$finalIconFile = new \Imagick();
128
-					$finalIconFile->setBackgroundColor('none');
129
-					$finalIconFile->readImageBlob($folder->getFile($key)->getContent());
130
-					$finalIconFile->setImageFormat('png32');
131
-					$pngFile = $folder->newFile($key . '.png');
132
-					$pngFile->putContent($finalIconFile->getImageBlob());
133
-					return $pngFile;
134
-				} catch (\ImagickException $e) {
135
-					$this->logger->info('The image was requested to be no SVG file, but converting it to PNG failed: ' . $e->getMessage());
136
-				}
137
-			} else {
138
-				return $folder->getFile($key . '.png');
139
-			}
140
-		}
141
-
142
-		return $folder->getFile($key);
143
-	}
144
-
145
-	public function hasImage(string $key): bool {
146
-		$mimeSetting = $this->config->getAppValue('theming', $key . 'Mime', '');
147
-		return $mimeSetting !== '';
148
-	}
149
-
150
-	/**
151
-	 * @return array<string, array{mime: string, url: string}>
152
-	 */
153
-	public function getCustomImages(): array {
154
-		$images = [];
155
-		foreach (self::SUPPORTED_IMAGE_KEYS as $key) {
156
-			$images[$key] = [
157
-				'mime' => $this->config->getAppValue('theming', $key . 'Mime', ''),
158
-				'url' => $this->getImageUrl($key),
159
-			];
160
-		}
161
-		return $images;
162
-	}
163
-
164
-	/**
165
-	 * Get folder for current theming files
166
-	 *
167
-	 * @return ISimpleFolder
168
-	 * @throws NotPermittedException
169
-	 */
170
-	public function getCacheFolder(): ISimpleFolder {
171
-		$cacheBusterValue = $this->config->getAppValue('theming', 'cachebuster', '0');
172
-		try {
173
-			$folder = $this->getRootFolder()->getFolder($cacheBusterValue);
174
-		} catch (NotFoundException $e) {
175
-			$folder = $this->getRootFolder()->newFolder($cacheBusterValue);
176
-			$this->cleanup();
177
-		}
178
-		return $folder;
179
-	}
180
-
181
-	/**
182
-	 * Get a file from AppData
183
-	 *
184
-	 * @param string $filename
185
-	 * @throws NotFoundException
186
-	 * @return \OCP\Files\SimpleFS\ISimpleFile
187
-	 * @throws NotPermittedException
188
-	 */
189
-	public function getCachedImage(string $filename): ISimpleFile {
190
-		$currentFolder = $this->getCacheFolder();
191
-		return $currentFolder->getFile($filename);
192
-	}
193
-
194
-	/**
195
-	 * Store a file for theming in AppData
196
-	 *
197
-	 * @param string $filename
198
-	 * @param string $data
199
-	 * @return \OCP\Files\SimpleFS\ISimpleFile
200
-	 * @throws NotFoundException
201
-	 * @throws NotPermittedException
202
-	 */
203
-	public function setCachedImage(string $filename, string $data): ISimpleFile {
204
-		$currentFolder = $this->getCacheFolder();
205
-		if ($currentFolder->fileExists($filename)) {
206
-			$file = $currentFolder->getFile($filename);
207
-		} else {
208
-			$file = $currentFolder->newFile($filename);
209
-		}
210
-		$file->putContent($data);
211
-		return $file;
212
-	}
213
-
214
-	public function delete(string $key): void {
215
-		/* ignore exceptions, since we don't want to fail hard if something goes wrong during cleanup */
216
-		try {
217
-			$file = $this->getRootFolder()->getFolder('images')->getFile($key);
218
-			$file->delete();
219
-		} catch (NotFoundException $e) {
220
-		} catch (NotPermittedException $e) {
221
-		}
222
-		try {
223
-			$file = $this->getRootFolder()->getFolder('images')->getFile($key . '.png');
224
-			$file->delete();
225
-		} catch (NotFoundException $e) {
226
-		} catch (NotPermittedException $e) {
227
-		}
228
-	}
229
-
230
-	public function updateImage(string $key, string $tmpFile): string {
231
-		$this->delete($key);
232
-
233
-		try {
234
-			$folder = $this->getRootFolder()->getFolder('images');
235
-		} catch (NotFoundException $e) {
236
-			$folder = $this->getRootFolder()->newFolder('images');
237
-		}
238
-
239
-		$target = $folder->newFile($key);
240
-		$supportedFormats = $this->getSupportedUploadImageFormats($key);
241
-		$detectedMimeType = mime_content_type($tmpFile);
242
-		if (!in_array($detectedMimeType, $supportedFormats, true)) {
243
-			throw new \Exception('Unsupported image type');
244
-		}
245
-
246
-		if ($key === 'background' && strpos($detectedMimeType, 'image/svg') === false && strpos($detectedMimeType, 'image/gif') === false) {
247
-			// Optimize the image since some people may upload images that will be
248
-			// either to big or are not progressive rendering.
249
-			$newImage = @imagecreatefromstring(file_get_contents($tmpFile));
250
-
251
-			// Preserve transparency
252
-			imagesavealpha($newImage, true);
253
-			imagealphablending($newImage, true);
254
-
255
-			$tmpFile = $this->tempManager->getTemporaryFile();
256
-			$newWidth = (int)(imagesx($newImage) < 4096 ? imagesx($newImage) : 4096);
257
-			$newHeight = (int)(imagesy($newImage) / (imagesx($newImage) / $newWidth));
258
-			$outputImage = imagescale($newImage, $newWidth, $newHeight);
259
-
260
-			imageinterlace($outputImage, 1);
261
-			imagepng($outputImage, $tmpFile, 8);
262
-			imagedestroy($outputImage);
263
-
264
-			$target->putContent(file_get_contents($tmpFile));
265
-		} else {
266
-			$target->putContent(file_get_contents($tmpFile));
267
-		}
268
-
269
-		return $detectedMimeType;
270
-	}
271
-
272
-	/**
273
-	 * Returns a list of supported mime types for image uploads.
274
-	 * "favicon" images are only allowed to be SVG when imagemagick with SVG support is available.
275
-	 *
276
-	 * @param string $key The image key, e.g. "favicon"
277
-	 * @return string[]
278
-	 */
279
-	private function getSupportedUploadImageFormats(string $key): array {
280
-		$supportedFormats = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
281
-
282
-		if ($key !== 'favicon' || $this->shouldReplaceIcons() === true) {
283
-			$supportedFormats[] = 'image/svg+xml';
284
-			$supportedFormats[] = 'image/svg';
285
-		}
286
-
287
-		if ($key === 'favicon') {
288
-			$supportedFormats[] = 'image/x-icon';
289
-			$supportedFormats[] = 'image/vnd.microsoft.icon';
290
-		}
291
-
292
-		return $supportedFormats;
293
-	}
294
-
295
-	/**
296
-	 * remove cached files that are not required any longer
297
-	 *
298
-	 * @throws NotPermittedException
299
-	 * @throws NotFoundException
300
-	 */
301
-	public function cleanup() {
302
-		$currentFolder = $this->getCacheFolder();
303
-		$folders = $this->getRootFolder()->getDirectoryListing();
304
-		foreach ($folders as $folder) {
305
-			if ($folder->getName() !== 'images' && $folder->getName() !== $currentFolder->getName()) {
306
-				$folder->delete();
307
-			}
308
-		}
309
-	}
310
-
311
-	/**
312
-	 * Check if Imagemagick is enabled and if SVG is supported
313
-	 * otherwise we can't render custom icons
314
-	 *
315
-	 * @return bool
316
-	 */
317
-	public function shouldReplaceIcons() {
318
-		$cache = $this->cacheFactory->createDistributed('theming-' . $this->urlGenerator->getBaseUrl());
319
-		if ($value = $cache->get('shouldReplaceIcons')) {
320
-			return (bool)$value;
321
-		}
322
-		$value = false;
323
-		if (extension_loaded('imagick')) {
324
-			if (count(\Imagick::queryFormats('SVG')) >= 1) {
325
-				$value = true;
326
-			}
327
-		}
328
-		$cache->set('shouldReplaceIcons', $value);
329
-		return $value;
330
-	}
331
-
332
-	private function getRootFolder(): ISimpleFolder {
333
-		try {
334
-			return $this->appData->getFolder('global');
335
-		} catch (NotFoundException $e) {
336
-			return $this->appData->newFolder('global');
337
-		}
338
-	}
50
+    public const SUPPORTED_IMAGE_KEYS = ['background', 'logo', 'logoheader', 'favicon'];
51
+
52
+    /** @var IConfig */
53
+    private $config;
54
+    /** @var IAppData */
55
+    private $appData;
56
+    /** @var IURLGenerator */
57
+    private $urlGenerator;
58
+    /** @var ICacheFactory */
59
+    private $cacheFactory;
60
+    /** @var ILogger */
61
+    private $logger;
62
+    /** @var ITempManager */
63
+    private $tempManager;
64
+
65
+    public function __construct(IConfig $config,
66
+                                IAppData $appData,
67
+                                IURLGenerator $urlGenerator,
68
+                                ICacheFactory $cacheFactory,
69
+                                ILogger $logger,
70
+                                ITempManager $tempManager) {
71
+        $this->config = $config;
72
+        $this->urlGenerator = $urlGenerator;
73
+        $this->cacheFactory = $cacheFactory;
74
+        $this->logger = $logger;
75
+        $this->tempManager = $tempManager;
76
+        $this->appData = $appData;
77
+    }
78
+
79
+    /**
80
+     * Get a globally defined image (admin theming settings)
81
+     *
82
+     * @param string $key the image key
83
+     * @return string the image url
84
+     */
85
+    public function getImageUrl(string $key): string {
86
+        $cacheBusterCounter = $this->config->getAppValue(Application::APP_ID, 'cachebuster', '0');
87
+        if ($this->hasImage($key)) {
88
+            return $this->urlGenerator->linkToRoute('theming.Theming.getImage', [ 'key' => $key ]) . '?v=' . $cacheBusterCounter;
89
+        }
90
+
91
+        switch ($key) {
92
+            case 'logo':
93
+            case 'logoheader':
94
+            case 'favicon':
95
+                return $this->urlGenerator->imagePath('core', 'logo/logo.png') . '?v=' . $cacheBusterCounter;
96
+            case 'background':
97
+                return $this->urlGenerator->linkTo(Application::APP_ID, 'img/background/' . BackgroundService::DEFAULT_BACKGROUND_IMAGE);
98
+        }
99
+        return '';
100
+    }
101
+
102
+    /**
103
+     * Get the absolute url. See getImageUrl
104
+     */
105
+    public function getImageUrlAbsolute(string $key): string {
106
+        return $this->urlGenerator->getAbsoluteURL($this->getImageUrl($key));
107
+    }
108
+
109
+    /**
110
+     * @param string $key
111
+     * @param bool $useSvg
112
+     * @return ISimpleFile
113
+     * @throws NotFoundException
114
+     * @throws NotPermittedException
115
+     */
116
+    public function getImage(string $key, bool $useSvg = true): ISimpleFile {
117
+        $logo = $this->config->getAppValue('theming', $key . 'Mime', '');
118
+        $folder = $this->getRootFolder()->getFolder('images');
119
+
120
+        if ($logo === '' || !$folder->fileExists($key)) {
121
+            throw new NotFoundException();
122
+        }
123
+
124
+        if (!$useSvg && $this->shouldReplaceIcons()) {
125
+            if (!$folder->fileExists($key . '.png')) {
126
+                try {
127
+                    $finalIconFile = new \Imagick();
128
+                    $finalIconFile->setBackgroundColor('none');
129
+                    $finalIconFile->readImageBlob($folder->getFile($key)->getContent());
130
+                    $finalIconFile->setImageFormat('png32');
131
+                    $pngFile = $folder->newFile($key . '.png');
132
+                    $pngFile->putContent($finalIconFile->getImageBlob());
133
+                    return $pngFile;
134
+                } catch (\ImagickException $e) {
135
+                    $this->logger->info('The image was requested to be no SVG file, but converting it to PNG failed: ' . $e->getMessage());
136
+                }
137
+            } else {
138
+                return $folder->getFile($key . '.png');
139
+            }
140
+        }
141
+
142
+        return $folder->getFile($key);
143
+    }
144
+
145
+    public function hasImage(string $key): bool {
146
+        $mimeSetting = $this->config->getAppValue('theming', $key . 'Mime', '');
147
+        return $mimeSetting !== '';
148
+    }
149
+
150
+    /**
151
+     * @return array<string, array{mime: string, url: string}>
152
+     */
153
+    public function getCustomImages(): array {
154
+        $images = [];
155
+        foreach (self::SUPPORTED_IMAGE_KEYS as $key) {
156
+            $images[$key] = [
157
+                'mime' => $this->config->getAppValue('theming', $key . 'Mime', ''),
158
+                'url' => $this->getImageUrl($key),
159
+            ];
160
+        }
161
+        return $images;
162
+    }
163
+
164
+    /**
165
+     * Get folder for current theming files
166
+     *
167
+     * @return ISimpleFolder
168
+     * @throws NotPermittedException
169
+     */
170
+    public function getCacheFolder(): ISimpleFolder {
171
+        $cacheBusterValue = $this->config->getAppValue('theming', 'cachebuster', '0');
172
+        try {
173
+            $folder = $this->getRootFolder()->getFolder($cacheBusterValue);
174
+        } catch (NotFoundException $e) {
175
+            $folder = $this->getRootFolder()->newFolder($cacheBusterValue);
176
+            $this->cleanup();
177
+        }
178
+        return $folder;
179
+    }
180
+
181
+    /**
182
+     * Get a file from AppData
183
+     *
184
+     * @param string $filename
185
+     * @throws NotFoundException
186
+     * @return \OCP\Files\SimpleFS\ISimpleFile
187
+     * @throws NotPermittedException
188
+     */
189
+    public function getCachedImage(string $filename): ISimpleFile {
190
+        $currentFolder = $this->getCacheFolder();
191
+        return $currentFolder->getFile($filename);
192
+    }
193
+
194
+    /**
195
+     * Store a file for theming in AppData
196
+     *
197
+     * @param string $filename
198
+     * @param string $data
199
+     * @return \OCP\Files\SimpleFS\ISimpleFile
200
+     * @throws NotFoundException
201
+     * @throws NotPermittedException
202
+     */
203
+    public function setCachedImage(string $filename, string $data): ISimpleFile {
204
+        $currentFolder = $this->getCacheFolder();
205
+        if ($currentFolder->fileExists($filename)) {
206
+            $file = $currentFolder->getFile($filename);
207
+        } else {
208
+            $file = $currentFolder->newFile($filename);
209
+        }
210
+        $file->putContent($data);
211
+        return $file;
212
+    }
213
+
214
+    public function delete(string $key): void {
215
+        /* ignore exceptions, since we don't want to fail hard if something goes wrong during cleanup */
216
+        try {
217
+            $file = $this->getRootFolder()->getFolder('images')->getFile($key);
218
+            $file->delete();
219
+        } catch (NotFoundException $e) {
220
+        } catch (NotPermittedException $e) {
221
+        }
222
+        try {
223
+            $file = $this->getRootFolder()->getFolder('images')->getFile($key . '.png');
224
+            $file->delete();
225
+        } catch (NotFoundException $e) {
226
+        } catch (NotPermittedException $e) {
227
+        }
228
+    }
229
+
230
+    public function updateImage(string $key, string $tmpFile): string {
231
+        $this->delete($key);
232
+
233
+        try {
234
+            $folder = $this->getRootFolder()->getFolder('images');
235
+        } catch (NotFoundException $e) {
236
+            $folder = $this->getRootFolder()->newFolder('images');
237
+        }
238
+
239
+        $target = $folder->newFile($key);
240
+        $supportedFormats = $this->getSupportedUploadImageFormats($key);
241
+        $detectedMimeType = mime_content_type($tmpFile);
242
+        if (!in_array($detectedMimeType, $supportedFormats, true)) {
243
+            throw new \Exception('Unsupported image type');
244
+        }
245
+
246
+        if ($key === 'background' && strpos($detectedMimeType, 'image/svg') === false && strpos($detectedMimeType, 'image/gif') === false) {
247
+            // Optimize the image since some people may upload images that will be
248
+            // either to big or are not progressive rendering.
249
+            $newImage = @imagecreatefromstring(file_get_contents($tmpFile));
250
+
251
+            // Preserve transparency
252
+            imagesavealpha($newImage, true);
253
+            imagealphablending($newImage, true);
254
+
255
+            $tmpFile = $this->tempManager->getTemporaryFile();
256
+            $newWidth = (int)(imagesx($newImage) < 4096 ? imagesx($newImage) : 4096);
257
+            $newHeight = (int)(imagesy($newImage) / (imagesx($newImage) / $newWidth));
258
+            $outputImage = imagescale($newImage, $newWidth, $newHeight);
259
+
260
+            imageinterlace($outputImage, 1);
261
+            imagepng($outputImage, $tmpFile, 8);
262
+            imagedestroy($outputImage);
263
+
264
+            $target->putContent(file_get_contents($tmpFile));
265
+        } else {
266
+            $target->putContent(file_get_contents($tmpFile));
267
+        }
268
+
269
+        return $detectedMimeType;
270
+    }
271
+
272
+    /**
273
+     * Returns a list of supported mime types for image uploads.
274
+     * "favicon" images are only allowed to be SVG when imagemagick with SVG support is available.
275
+     *
276
+     * @param string $key The image key, e.g. "favicon"
277
+     * @return string[]
278
+     */
279
+    private function getSupportedUploadImageFormats(string $key): array {
280
+        $supportedFormats = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
281
+
282
+        if ($key !== 'favicon' || $this->shouldReplaceIcons() === true) {
283
+            $supportedFormats[] = 'image/svg+xml';
284
+            $supportedFormats[] = 'image/svg';
285
+        }
286
+
287
+        if ($key === 'favicon') {
288
+            $supportedFormats[] = 'image/x-icon';
289
+            $supportedFormats[] = 'image/vnd.microsoft.icon';
290
+        }
291
+
292
+        return $supportedFormats;
293
+    }
294
+
295
+    /**
296
+     * remove cached files that are not required any longer
297
+     *
298
+     * @throws NotPermittedException
299
+     * @throws NotFoundException
300
+     */
301
+    public function cleanup() {
302
+        $currentFolder = $this->getCacheFolder();
303
+        $folders = $this->getRootFolder()->getDirectoryListing();
304
+        foreach ($folders as $folder) {
305
+            if ($folder->getName() !== 'images' && $folder->getName() !== $currentFolder->getName()) {
306
+                $folder->delete();
307
+            }
308
+        }
309
+    }
310
+
311
+    /**
312
+     * Check if Imagemagick is enabled and if SVG is supported
313
+     * otherwise we can't render custom icons
314
+     *
315
+     * @return bool
316
+     */
317
+    public function shouldReplaceIcons() {
318
+        $cache = $this->cacheFactory->createDistributed('theming-' . $this->urlGenerator->getBaseUrl());
319
+        if ($value = $cache->get('shouldReplaceIcons')) {
320
+            return (bool)$value;
321
+        }
322
+        $value = false;
323
+        if (extension_loaded('imagick')) {
324
+            if (count(\Imagick::queryFormats('SVG')) >= 1) {
325
+                $value = true;
326
+            }
327
+        }
328
+        $cache->set('shouldReplaceIcons', $value);
329
+        return $value;
330
+    }
331
+
332
+    private function getRootFolder(): ISimpleFolder {
333
+        try {
334
+            return $this->appData->getFolder('global');
335
+        } catch (NotFoundException $e) {
336
+            return $this->appData->newFolder('global');
337
+        }
338
+    }
339 339
 }
Please login to merge, or discard this patch.
Spacing   +15 added lines, -15 removed lines patch added patch discarded remove patch
@@ -85,16 +85,16 @@  discard block
 block discarded – undo
85 85
 	public function getImageUrl(string $key): string {
86 86
 		$cacheBusterCounter = $this->config->getAppValue(Application::APP_ID, 'cachebuster', '0');
87 87
 		if ($this->hasImage($key)) {
88
-			return $this->urlGenerator->linkToRoute('theming.Theming.getImage', [ 'key' => $key ]) . '?v=' . $cacheBusterCounter;
88
+			return $this->urlGenerator->linkToRoute('theming.Theming.getImage', ['key' => $key]).'?v='.$cacheBusterCounter;
89 89
 		}
90 90
 
91 91
 		switch ($key) {
92 92
 			case 'logo':
93 93
 			case 'logoheader':
94 94
 			case 'favicon':
95
-				return $this->urlGenerator->imagePath('core', 'logo/logo.png') . '?v=' . $cacheBusterCounter;
95
+				return $this->urlGenerator->imagePath('core', 'logo/logo.png').'?v='.$cacheBusterCounter;
96 96
 			case 'background':
97
-				return $this->urlGenerator->linkTo(Application::APP_ID, 'img/background/' . BackgroundService::DEFAULT_BACKGROUND_IMAGE);
97
+				return $this->urlGenerator->linkTo(Application::APP_ID, 'img/background/'.BackgroundService::DEFAULT_BACKGROUND_IMAGE);
98 98
 		}
99 99
 		return '';
100 100
 	}
@@ -114,7 +114,7 @@  discard block
 block discarded – undo
114 114
 	 * @throws NotPermittedException
115 115
 	 */
116 116
 	public function getImage(string $key, bool $useSvg = true): ISimpleFile {
117
-		$logo = $this->config->getAppValue('theming', $key . 'Mime', '');
117
+		$logo = $this->config->getAppValue('theming', $key.'Mime', '');
118 118
 		$folder = $this->getRootFolder()->getFolder('images');
119 119
 
120 120
 		if ($logo === '' || !$folder->fileExists($key)) {
@@ -122,20 +122,20 @@  discard block
 block discarded – undo
122 122
 		}
123 123
 
124 124
 		if (!$useSvg && $this->shouldReplaceIcons()) {
125
-			if (!$folder->fileExists($key . '.png')) {
125
+			if (!$folder->fileExists($key.'.png')) {
126 126
 				try {
127 127
 					$finalIconFile = new \Imagick();
128 128
 					$finalIconFile->setBackgroundColor('none');
129 129
 					$finalIconFile->readImageBlob($folder->getFile($key)->getContent());
130 130
 					$finalIconFile->setImageFormat('png32');
131
-					$pngFile = $folder->newFile($key . '.png');
131
+					$pngFile = $folder->newFile($key.'.png');
132 132
 					$pngFile->putContent($finalIconFile->getImageBlob());
133 133
 					return $pngFile;
134 134
 				} catch (\ImagickException $e) {
135
-					$this->logger->info('The image was requested to be no SVG file, but converting it to PNG failed: ' . $e->getMessage());
135
+					$this->logger->info('The image was requested to be no SVG file, but converting it to PNG failed: '.$e->getMessage());
136 136
 				}
137 137
 			} else {
138
-				return $folder->getFile($key . '.png');
138
+				return $folder->getFile($key.'.png');
139 139
 			}
140 140
 		}
141 141
 
@@ -143,7 +143,7 @@  discard block
 block discarded – undo
143 143
 	}
144 144
 
145 145
 	public function hasImage(string $key): bool {
146
-		$mimeSetting = $this->config->getAppValue('theming', $key . 'Mime', '');
146
+		$mimeSetting = $this->config->getAppValue('theming', $key.'Mime', '');
147 147
 		return $mimeSetting !== '';
148 148
 	}
149 149
 
@@ -154,7 +154,7 @@  discard block
 block discarded – undo
154 154
 		$images = [];
155 155
 		foreach (self::SUPPORTED_IMAGE_KEYS as $key) {
156 156
 			$images[$key] = [
157
-				'mime' => $this->config->getAppValue('theming', $key . 'Mime', ''),
157
+				'mime' => $this->config->getAppValue('theming', $key.'Mime', ''),
158 158
 				'url' => $this->getImageUrl($key),
159 159
 			];
160 160
 		}
@@ -220,7 +220,7 @@  discard block
 block discarded – undo
220 220
 		} catch (NotPermittedException $e) {
221 221
 		}
222 222
 		try {
223
-			$file = $this->getRootFolder()->getFolder('images')->getFile($key . '.png');
223
+			$file = $this->getRootFolder()->getFolder('images')->getFile($key.'.png');
224 224
 			$file->delete();
225 225
 		} catch (NotFoundException $e) {
226 226
 		} catch (NotPermittedException $e) {
@@ -253,8 +253,8 @@  discard block
 block discarded – undo
253 253
 			imagealphablending($newImage, true);
254 254
 
255 255
 			$tmpFile = $this->tempManager->getTemporaryFile();
256
-			$newWidth = (int)(imagesx($newImage) < 4096 ? imagesx($newImage) : 4096);
257
-			$newHeight = (int)(imagesy($newImage) / (imagesx($newImage) / $newWidth));
256
+			$newWidth = (int) (imagesx($newImage) < 4096 ? imagesx($newImage) : 4096);
257
+			$newHeight = (int) (imagesy($newImage) / (imagesx($newImage) / $newWidth));
258 258
 			$outputImage = imagescale($newImage, $newWidth, $newHeight);
259 259
 
260 260
 			imageinterlace($outputImage, 1);
@@ -315,9 +315,9 @@  discard block
 block discarded – undo
315 315
 	 * @return bool
316 316
 	 */
317 317
 	public function shouldReplaceIcons() {
318
-		$cache = $this->cacheFactory->createDistributed('theming-' . $this->urlGenerator->getBaseUrl());
318
+		$cache = $this->cacheFactory->createDistributed('theming-'.$this->urlGenerator->getBaseUrl());
319 319
 		if ($value = $cache->get('shouldReplaceIcons')) {
320
-			return (bool)$value;
320
+			return (bool) $value;
321 321
 		}
322 322
 		$value = false;
323 323
 		if (extension_loaded('imagick')) {
Please login to merge, or discard this patch.
apps/theming/lib/ThemingDefaults.php 1 patch
Indentation   +439 added lines, -439 removed lines patch added patch discarded remove patch
@@ -55,443 +55,443 @@
 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) {
443
-		$this->config->setAppValue('theming', $setting, $value);
444
-		$this->increaseCacheBuster();
445
-	}
446
-
447
-	/**
448
-	 * Revert settings to the default value
449
-	 *
450
-	 * @param string $setting setting which should be reverted
451
-	 * @return string default value
452
-	 */
453
-	public function undo($setting) {
454
-		$this->config->deleteAppValue('theming', $setting);
455
-		$this->increaseCacheBuster();
456
-
457
-		$returnValue = '';
458
-		switch ($setting) {
459
-			case 'name':
460
-				$returnValue = $this->getEntity();
461
-				break;
462
-			case 'url':
463
-				$returnValue = $this->getBaseUrl();
464
-				break;
465
-			case 'slogan':
466
-				$returnValue = $this->getSlogan();
467
-				break;
468
-			case 'color':
469
-				$returnValue = $this->getDefaultColorPrimary();
470
-				break;
471
-			case 'logo':
472
-			case 'logoheader':
473
-			case 'background':
474
-			case 'favicon':
475
-				$this->imageManager->delete($setting);
476
-				break;
477
-		}
478
-
479
-		return $returnValue;
480
-	}
481
-
482
-	/**
483
-	 * Color of text in the header and primary buttons
484
-	 *
485
-	 * @return string
486
-	 */
487
-	public function getTextColorPrimary() {
488
-		return $this->util->invertTextColor($this->getColorPrimary()) ? '#000000' : '#ffffff';
489
-	}
490
-
491
-	/**
492
-	 * Has the admin disabled user customization
493
-	 */
494
-	public function isUserThemingDisabled(): bool {
495
-		return $this->config->getAppValue('theming', 'disable-user-theming', 'no') === 'yes';
496
-	}
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) {
443
+        $this->config->setAppValue('theming', $setting, $value);
444
+        $this->increaseCacheBuster();
445
+    }
446
+
447
+    /**
448
+     * Revert settings to the default value
449
+     *
450
+     * @param string $setting setting which should be reverted
451
+     * @return string default value
452
+     */
453
+    public function undo($setting) {
454
+        $this->config->deleteAppValue('theming', $setting);
455
+        $this->increaseCacheBuster();
456
+
457
+        $returnValue = '';
458
+        switch ($setting) {
459
+            case 'name':
460
+                $returnValue = $this->getEntity();
461
+                break;
462
+            case 'url':
463
+                $returnValue = $this->getBaseUrl();
464
+                break;
465
+            case 'slogan':
466
+                $returnValue = $this->getSlogan();
467
+                break;
468
+            case 'color':
469
+                $returnValue = $this->getDefaultColorPrimary();
470
+                break;
471
+            case 'logo':
472
+            case 'logoheader':
473
+            case 'background':
474
+            case 'favicon':
475
+                $this->imageManager->delete($setting);
476
+                break;
477
+        }
478
+
479
+        return $returnValue;
480
+    }
481
+
482
+    /**
483
+     * Color of text in the header and primary buttons
484
+     *
485
+     * @return string
486
+     */
487
+    public function getTextColorPrimary() {
488
+        return $this->util->invertTextColor($this->getColorPrimary()) ? '#000000' : '#ffffff';
489
+    }
490
+
491
+    /**
492
+     * Has the admin disabled user customization
493
+     */
494
+    public function isUserThemingDisabled(): bool {
495
+        return $this->config->getAppValue('theming', 'disable-user-theming', 'no') === 'yes';
496
+    }
497 497
 }
Please login to merge, or discard this patch.
apps/theming/lib/Controller/UserThemeController.php 2 patches
Indentation   +158 added lines, -158 removed lines patch added patch discarded remove patch
@@ -50,162 +50,162 @@
 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
-					$this->backgroundService->setDefaultBackground();
190
-					break;
191
-				default:
192
-					if (!$color) {
193
-						return new JSONResponse(['error' => 'Invalid type provided'], Http::STATUS_BAD_REQUEST);
194
-					}
195
-			}
196
-		} catch (\InvalidArgumentException $e) {
197
-			return new JSONResponse(['error' => $e->getMessage()], Http::STATUS_BAD_REQUEST);
198
-		} catch (\Throwable $e) {
199
-			return new JSONResponse(['error' => $e->getMessage()], Http::STATUS_INTERNAL_SERVER_ERROR);
200
-		}
201
-
202
-		$currentVersion++;
203
-		$this->config->setUserValue($this->userId, Application::APP_ID, 'userCacheBuster', (string)$currentVersion);
204
-
205
-		return new JSONResponse([
206
-			'backgroundImage' => $this->config->getUserValue($this->userId, Application::APP_ID, 'background_image', BackgroundService::BACKGROUND_DEFAULT),
207
-			'backgroundColor' => $this->themingDefaults->getColorPrimary(),
208
-			'version' => $currentVersion,
209
-		]);
210
-	}
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
+                    $this->backgroundService->setDefaultBackground();
190
+                    break;
191
+                default:
192
+                    if (!$color) {
193
+                        return new JSONResponse(['error' => 'Invalid type provided'], Http::STATUS_BAD_REQUEST);
194
+                    }
195
+            }
196
+        } catch (\InvalidArgumentException $e) {
197
+            return new JSONResponse(['error' => $e->getMessage()], Http::STATUS_BAD_REQUEST);
198
+        } catch (\Throwable $e) {
199
+            return new JSONResponse(['error' => $e->getMessage()], Http::STATUS_INTERNAL_SERVER_ERROR);
200
+        }
201
+
202
+        $currentVersion++;
203
+        $this->config->setUserValue($this->userId, Application::APP_ID, 'userCacheBuster', (string)$currentVersion);
204
+
205
+        return new JSONResponse([
206
+            'backgroundImage' => $this->config->getUserValue($this->userId, Application::APP_ID, 'background_image', BackgroundService::BACKGROUND_DEFAULT),
207
+            'backgroundColor' => $this->themingDefaults->getColorPrimary(),
208
+            'version' => $currentVersion,
209
+        ]);
210
+    }
211 211
 }
Please login to merge, or discard this patch.
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -121,12 +121,12 @@  discard block
 block discarded – undo
121 121
 	 */
122 122
 	private function validateTheme(string $themeId): ITheme {
123 123
 		if ($themeId === '' || !$themeId) {
124
-			throw new OCSBadRequestException('Invalid theme id: ' . $themeId);
124
+			throw new OCSBadRequestException('Invalid theme id: '.$themeId);
125 125
 		}
126 126
 
127 127
 		$themes = $this->themesService->getThemes();
128 128
 		if (!isset($themes[$themeId])) {
129
-			throw new OCSBadRequestException('Invalid theme id: ' . $themeId);
129
+			throw new OCSBadRequestException('Invalid theme id: '.$themeId);
130 130
 		}
131 131
 
132 132
 		// If trying to toggle another theme but this is enforced
@@ -156,7 +156,7 @@  discard block
 block discarded – undo
156 156
 	 * @NoAdminRequired
157 157
 	 */
158 158
 	public function deleteBackground(): JSONResponse {
159
-		$currentVersion = (int)$this->config->getUserValue($this->userId, Application::APP_ID, 'userCacheBuster', '0');
159
+		$currentVersion = (int) $this->config->getUserValue($this->userId, Application::APP_ID, 'userCacheBuster', '0');
160 160
 		$this->backgroundService->deleteBackgroundImage();
161 161
 		return new JSONResponse([
162 162
 			'backgroundImage' => null,
@@ -169,7 +169,7 @@  discard block
 block discarded – undo
169 169
 	 * @NoAdminRequired
170 170
 	 */
171 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');
172
+		$currentVersion = (int) $this->config->getUserValue($this->userId, Application::APP_ID, 'userCacheBuster', '0');
173 173
 
174 174
 		// Set color if provided
175 175
 		if ($color) {
@@ -200,7 +200,7 @@  discard block
 block discarded – undo
200 200
 		}
201 201
 
202 202
 		$currentVersion++;
203
-		$this->config->setUserValue($this->userId, Application::APP_ID, 'userCacheBuster', (string)$currentVersion);
203
+		$this->config->setUserValue($this->userId, Application::APP_ID, 'userCacheBuster', (string) $currentVersion);
204 204
 
205 205
 		return new JSONResponse([
206 206
 			'backgroundImage' => $this->config->getUserValue($this->userId, Application::APP_ID, 'background_image', BackgroundService::BACKGROUND_DEFAULT),
Please login to merge, or discard this patch.
apps/theming/appinfo/routes.php 1 patch
Indentation   +78 added lines, -78 removed lines patch added patch discarded remove patch
@@ -28,82 +28,82 @@
 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#uploadImage',
44
-			'url' => '/ajax/uploadImage',
45
-			'verb' => 'POST'
46
-		],
47
-		[
48
-			'name' => 'Theming#getThemeStylesheet',
49
-			'url' => '/theme/{themeId}.css',
50
-			'verb' => 'GET',
51
-		],
52
-		[
53
-			'name' => 'Theming#getImage',
54
-			'url' => '/image/{key}',
55
-			'verb' => 'GET',
56
-		],
57
-		[
58
-			'name' => 'Theming#getManifest',
59
-			'url' => '/manifest/{app}',
60
-			'verb' => 'GET',
61
-			'defaults' => ['app' => 'core']
62
-		],
63
-		[
64
-			'name' => 'Icon#getFavicon',
65
-			'url' => '/favicon/{app}',
66
-			'verb' => 'GET',
67
-			'defaults' => ['app' => 'core'],
68
-		],
69
-		[
70
-			'name' => 'Icon#getTouchIcon',
71
-			'url' => '/icon/{app}',
72
-			'verb' => 'GET',
73
-			'defaults' => ['app' => 'core'],
74
-		],
75
-		[
76
-			'name' => 'Icon#getThemedIcon',
77
-			'url' => '/img/{app}/{image}',
78
-			'verb' => 'GET',
79
-			'requirements' => ['image' => '.+']
80
-		],
81
-		[
82
-			'name' => 'userTheme#getBackground',
83
-			'url' => '/background',
84
-			'verb' => 'GET',
85
-		],
86
-		[
87
-			'name' => 'userTheme#setBackground',
88
-			'url' => '/background/{type}',
89
-			'verb' => 'POST',
90
-		],
91
-		[
92
-			'name' => 'userTheme#deleteBackground',
93
-			'url' => '/background/custom',
94
-			'verb' => 'DELETE',
95
-		],
96
-	],
97
-	'ocs' => [
98
-		[
99
-			'name' => 'userTheme#enableTheme',
100
-			'url' => '/api/v1/theme/{themeId}/enable',
101
-			'verb' => 'PUT',
102
-		],
103
-		[
104
-			'name' => 'userTheme#disableTheme',
105
-			'url' => '/api/v1/theme/{themeId}',
106
-			'verb' => 'DELETE',
107
-		],
108
-	]
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#uploadImage',
44
+            'url' => '/ajax/uploadImage',
45
+            'verb' => 'POST'
46
+        ],
47
+        [
48
+            'name' => 'Theming#getThemeStylesheet',
49
+            'url' => '/theme/{themeId}.css',
50
+            'verb' => 'GET',
51
+        ],
52
+        [
53
+            'name' => 'Theming#getImage',
54
+            'url' => '/image/{key}',
55
+            'verb' => 'GET',
56
+        ],
57
+        [
58
+            'name' => 'Theming#getManifest',
59
+            'url' => '/manifest/{app}',
60
+            'verb' => 'GET',
61
+            'defaults' => ['app' => 'core']
62
+        ],
63
+        [
64
+            'name' => 'Icon#getFavicon',
65
+            'url' => '/favicon/{app}',
66
+            'verb' => 'GET',
67
+            'defaults' => ['app' => 'core'],
68
+        ],
69
+        [
70
+            'name' => 'Icon#getTouchIcon',
71
+            'url' => '/icon/{app}',
72
+            'verb' => 'GET',
73
+            'defaults' => ['app' => 'core'],
74
+        ],
75
+        [
76
+            'name' => 'Icon#getThemedIcon',
77
+            'url' => '/img/{app}/{image}',
78
+            'verb' => 'GET',
79
+            'requirements' => ['image' => '.+']
80
+        ],
81
+        [
82
+            'name' => 'userTheme#getBackground',
83
+            'url' => '/background',
84
+            'verb' => 'GET',
85
+        ],
86
+        [
87
+            'name' => 'userTheme#setBackground',
88
+            'url' => '/background/{type}',
89
+            'verb' => 'POST',
90
+        ],
91
+        [
92
+            'name' => 'userTheme#deleteBackground',
93
+            'url' => '/background/custom',
94
+            'verb' => 'DELETE',
95
+        ],
96
+    ],
97
+    'ocs' => [
98
+        [
99
+            'name' => 'userTheme#enableTheme',
100
+            'url' => '/api/v1/theme/{themeId}/enable',
101
+            'verb' => 'PUT',
102
+        ],
103
+        [
104
+            'name' => 'userTheme#disableTheme',
105
+            'url' => '/api/v1/theme/{themeId}',
106
+            'verb' => 'DELETE',
107
+        ],
108
+    ]
109 109
 ];
Please login to merge, or discard this patch.