Passed
Push — split-cluster-person ( 7ada7e...098531 )
by Matias
05:26
created

PersonController::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 21
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 9
c 1
b 0
f 0
nc 1
nop 10
dl 0
loc 21
ccs 0
cts 20
cp 0
crap 2
rs 9.9666

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
/**
3
 * @copyright Copyright (c) 2018-2020 Matias De lellis <[email protected]>
4
 *
5
 * @author Matias De lellis <[email protected]>
6
 *
7
 * @license GNU AGPL version 3 or any later version
8
 *
9
 * This program is free software: you can redistribute it and/or modify
10
 * it under the terms of the GNU Affero General Public License as
11
 * published by the Free Software Foundation, either version 3 of the
12
 * License, or (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU Affero General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Affero General Public License
20
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
 *
22
 */
23
24
namespace OCA\FaceRecognition\Controller;
25
26
use OCP\IRequest;
27
use OCP\Files\IRootFolder;
28
use OCP\Files\File;
29
use OCP\IUserSession;
30
use OCP\IURLGenerator;
31
32
use OCP\AppFramework\Http;
33
use OCP\AppFramework\Http\DataResponse;
34
use OCP\AppFramework\Http\JSONResponse;
35
use OCP\AppFramework\Http\DataDisplayResponse;
36
use OCP\AppFramework\Controller;
37
38
use OCA\FaceRecognition\Db\Face;
39
use OCA\FaceRecognition\Db\FaceMapper;
40
41
use OCA\FaceRecognition\Db\Image;
42
use OCA\FaceRecognition\Db\ImageMapper;
43
44
use OCA\FaceRecognition\Db\Person;
45
use OCA\FaceRecognition\Db\PersonMapper;
46
47
use OCA\FaceRecognition\Service\SettingsService;
48
49
50
class PersonController extends Controller {
51
52
	/** @var IRootFolder */
53
	private $rootFolder;
54
55
	/** @var IUserSession */
56
	private $userSession;
57
58
	/** @var IURLGenerator */
59
	private $urlGenerator;
60
61
	/** @var FaceMapper */
62
	private $faceMapper;
63
64
	/** @var ImageMapper */
65
	private $imageMapper;
66
67
	/** @var PersonMapper */
68
	private $personMapper;
69
70
	/** @var SettingsService */
71
	private $settingsService;
72
73
	/** @var string */
74
	private $userId;
75
76
	public function __construct($AppName,
77
	                            IRequest        $request,
78
	                            IRootFolder     $rootFolder,
79
	                            IUserSession    $userSession,
80
	                            IURLGenerator   $urlGenerator,
81
	                            FaceMapper      $faceMapper,
82
	                            ImageMapper     $imageMapper,
83
	                            PersonMapper    $personmapper,
84
	                            SettingsService $settingsService,
85
	                            $UserId)
86
	{
87
		parent::__construct($AppName, $request);
88
89
		$this->rootFolder      = $rootFolder;
90
		$this->userSession     = $userSession;
91
		$this->urlGenerator    = $urlGenerator;
92
		$this->faceMapper      = $faceMapper;
93
		$this->imageMapper     = $imageMapper;
94
		$this->personMapper    = $personmapper;
95
		$this->settingsService = $settingsService;
96
		$this->userId          = $UserId;
97
	}
98
99
	/**
100
	 * @NoAdminRequired
101
	 */
102
	public function index() {
103
		$userEnabled = $this->settingsService->getUserEnabled($this->userId);
104
105
		$resp = array();
106
		$resp['enabled'] = $userEnabled;
107
		$resp['persons'] = array();
108
109
		if (!$userEnabled)
110
			return new DataResponse($resp);
111
112
		$modelId = $this->settingsService->getCurrentFaceModel();
113
114
		$personsNames = $this->personMapper->findDistinctNames($this->userId, $modelId);
115
		foreach ($personsNames as $personNamed) {
116
			$facesCount = 0;
117
			$faceUrl = null;
118
			$faces = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $faces is dead and can be removed.
Loading history...
119
			$persons = $this->personMapper->findByName($this->userId, $modelId, $personNamed->getName());
120
			foreach ($persons as $person) {
121
				$personFaces = $this->faceMapper->findFacesFromPerson($this->userId, $person->getId(), $modelId);
122
				if (is_null($faceUrl)) {
123
					$faceUrl = $this->getThumbUrl($personFaces[0]->getId(), 128);
124
				}
125
				$facesCount += count($personFaces);
126
			}
127
128
			$person = [];
129
			$person['name'] = $personNamed->getName();
130
			$person['thumbUrl'] = $faceUrl;
131
			$person['count'] = $facesCount;
132
133
			$resp['persons'][] = $person;
134
		}
135
		return new DataResponse($resp);
136
	}
137
138
	/**
139
	 * @NoAdminRequired
140
	 */
141
	public function find(int $id) {
142
		$person = $this->personMapper->find($this->userId, $id);
143
144
		$resp = [];
145
		$faces = [];
146
		$personFaces = $this->faceMapper->findFacesFromPerson($this->userId, $person->getId(), $this->settingsService->getCurrentFaceModel());
147
		foreach ($personFaces as $personFace) {
148
			$image = $this->imageMapper->find($this->userId, $personFace->getImage());
149
			$fileId = $image->getFile();
150
			if ($fileId === null) continue;
151
152
			$fileUrl = $this->getRedirectToFileUrl($fileId);
153
			if ($fileUrl === null) continue;
154
155
			$face = [];
156
			$face['thumbUrl'] = $this->getThumbUrl($personFace->getId());
0 ignored issues
show
Bug introduced by
The call to OCA\FaceRecognition\Cont...ntroller::getThumbUrl() has too few arguments starting with size. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

156
			/** @scrutinizer ignore-call */ 
157
   $face['thumbUrl'] = $this->getThumbUrl($personFace->getId());

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
157
			$face['fileUrl'] = $fileUrl;
158
			$faces[] = $face;
159
		}
160
		$resp['name'] = $person->getName();
161
		$resp['id'] = $person->getId();
162
		$resp['faces'] = $faces;
163
164
		return new DataResponse($resp);
165
	}
166
167
	/**
168
	 * @NoAdminRequired
169
	 */
170
	public function findByName(string $personName) {
171
		$userEnabled = $this->settingsService->getUserEnabled($this->userId);
172
173
		$resp = array();
174
		$resp['enabled'] = $userEnabled;
175
		$resp['name'] = $personName;
176
		$resp['clusters'] = 0;
177
		$resp['images'] = array();
178
179
		if (!$userEnabled)
180
			return new DataResponse($resp);
181
182
		$modelId = $this->settingsService->getCurrentFaceModel();
183
184
		$clusters = $this->personMapper->findByName($this->userId, $modelId, $personName);
185
		foreach ($clusters as $cluster) {
186
			$resp['clusters']++;
187
188
			$faces = $this->faceMapper->findFacesFromPerson($this->userId, $cluster->getId(), $modelId);
189
			foreach ($faces as $face) {
190
				$image = $this->imageMapper->find($this->userId, $face->getImage());
191
192
				$fileId = $image->getFile();
193
				if ($fileId === null) continue;
194
195
				$fileUrl = $this->getRedirectToFileUrl($fileId);
196
				if ($fileUrl === null) continue;
197
198
				$thumbUrl = $this->getPreviewUrl($fileId, 256);
199
				if ($thumbUrl === null) continue;
200
201
				$image = [];
202
				$image['thumbUrl'] = $thumbUrl;
203
				$image['fileUrl'] = $fileUrl;
204
205
				$resp['images'][] = $image;
206
			}
207
		}
208
209
		return new DataResponse($resp);
210
	}
211
212
	/**
213
	 * @NoAdminRequired
214
	 */
215
	public function findClustersByName(string $personName) {
216
		$userEnabled = $this->settingsService->getUserEnabled($this->userId);
217
218
		$resp = array();
219
		$resp['enabled'] = $userEnabled;
220
		$resp['clusters'] = array();
221
222
		if (!$userEnabled)
223
			return new DataResponse($resp);
224
225
		$modelId = $this->settingsService->getCurrentFaceModel();
226
227
		$persons = $this->personMapper->findByName($this->userId, $modelId, $personName);
228
		foreach ($persons as $person) {
229
			$personFaces = $this->faceMapper->findFacesFromPerson($this->userId, $person->getId(), $modelId);
230
231
			$faces = [];
232
			foreach ($personFaces as $personFace) {
233
				$image = $this->imageMapper->find($this->userId, $personFace->getImage());
234
				$fileId = $image->getFile();
235
				if ($fileId === null) continue;
236
237
				$fileUrl = $this->getRedirectToFileUrl($fileId);
238
				if ($fileUrl === null) continue;
239
240
				$face = [];
241
				$face['thumbUrl'] = $this->getThumbUrl($personFace->getId(), 50);
242
				$face['fileUrl'] = $fileUrl;
243
				$faces[] = $face;
244
			}
245
246
			$cluster = [];
247
			$cluster['name'] = $person->getName();
248
			$cluster['count'] = count($personFaces);
249
			$cluster['id'] = $person->getId();
250
			$cluster['faces'] = $faces;
251
			$resp['clusters'][] = $cluster;
252
		}
253
254
		return new DataResponse($resp);
255
	}
256
257
	/**
258
	 * @NoAdminRequired
259
	 *
260
	 */
261
	public function findUnassignedClusters() {
262
		$userEnabled = $this->settingsService->getUserEnabled($this->userId);
263
264
		$resp = array();
265
		$resp['enabled'] = $userEnabled;
266
		$resp['clusters'] = array();
267
268
		if (!$userEnabled)
269
			return new DataResponse($resp);
270
271
		$modelId = $this->settingsService->getCurrentFaceModel();
272
273
		$persons = $this->personMapper->findUnassigned($this->userId, $modelId);
274
		foreach ($persons as $person) {
275
			$personFaces = $this->faceMapper->findFacesFromPerson($this->userId, $person->getId(), $modelId);
276
			if (count($personFaces) === 1)
277
				continue;
278
279
			$faces = [];
280
			foreach ($personFaces as $personFace) {
281
				$face = [];
282
				$face['thumbUrl'] = $this->getThumbUrl($personFace->getId(), 50);
283
				$faces[] = $face;
284
			}
285
286
			$cluster = [];
287
			$cluster['count'] = count($personFaces);
288
			$cluster['id'] = $person->getId();
289
			$cluster['faces'] = $faces;
290
			$resp['clusters'][] = $cluster;
291
		}
292
293
		return new DataResponse($resp);
294
	}
295
296
	/**
297
	 * @NoAdminRequired
298
	 *
299
	 * @param string $personName
300
	 * @param string $name
301
	 */
302
	public function updatePerson($personName, $name) {
303
		$modelId = $this->settingsService->getCurrentFaceModel();
304
		$clusters = $this->personMapper->findByName($this->userId, $modelId, $personName);
305
		foreach ($clusters as $person) {
306
			$person->setName($name);
307
			$this->personMapper->update($person);
308
		}
309
		return $this->findByName($name);
310
	}
311
312
	/**
313
	 * @NoAdminRequired
314
	 *
315
	 * @param int $id
316
	 * @param string $name
317
	 */
318
	public function updateName($id, $name) {
319
		$person = $this->personMapper->find ($this->userId, $id);
320
		$person->setName($name);
321
		$this->personMapper->update($person);
322
323
		$newPerson = $this->personMapper->find($this->userId, $id);
324
		return new DataResponse($newPerson);
325
	}
326
327
	/**
328
	 * Url to thumb face
329
	 *
330
	 * @param int $faceId face id to show
331
	 * @param int $size Size of face thumbnails
332
	 */
333
	private function getThumbUrl(int $faceId, int $size) {
334
		$params = [];
335
		$params['id'] = $faceId;
336
		$params['size'] = $size;
337
		return $this->urlGenerator->linkToRoute('facerecognition.face.getThumb', $params);
338
	}
339
340
	/**
341
	 * Get thumbnail of the give file id
342
	 *
343
	 * @param int $fileId file id to show
344
	 * @param int $sideSize side lenght to show
345
	 */
346
	public function getPreviewUrl(int $fileId, int $sideSize): ?string {
347
		$userFolder = $this->rootFolder->getUserFolder($this->userId);
348
		$file = current($userFolder->getById($fileId));
349
350
		if (!($file instanceof File)) {
351
			// If we cannot find a file probably it was deleted out of our control and we must clean our tables.
352
			$this->settingsService->setNeedRemoveStaleImages(true, $this->userId);
353
			return null;
354
		}
355
356
		return '/core/preview?fileId=' . $fileId .'&x=' . $sideSize . '&y=' . $sideSize . '&a=false&v=' . $file->getETag();
357
	}
358
359
	/**
360
	 * Redirects to the file list and highlight the given file id
361
	 *
362
	 * @param int $fileId file id to show
363
	 */
364
	private function getRedirectToFileUrl(int $fileId) {
365
		$uid        = $this->userSession->getUser()->getUID();
366
		$baseFolder = $this->rootFolder->getUserFolder($uid);
367
		$files      = $baseFolder->getById($fileId);
368
		$file       = current($files);
369
370
		if(!($file instanceof File)) {
371
			// If we cannot find a file probably it was deleted out of our control and we must clean our tables.
372
			$this->settingsService->setNeedRemoveStaleImages(true, $this->userId);
373
			return null;
374
		}
375
376
		$params = [];
377
		$params['dir'] = $baseFolder->getRelativePath($file->getParent()->getPath());
378
		$params['scrollto'] = $file->getName();
379
380
		return $this->urlGenerator->linkToRoute('files.view.index', $params);
381
	}
382
383
}
384