SettingsService   B
last analyzed

Complexity

Total Complexity 46

Size/Duplication

Total Lines 366
Duplicated Lines 0 %

Test Coverage

Coverage 60.2%

Importance

Changes 15
Bugs 0 Features 0
Metric Value
eloc 122
c 15
b 0
f 0
dl 0
loc 366
ccs 59
cts 98
cp 0.602
rs 8.72
wmc 46

39 Methods

Rating   Name   Duplication   Size   Complexity  
A getSensitivity() 0 2 1
A setSensitivity() 0 2 1
A getCurrentFaceModel() 0 2 1
A setMinimumFacesInCluster() 0 2 1
A getAnalysisImageArea() 0 2 1
A getSystemModelPath() 0 2 1
A _setForceCreateClusters() 0 2 2
A getUserEnabled() 0 4 1
A getExternalModelApiKey() 0 2 1
A getMinimumConfidence() 0 2 1
A getExternalModelUrl() 0 2 1
A getClusterigBatchSize() 0 2 1
A getDefaultUserEnabled() 0 3 1
A getLastStaleImageChecked() 0 2 1
A getHandleExternalFiles() 0 3 1
A setUserFullScanDone() 0 2 2
A setAssignedMemory() 0 2 1
A setObfuscateFaces() 0 2 2
A setNeedRecreateClusters() 0 2 2
A isAllowedMimetype() 0 10 2
A setLastStaleImageChecked() 0 2 1
A setMinimumConfidence() 0 2 1
A getAssignedMemory() 0 2 1
A _getForceCreateClusters() 0 3 1
A getMinimumImageSize() 0 2 1
A getNeedRemoveStaleImages() 0 3 1
A getHandleSharedFiles() 0 3 1
A setCurrentFaceModel() 0 2 1
A getMinimumFaceSize() 0 5 1
A getHandleGroupFiles() 0 3 1
A setNeedRemoveStaleImages() 0 2 2
A __construct() 0 5 1
A setAnalysisImageArea() 0 2 1
A getNeedRecreateClusters() 0 3 1
A getMaximumImageArea() 0 2 1
A getUserFullScanDone() 0 3 1
A setUserEnabled() 0 2 2
A getMinimumFacesInCluster() 0 2 1
A getObfuscateFaces() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like SettingsService often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use SettingsService, and based on these observations, apply Extract Interface, too.

1
<?php
2
declare(strict_types=1);
3
/**
4
 * @copyright Copyright (c) 2020 Matias De lellis <[email protected]>
5
 *
6
 * @author Matias De lellis <[email protected]>
7
 *
8
 * @license GNU AGPL version 3 or any later version
9
 *
10
 * This program is free software: you can redistribute it and/or modify
11
 * it under the terms of the GNU Affero General Public License as
12
 * published by the Free Software Foundation, either version 3 of the
13
 * License, or (at your option) any later version.
14
 *
15
 * This program is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 * GNU Affero General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU Affero General Public License
21
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22
 *
23
 */
