Passed
Push — split-cluster-person ( 71fbb4...a0dc73 )
by Matias
07:16
created

PersonController::getPreviewUrl()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 9
c 1
b 0
f 0
nc 2
nop 2
dl 0
loc 14
ccs 0
cts 11
cp 0
crap 6
rs 9.9666
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['thumb-url'] = $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['thumb-url'] = $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['thumb-url'] = $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['file-url'] = $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, 128);
199
				if ($thumbUrl === null) continue;
200
201
				$image = [];
202
				$image['thumb-url'] = $thumbUrl;
203
				$image['file-url'] = $fileUrl;
204
205
				$resp['images'][] = $image;
206
			}
207
		}
208
209
		return new DataResponse($resp);
210
	}
211
212
213
214
	/**
215
	 * @NoAdminRequired
216
	 */
217
	public function findClustersByName(string $personName) {
218
		$userEnabled = $this->settingsService->getUserEnabled($this->userId);
219
220
		$resp = array();
221
		$resp['enabled'] = $userEnabled;
222
		$resp['clusters'] = array();
223
224
		if (!$userEnabled)
225
			return new DataResponse($resp);
226
227
		$modelId = $this->settingsService->getCurrentFaceModel();
228
229
		$persons = $this->personMapper->findByName($this->userId, $modelId, $personName);
230
		foreach ($persons as $person) {
231
			$personFaces = $this->faceMapper->findFacesFromPerson($this->userId, $person->getId(), $modelId);
232
233
			$faces = [];
234
			foreach ($personFaces as $personFace) {
235
				$image = $this->imageMapper->find($this->userId, $personFace->getImage());
236
				$fileId = $image->getFile();
237
				if ($fileId === null) continue;
238
239
				$fileUrl = $this->getRedirectToFileUrl($fileId);
240
				if ($fileUrl === null) continue;
241
242
				$face = [];
243
				$face['thumb-url'] = $this->getThumbUrl($personFace->getId(), 50);
244
				$face['file-url'] = $fileUrl;
245
				$faces[] = $face;
246
			}
247
248
			$cluster = [];
249
			$cluster['name'] = $person->getName();
250
			$cluster['count'] = count($personFaces);
251
			$cluster['id'] = $person->getId();
252
			$cluster['faces'] = $faces;
253
			$resp['clusters'][] = $cluster;
254
		}
255
256
		return new DataResponse($resp);
257
	}
258
259
	/**
260
	 * @NoAdminRequired
261
	 *
262
	 * @param int $id
263
	 * @param string $name
264
	 */
265
	public function updateName($id, $name) {
266
		$person = $this->personMapper->find ($this->userId, $id);
267
		$person->setName($name);
268
		$this->personMapper->update($person);
269
270
		$newPerson = $this->personMapper->find($this->userId, $id);
271
		return new DataResponse($newPerson);
272
	}
273
274
	/**
275
	 * Url to thumb face
276
	 *
277
	 * @param int $faceId face id to show
278
	 * @param int $size Size of face thumbnails
279
	 */
280
	private function getThumbUrl(int $faceId, int $size) {
281
		$params = [];
282
		$params['id'] = $faceId;
283
		$params['size'] = $size;
284
		return $this->urlGenerator->linkToRoute('facerecognition.face.getThumb', $params);
285
	}
286
287
	/**
288
	 * Get thumbnail of the give file id
289
	 *
290
	 * @param int $fileId file id to show
291
	 * @param int $sideSize side lenght to show
292
	 */
293
	public function getPreviewUrl(int $fileId, int $sideSize): ?string {
294
		$userFolder = $this->rootFolder->getUserFolder($this->userId);
295
		$file = current($userFolder->getById($fileId));
296
297
		if (!($file instanceof File)) {
298
			// If we cannot find a file probably it was deleted out of our control and we must clean our tables.
299
			$this->settingsService->setNeedRemoveStaleImages(true, $this->userId);
300
			return null;
301
		}
302
303
		return $this->urlGenerator->linkToRouteAbsolute('core.Preview.getPreview', [
304
			'file' => $userFolder->getRelativePath($file->getPath()),
305
			'x' => $sideSize,
306
			'y' => $sideSize
307
		]);
308
	}
309
310
	/**
311
	 * Redirects to the file list and highlight the given file id
312
	 *
313
	 * @param int $fileId file id to show
314
	 */
315
	private function getRedirectToFileUrl(int $fileId) {
316
		$uid        = $this->userSession->getUser()->getUID();
317
		$baseFolder = $this->rootFolder->getUserFolder($uid);
318
		$files      = $baseFolder->getById($fileId);
319
		$file       = current($files);
320
321
		if(!($file instanceof File)) {
322
			// If we cannot find a file probably it was deleted out of our control and we must clean our tables.
323
			$this->settingsService->setNeedRemoveStaleImages(true, $this->userId);
324
			return null;
325
		}
326
327
		$params = [];
328
		$params['dir'] = $baseFolder->getRelativePath($file->getParent()->getPath());
329
		$params['scrollto'] = $file->getName();
330
331
		return $this->urlGenerator->linkToRoute('files.view.index', $params);
332
	}
333
334
}
335