24
25
namespace OCA\FaceRecognition\Service;
26
27
use OCA\FaceRecognition\AppInfo\Application;
28
29
use OCA\FaceRecognition\Model\ModelManager;
30
31
use OCP\IConfig;
32
33
class SettingsService {
34
35
	/*
36
	 * System
37
	 */
38
	const MINIMUM_SYSTEM_MEMORY_REQUIREMENTS = 1 * 1024 * 1024 * 1024;
39
40
	/*
41
	 * Settings keys and default values.
42
	 */
43
44
	/** Current Model used to analyze */
45
	const CURRENT_MODEL_KEY = 'model';
46
	const FALLBACK_CURRENT_MODEL = -1;
47
48
	/* Enabling facial recognition for users */
49
	const DEFAULT_USER_ENABLED_KEY = 'default_enabled';
50
	const DEFAULT_USER_ENABLED = 'false';
51
52
	/* Assigned memory for image processing */
53
	const ASSIGNED_MEMORY_KEY = 'assigned_memory';
54
	const MINIMUM_ASSIGNED_MEMORY = (1 * 1024 * 1024 * 1024) * 2.0 / 3.0;
55
	const DEFAULT_ASSIGNED_MEMORY = -1;
56
	const MAXIMUN_ASSIGNED_MEMORY = 8 * 1024 * 1024 * 1024;
57
58
	/** Image area that used used for analysis */
59
	const ANALYSIS_IMAGE_AREA_KEY = 'analysis_image_area';
60
	const MINIMUM_ANALYSIS_IMAGE_AREA = 640*480;
61
	const DEFAULT_ANALYSIS_IMAGE_AREA = -1; // It is dynamically configured according to hardware
62
	const MAXIMUM_ANALYSIS_IMAGE_AREA = 3840*2160;
63
64
	/** Sensitivity used to clustering */
65
	const SENSITIVITY_KEY = 'sensitivity';
66
	const MINIMUM_SENSITIVITY = '0.2';
67
	const DEFAULT_SENSITIVITY = '0.4';
68
	const MAXIMUM_SENSITIVITY = '0.6';
69
70
	/** Minimum confidence used to try to clustring faces */
71
	const MINIMUM_CONFIDENCE_KEY = 'min_confidence';
72
	const MINIMUM_MINIMUM_CONFIDENCE = '0.0';
73
	const DEFAULT_MINIMUM_CONFIDENCE = '0.99';
74
	const MAXIMUM_MINIMUM_CONFIDENCE = '1.1';
75
76
	/** Minimum face size used to try to clustring faces */
77
	const MINIMUM_FACE_SIZE_KEY = 'min_face_size';
78
	const MINIMUM_MINIMUM_FACE_SIZE = '0';
79
	const DEFAULT_MINIMUM_FACE_SIZE = '40';
80
	const MAXIMUM_MINIMUM_FACE_SIZE = '250';
81
82
	/** Minimum of faces in cluster */
83
	const MINIMUM_FACES_IN_CLUSTER_KEY = 'min_faces_in_cluster';
84
	const MINIMUM_MINIMUM_FACES_IN_CLUSTER = '1';
85
	const DEFAULT_MINIMUM_FACES_IN_CLUSTER = '5';
86
	const MAXIMUM_MINIMUM_FACES_IN_CLUSTER = '20';
87
88
	/** User setting what indicates if has the analysis enabled */
89
	const USER_ENABLED_KEY = 'enabled';
90
	// The default is defined by system 'default_enabled' key
91
92
	const CLUSTERING_BATCH_SIZE_KEY = 'clustering_batch_size';
93
	const DEFAULT_CLUSTERING_BATCH_SIZE = '-1';
94
95
	/** User setting that remember last images checked */
96
	const STALE_IMAGES_LAST_CHECKED_KEY = 'stale_images_last_checked';
97
	const DEFAULT_STALE_IMAGES_LAST_CHECKED = '0';
98
99
	/** Define if for some reason need remove old images */
100
	const STALE_IMAGES_REMOVAL_NEEDED_KEY = 'stale_images_removal_needed';
101
	const DEFAULT_STALE_IMAGES_REMOVAL_NEEDED = 'false';
102
103
	/** User setting that indicate when scan finished */
104
	const FULL_IMAGE_SCAN_DONE_KEY = 'full_image_scan_done';
105
	const DEFAULT_FULL_IMAGE_SCAN_DONE = 'false';
106
107
	/** User setting that indicate that need to recreate clusters */
108
	const USER_RECREATE_CLUSTERS_KEY = 'recreate_clusters';
109
	const DEFAULT_USER_RECREATE_CLUSTERS = 'false';
110
111
	/** User setting that indicate that is forced to create clusters */
112
	const FORCE_CREATE_CLUSTERS_KEY = 'force_create_clusters';
113
	const DEFAULT_FORCE_CREATE_CLUSTERS = 'false';
114
115
	/** Hidden setting that allows to analyze shared files */
116
	const HANDLE_SHARED_FILES_KEY = 'handle_shared_files';
117
	const DEFAULT_HANDLE_SHARED_FILES = 'false';
118
119
	/** Hidden setting that allows to analyze external files */
120
	const HANDLE_EXTERNAL_FILES_KEY = 'handle_external_files';
121
	const DEFAULT_HANDLE_EXTERNAL_FILES = 'false';
122
123
	/** Hidden setting that allows to analyze group files */
124
	const HANDLE_GROUP_FILES_KEY = 'handle_group_files';
125
	const DEFAULT_HANDLE_GROUP_FILES = 'false';
126
127
	/** Hidden setting that indicate minimum large of image to analyze */
128
	const MINIMUM_IMAGE_SIZE_KEY = 'min_image_size';
129
	const DEFAULT_MINIMUM_IMAGE_SIZE = '512';
130
131
	/** Hidden setting that indicate maximum area of image to analyze */
132
	const MAXIMUM_IMAGE_AREA_KEY = 'max_image_area';
133
	const DEFAULT_MAXIMUM_IMAGE_AREA = '-1';
134
135
	/** Hidden setting that allows obfuscate that faces for security */
136
	const OBFUSCATE_FACE_THUMBS_KEY = 'obfuscate_faces';
137
	const DEFAULT_OBFUSCATE_FACE_THUMBS = 'false';
138
139
	/** System setting to enable mimetypes */
140
141
	const SYSTEM_ENABLED_MIMETYPES = 'enabledFaceRecognitionMimetype';
142
	private $allowedMimetypes = ['image/jpeg', 'image/png'];
143
	private $cachedAllowedMimetypes = false;
144
145
	/** System setting to use custom folder for models */
146
	const SYSTEM_MODEL_PATH = 'facerecognition.model_path';
147
148
	/** System setting to configure external model */
149
	const SYSTEM_EXTERNAL_MODEL_URL = 'facerecognition.external_model_url';
150
	const SYSTEM_EXTERNAL_MODEL_API_KEY = 'facerecognition.external_model_api_key';
151
152
	/**
153
	 * SettingsService
154
	 */
155
156
	/** @var IConfig Config */
157
	private $config;
158
159
	/**  @var string|null */
160
	private $userId;
161
162
	/**
163
	 * @param IConfig $config
164
	 * @param string $userId
165
	 */
166 1
	public function __construct(IConfig $config,
167
	                            $userId)
168
	{
169 1
		$this->config = $config;
170 1
		$this->userId = $userId;
171
	}
172
173
	/*
174
	 * User settings.
175
	 */
176
	/**
177
	 * @param null|string $userId
178
	 */
179 10
	public function getUserEnabled (?string $userId = null): bool {
180 10
		$enabled = $this->config->getUserValue($userId ?? $this->userId, Application::APP_NAME, self::USER_ENABLED_KEY,
181 10
		                                       $this->getDefaultUserEnabled());
182 10
		return ($enabled === 'true');
183
	}
184
185
	public function setUserEnabled (bool $enabled, $userId = null): void {
186
		$this->config->setUserValue($userId ?? $this->userId, Application::APP_NAME, self::USER_ENABLED_KEY, $enabled ? "true" : "false");
187
	}
188
189
	/**
190
	 * @param null|string $userId
191
	 */
192 10
	public function getUserFullScanDone (?string $userId = null): bool {
193 10
		$fullScanDone = $this->config->getUserValue($userId ?? $this->userId, Application::APP_NAME, self::FULL_IMAGE_SCAN_DONE_KEY, self::DEFAULT_FULL_IMAGE_SCAN_DONE);
194 10
		return ($fullScanDone === 'true');
195
	}
196
197
	/**
198
	 * @param null|string $userId
199
	 */
200 28
	public function setUserFullScanDone (bool $fullScanDone, ?string $userId = null): void {
201 28
		$this->config->setUserValue($userId ?? $this->userId, Application::APP_NAME, self::FULL_IMAGE_SCAN_DONE_KEY, $fullScanDone ? "true" : "false");
202
	}
203
204 3
	public function getNeedRemoveStaleImages ($userId = null): bool {
205 3
		$needRemoval = $this->config->getUserValue($userId ?? $this->userId, Application::APP_NAME, self::STALE_IMAGES_REMOVAL_NEEDED_KEY, self::DEFAULT_STALE_IMAGES_REMOVAL_NEEDED);
206 3
		return ($needRemoval === 'true');
207
	}
208
209
	/**
210
	 * @param null|string $userId
211
	 */
212 2
	public function setNeedRemoveStaleImages (bool $needRemoval, ?string $userId = null): void {
213 2
		$this->config->setUserValue($userId ?? $this->userId, Application::APP_NAME, self::STALE_IMAGES_REMOVAL_NEEDED_KEY, $needRemoval ? "true" : "false");
214
	}
215
216
	/**
217
	 * @param null|string $userId
218
	 */
219 2
	public function getLastStaleImageChecked (?string $userId = null): int {
220 2
		return intval($this->config->getUserValue($userId ?? $this->userId, Application::APP_NAME, self::STALE_IMAGES_LAST_CHECKED_KEY, self::DEFAULT_STALE_IMAGES_LAST_CHECKED));
221
	}
222
223
	/**
224
	 * @param null|string $userId
225
	 */
226 2
	public function setLastStaleImageChecked (int $lastCheck, ?string $userId = null): void {
227 2
		$this->config->setUserValue($userId ?? $this->userId, Application::APP_NAME, self::STALE_IMAGES_LAST_CHECKED_KEY, strval($lastCheck));
228
	}
229
230
	/**
231
	 * @param null|string $userId
232
	 */
233
	public function getNeedRecreateClusters (?string $userId = null): bool {
234
		$needRecreate = $this->config->getUserValue($userId ?? $this->userId, Application::APP_NAME, self::USER_RECREATE_CLUSTERS_KEY, self::DEFAULT_USER_RECREATE_CLUSTERS);
235
		return ($needRecreate === 'true');
236
	}
237
238
	/**
239
	 * @param null|string $userId
240
	 */
241 1
	public function setNeedRecreateClusters (bool $needRecreate, ?string $userId = null): void {
242 1
		$this->config->setUserValue($userId ?? $this->userId, Application::APP_NAME, self::USER_RECREATE_CLUSTERS_KEY, $needRecreate ? "true" : "false");
243
	}
244
245
	// Private function used only on tests
246
	/**
247
	 * @param null|string $userId
248
	 */
249 1
	public function _getForceCreateClusters (?string $userId = null): bool {
250 1
		$forceCreate = $this->config->getUserValue($userId ?? $this->userId, Application::APP_NAME, self::FORCE_CREATE_CLUSTERS_KEY, self::DEFAULT_FORCE_CREATE_CLUSTERS);
251 1
		return ($forceCreate === 'true');
252
	}
253
254
	// Private function used only on tests
255
	/**
256
	 * @param null|string $userId
257
	 */
258 1
	public function _setForceCreateClusters (bool $forceCreate, ?string $userId = null): void {
259 1
		$this->config->setUserValue($userId ?? $this->userId, Application::APP_NAME, self::FORCE_CREATE_CLUSTERS_KEY, $forceCreate ? "true" : "false");
260
	}
261
262
	/*
263
	 * Admin and process settings.
264
	 */
265 12
	public function getCurrentFaceModel(): int {
266 12
		return intval($this->config->getAppValue(Application::APP_NAME, self::CURRENT_MODEL_KEY, strval(self::FALLBACK_CURRENT_MODEL)));
267
	}
268
269
	public function setCurrentFaceModel(int $model): void {
270
		$this->config->setAppValue(Application::APP_NAME, self::CURRENT_MODEL_KEY, strval($model));
271
	}
272
273 4
	public function getAnalysisImageArea(): int {
274 4
		return intval($this->config->getAppValue(Application::APP_NAME, self::ANALYSIS_IMAGE_AREA_KEY, strval(self::DEFAULT_ANALYSIS_IMAGE_AREA)));
275
	}
276
277
	public function setAssignedMemory(int $assignedMemory): void {
278
		$this->config->setAppValue(Application::APP_NAME, self::ASSIGNED_MEMORY_KEY, strval($assignedMemory));
279
	}
280
281
	public function setAnalysisImageArea(int $imageArea): void {
282
		$this->config->setAppValue(Application::APP_NAME, self::ANALYSIS_IMAGE_AREA_KEY, strval($imageArea));
283
	}
284
285 1
	public function getSensitivity(): float {
286 1
		return floatval($this->config->getAppValue(Application::APP_NAME, self::SENSITIVITY_KEY, self::DEFAULT_SENSITIVITY));
287
	}
288
289
	public function setSensitivity($sensitivity): void {
290
		$this->config->setAppValue(Application::APP_NAME, self::SENSITIVITY_KEY, $sensitivity);
291
	}
292
293 1
	public function getMinimumConfidence(): float {
294 1
		return floatval($this->config->getAppValue(Application::APP_NAME, self::MINIMUM_CONFIDENCE_KEY, self::DEFAULT_MINIMUM_CONFIDENCE));
295
	}
296
297
	public function setMinimumConfidence($confidence): void {
298
		$this->config->setAppValue(Application::APP_NAME, self::MINIMUM_CONFIDENCE_KEY, $confidence);
299
	}
300
301
	public function getMinimumFacesInCluster(): int {
302
		return intval($this->config->getAppValue(Application::APP_NAME, self::MINIMUM_FACES_IN_CLUSTER_KEY, self::DEFAULT_MINIMUM_FACES_IN_CLUSTER));
303
	}
304
305
	public function setMinimumFacesInCluster($no_faces): void {
306
		$this->config->setAppValue(Application::APP_NAME, self::MINIMUM_FACES_IN_CLUSTER_KEY, $no_faces);
307
	}
308
309
	/**
310
	 * The next settings are advanced preferences that are not available in gui.
311
	 * See: https://github.com/matiasdelellis/facerecognition/wiki/Settings#hidden-settings
312
	 */
313 10
	public function getDefaultUserEnabled (): bool {
314 10
		$enabled = $this->config->getAppValue(Application::APP_NAME, self::DEFAULT_USER_ENABLED_KEY, self::DEFAULT_USER_ENABLED);
315 10
		return ($enabled === 'true');
316
	}
317
318 1
	public function getClusterigBatchSize(): int {
319 1
		return intval($this->config->getAppValue(Application::APP_NAME, self::CLUSTERING_BATCH_SIZE_KEY, self::DEFAULT_CLUSTERING_BATCH_SIZE));
320
	}
321
322
	public function getHandleSharedFiles(): bool {
323
		$handle = $this->config->getAppValue(Application::APP_NAME, self::HANDLE_SHARED_FILES_KEY, self::DEFAULT_HANDLE_SHARED_FILES);
324
		return ($handle === 'true');
325
	}
326
327
	public function getHandleExternalFiles(): bool {
328
		$handle = $this->config->getAppValue(Application::APP_NAME, self::HANDLE_EXTERNAL_FILES_KEY, self::DEFAULT_HANDLE_EXTERNAL_FILES);
329
		return ($handle === 'true');
330
	}
331
332
	public function getHandleGroupFiles(): bool {
333
		$handle = $this->config->getAppValue(Application::APP_NAME, self::HANDLE_GROUP_FILES_KEY, self::DEFAULT_HANDLE_GROUP_FILES);
334
		return ($handle === 'true');
335
	}
336
337 4
	public function getMinimumImageSize(): int {
338 4
		return intval($this->config->getAppValue(Application::APP_NAME, self::MINIMUM_IMAGE_SIZE_KEY, self::DEFAULT_MINIMUM_IMAGE_SIZE));
339
	}
340
341 1
	public function getMinimumFaceSize(): int {
342 1
		$minFaceSize = intval($this->config->getAppValue(Application::APP_NAME, self::MINIMUM_FACE_SIZE_KEY, self::DEFAULT_MINIMUM_FACE_SIZE));
343 1
		$minFaceSize = max(self::MINIMUM_MINIMUM_FACE_SIZE, $minFaceSize);
344 1
		$minFaceSize = min($minFaceSize, self::MAXIMUM_MINIMUM_FACE_SIZE);
345 1
		return intval($minFaceSize);
346
	}
347
348 4
	public function getMaximumImageArea(): int {
349 4
		return intval($this->config->getAppValue(Application::APP_NAME, self::MAXIMUM_IMAGE_AREA_KEY, self::DEFAULT_MAXIMUM_IMAGE_AREA));
350
	}
351
352
	public function getAssignedMemory(): int {
353
		return intval($this->config->getAppValue(Application::APP_NAME, self::ASSIGNED_MEMORY_KEY, strval(self::DEFAULT_ASSIGNED_MEMORY)));
354
	}
355
356
	public function getObfuscateFaces(): bool {
357
		$obfuscate = $this->config->getAppValue(Application::APP_NAME, self::OBFUSCATE_FACE_THUMBS_KEY, self::DEFAULT_OBFUSCATE_FACE_THUMBS);
358
		return ($obfuscate === 'true');
359
	}
360
361
	public function setObfuscateFaces(bool $obfuscate): void {
362
		$this->config->setAppValue(Application::APP_NAME, self::OBFUSCATE_FACE_THUMBS_KEY, $obfuscate ? 'true' : 'false');
363
	}
364
365
	/**
366
	 * System settings that must be configured according to the server configuration.
367
	 */
368 8
	public function isAllowedMimetype(string $mimetype): bool {
369 8
		if (!$this->cachedAllowedMimetypes) {
370 1
			$systemMimetypes = $this->config->getSystemValue(self::SYSTEM_ENABLED_MIMETYPES, $this->allowedMimetypes);
371 1
			$this->allowedMimetypes = array_merge($this->allowedMimetypes, $systemMimetypes);
372 1
			$this->allowedMimetypes = array_unique($this->allowedMimetypes);
373
374 1
			$this->cachedAllowedMimetypes = true;
375
		}
376
377 8
		return in_array($mimetype, $this->allowedMimetypes);
378
	}
379
380
	/**
381
	 * System settings that allow use an custom folder to install the models.
382
	 */
383 1
	public function getSystemModelPath(): ?string {
384 1
		return $this->config->getSystemValue(self::SYSTEM_MODEL_PATH, null);
385
	}
386
387
	/**
388
	 * External model url
389
	 */
390
	public function getExternalModelUrl(): ?string {
391
		return $this->config->getSystemValue(self::SYSTEM_EXTERNAL_MODEL_URL, null);
392
	}
393
394
	/**
395
	 * External model Api Key
396
	 */
397
	public function getExternalModelApiKey(): ?string {
398
		return $this->config->getSystemValue(self::SYSTEM_EXTERNAL_MODEL_API_KEY, null);
399
	}
400
401
}
402