1 | <?php |
||||
2 | /** |
||||
3 | * @copyright Copyright (c) 2018-2021, Matias De lellis <[email protected]> |
||||
4 | * @copyright Copyright (c) 2018-2019, Branko Kokanovic <[email protected]> |
||||
5 | * |
||||
6 | * @author Branko Kokanovic <[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 | namespace OCA\FaceRecognition\Db; |
||||
25 | |||||
26 | use OC\DB\QueryBuilder\Literal; |
||||
0 ignored issues
–
show
|
|||||
27 | |||||
28 | use OCP\IDBConnection; |
||||
29 | use OCP\IUser; |
||||
30 | |||||
31 | use OCP\AppFramework\Db\QBMapper; |
||||
32 | use OCP\AppFramework\Db\DoesNotExistException; |
||||
33 | use OCP\DB\QueryBuilder\IQueryBuilder; |
||||
34 | |||||
35 | class PersonMapper extends QBMapper { |
||||
36 | |||||
37 | 1 | public function __construct(IDBConnection $db) { |
|||
38 | 1 | parent::__construct($db, 'facerecog_persons', '\OCA\FaceRecognition\Db\Person'); |
|||
39 | } |
||||
40 | |||||
41 | /** |
||||
42 | * @param string $userId ID of the user |
||||
43 | * @param int $personId ID of the person |
||||
44 | * |
||||
45 | * @return Person |
||||
46 | */ |
||||
47 | 8 | public function find(string $userId, int $personId): Person { |
|||
48 | 8 | $qb = $this->db->getQueryBuilder(); |
|||
49 | 8 | $qb->select('id', 'name', 'is_visible') |
|||
50 | 8 | ->from($this->getTableName(), 'p') |
|||
51 | 8 | ->where($qb->expr()->eq('id', $qb->createNamedParameter($personId))) |
|||
52 | 8 | ->andWhere($qb->expr()->eq('user', $qb->createNamedParameter($userId))); |
|||
53 | 8 | return $this->findEntity($qb); |
|||
0 ignored issues
–
show
|
|||||
54 | } |
||||
55 | |||||
56 | /** |
||||
57 | * @param string $userId ID of the user |
||||
58 | * @param int $modelId ID of the model |
||||
59 | * @param string $personName name of the person to find |
||||
60 | * @return Person[] |
||||
61 | */ |
||||
62 | 2 | public function findByName(string $userId, int $modelId, string $personName): array { |
|||
63 | 2 | $sub = $this->db->getQueryBuilder(); |
|||
64 | 2 | $sub->select(new Literal('1')) |
|||
65 | 2 | ->from('facerecog_faces', 'f') |
|||
66 | 2 | ->innerJoin('f', 'facerecog_images' ,'i', $sub->expr()->eq('f.image', 'i.id')) |
|||
67 | 2 | ->where($sub->expr()->eq('p.id', 'f.person')) |
|||
68 | 2 | ->andWhere($sub->expr()->eq('i.user', $sub->createParameter('user_id'))) |
|||
69 | 2 | ->andWhere($sub->expr()->eq('i.model', $sub->createParameter('model_id'))) |
|||
70 | 2 | ->andWhere($sub->expr()->eq('p.name', $sub->createParameter('person_name'))); |
|||
71 | |||||
72 | 2 | $qb = $this->db->getQueryBuilder(); |
|||
73 | 2 | $qb->select('id', 'name', 'is_valid') |
|||
74 | 2 | ->from($this->getTableName(), 'p') |
|||
75 | 2 | ->where('EXISTS (' . $sub->getSQL() . ')') |
|||
76 | 2 | ->setParameter('user_id', $userId) |
|||
77 | 2 | ->setParameter('model_id', $modelId) |
|||
78 | 2 | ->setParameter('person_name', $personName); |
|||
79 | |||||
80 | 2 | return $this->findEntities($qb); |
|||
81 | } |
||||
82 | |||||
83 | /** |
||||
84 | * @param string $userId ID of the user |
||||
85 | * @param int $modelId ID of the model |
||||
86 | * @return Person[] |
||||
87 | */ |
||||
88 | public function findUnassigned(string $userId, int $modelId): array { |
||||
89 | $sub = $this->db->getQueryBuilder(); |
||||
90 | $sub->select(new Literal('1')) |
||||
91 | ->from('facerecog_faces', 'f') |
||||
92 | ->innerJoin('f', 'facerecog_images' ,'i', $sub->expr()->eq('f.image', 'i.id')) |
||||
93 | ->where($sub->expr()->eq('p.id', 'f.person')) |
||||
94 | ->andWhere($sub->expr()->eq('i.user', $sub->createParameter('user_id'))) |
||||
95 | ->andWhere($sub->expr()->eq('i.model', $sub->createParameter('model_id'))); |
||||
96 | |||||
97 | $qb = $this->db->getQueryBuilder(); |
||||
98 | $qb->select('id', 'is_valid') |
||||
99 | ->from($this->getTableName(), 'p') |
||||
100 | ->where('EXISTS (' . $sub->getSQL() . ')') |
||||
101 | ->andWhere($qb->expr()->eq('is_valid', $qb->createParameter('is_valid'))) |
||||
102 | ->andWhere($qb->expr()->eq('is_visible', $qb->createParameter('is_visible'))) |
||||
103 | ->andWhere($qb->expr()->isNull('name')) |
||||
104 | ->setParameter('user_id', $userId) |
||||
105 | ->setParameter('model_id', $modelId) |
||||
106 | ->setParameter('is_valid', true, IQueryBuilder::PARAM_BOOL) |
||||
107 | ->setParameter('is_visible', true, IQueryBuilder::PARAM_BOOL); |
||||
108 | |||||
109 | return $this->findEntities($qb); |
||||
110 | } |
||||
111 | |||||
112 | /** |
||||
113 | * @param string $userId ID of the user |
||||
114 | * @param int $modelId ID of the model |
||||
115 | * @return Person[] |
||||
116 | */ |
||||
117 | public function findIgnored(string $userId, int $modelId): array { |
||||
118 | $sub = $this->db->getQueryBuilder(); |
||||
119 | $sub->select(new Literal('1')) |
||||
120 | ->from('facerecog_faces', 'f') |
||||
121 | ->innerJoin('f', 'facerecog_images' ,'i', $sub->expr()->eq('f.image', 'i.id')) |
||||
122 | ->where($sub->expr()->eq('p.id', 'f.person')) |
||||
123 | ->andWhere($sub->expr()->eq('i.user', $sub->createParameter('user_id'))) |
||||
124 | ->andWhere($sub->expr()->eq('i.model', $sub->createParameter('model_id'))); |
||||
125 | |||||
126 | $qb = $this->db->getQueryBuilder(); |
||||
127 | $qb->select('id', 'is_valid') |
||||
128 | ->from($this->getTableName(), 'p') |
||||
129 | ->where('EXISTS (' . $sub->getSQL() . ')') |
||||
130 | ->andWhere($qb->expr()->eq('is_valid', $qb->createParameter('is_valid'))) |
||||
131 | ->andWhere($qb->expr()->eq('is_visible', $qb->createParameter('is_visible'))) |
||||
132 | ->andWhere($qb->expr()->isNull('name')) |
||||
133 | ->setParameter('user_id', $userId) |
||||
134 | ->setParameter('model_id', $modelId) |
||||
135 | ->setParameter('is_valid', true, IQueryBuilder::PARAM_BOOL) |
||||
136 | ->setParameter('is_visible', false, IQueryBuilder::PARAM_BOOL); |
||||
137 | |||||
138 | return $this->findEntities($qb); |
||||
139 | } |
||||
140 | |||||
141 | /** |
||||
142 | * @param string $userId ID of the user |
||||
143 | * @param int $modelId ID of the model |
||||
144 | * @return Person[] |
||||
145 | */ |
||||
146 | 13 | public function findAll(string $userId, int $modelId): array { |
|||
147 | 13 | $sub = $this->db->getQueryBuilder(); |
|||
148 | 13 | $sub->select(new Literal('1')) |
|||
149 | 13 | ->from('facerecog_faces', 'f') |
|||
150 | 13 | ->innerJoin('f', 'facerecog_images' ,'i', $sub->expr()->eq('f.image', 'i.id')) |
|||
151 | 13 | ->where($sub->expr()->eq('p.id', 'f.person')) |
|||
152 | 13 | ->andWhere($sub->expr()->eq('i.user', $sub->createParameter('user_id'))) |
|||
153 | 13 | ->andWhere($sub->expr()->eq('i.model', $sub->createParameter('model_id'))); |
|||
154 | |||||
155 | 13 | $qb = $this->db->getQueryBuilder(); |
|||
156 | 13 | $qb->select('id', 'name', 'is_valid') |
|||
157 | 13 | ->from($this->getTableName(), 'p') |
|||
158 | 13 | ->where('EXISTS (' . $sub->getSQL() . ')') |
|||
159 | 13 | ->setParameter('user_id', $userId) |
|||
160 | 13 | ->setParameter('model_id', $modelId); |
|||
161 | |||||
162 | 13 | return $this->findEntities($qb); |
|||
163 | } |
||||
164 | |||||
165 | /** |
||||
166 | * @param string $userId ID of the user |
||||
167 | * |
||||
168 | * @return Person[] |
||||
169 | */ |
||||
170 | 7 | public function findDistinctNames(string $userId, int $modelId): array { |
|||
171 | 7 | $qb = $this->db->getQueryBuilder(); |
|||
172 | 7 | $qb->selectDistinct('name') |
|||
173 | 7 | ->from($this->getTableName(), 'p') |
|||
174 | 7 | ->innerJoin('p', 'facerecog_faces' , 'f', $qb->expr()->eq('f.person', 'p.id')) |
|||
175 | 7 | ->innerJoin('f', 'facerecog_images' ,'i', $qb->expr()->eq('f.image', 'i.id')) |
|||
176 | 7 | ->where($qb->expr()->eq('i.user', $qb->createParameter('user_id'))) |
|||
177 | 7 | ->andWhere($qb->expr()->eq('i.model', $qb->createParameter('model_id'))) |
|||
178 | 7 | ->andwhere($qb->expr()->isNotNull('p.name')) |
|||
179 | 7 | ->setParameter('user_id', $userId) |
|||
180 | 7 | ->setParameter('model_id', $modelId); |
|||
181 | 7 | return $this->findEntities($qb); |
|||
182 | } |
||||
183 | |||||
184 | /** |
||||
185 | * @param string $userId ID of the user |
||||
186 | * |
||||
187 | * @return Person[] |
||||
188 | */ |
||||
189 | public function findDistinctNamesSelected(string $userId, int $modelId, $faceNames): array { |
||||
190 | $qb = $this->db->getQueryBuilder(); |
||||
191 | $qb->selectDistinct('name') |
||||
192 | ->from($this->getTableName(), 'p') |
||||
193 | ->innerJoin('p', 'facerecog_faces' , 'f', $qb->expr()->eq('f.person', 'p.id')) |
||||
194 | ->innerJoin('f', 'facerecog_images' ,'i', $qb->expr()->eq('f.image', 'i.id')) |
||||
195 | ->where($qb->expr()->eq('i.user', $qb->createParameter('user_id'))) |
||||
196 | ->andWhere($qb->expr()->eq('i.model', $qb->createParameter('model_id'))) |
||||
197 | ->andwhere($qb->expr()->isNotNull('p.name')) |
||||
198 | ->andWhere($qb->expr()->eq('p.name', $qb->createParameter('faceNames'))) |
||||
199 | ->setParameter('user_id', $userId) |
||||
200 | ->setParameter('model_id', $modelId) |
||||
201 | ->setParameter('faceNames', $faceNames); |
||||
202 | return $this->findEntities($qb); |
||||
203 | } |
||||
204 | |||||
205 | /** |
||||
206 | * Search Person by name |
||||
207 | * |
||||
208 | * @param int|null $offset |
||||
209 | * @param int|null $limit |
||||
210 | */ |
||||
211 | public function findPersonsLike(string $userId, int $modelId, string $name, ?int $offset = null, ?int $limit = null): array { |
||||
212 | $qb = $this->db->getQueryBuilder(); |
||||
213 | $qb->selectDistinct('p.name') |
||||
214 | ->from($this->getTableName(), 'p') |
||||
215 | ->innerJoin('p', 'facerecog_faces', 'f', $qb->expr()->eq('f.person', 'p.id')) |
||||
216 | ->innerJoin('p', 'facerecog_images', 'i', $qb->expr()->eq('f.image', 'i.id')) |
||||
217 | ->where($qb->expr()->eq('p.user', $qb->createNamedParameter($userId))) |
||||
218 | ->andWhere($qb->expr()->eq('model', $qb->createNamedParameter($modelId))) |
||||
219 | ->andWhere($qb->expr()->eq('is_processed', $qb->createNamedParameter(True))) |
||||
220 | ->andWhere($qb->expr()->like($qb->func()->lower('p.name'), $qb->createParameter('query'))); |
||||
221 | |||||
222 | $query = '%' . $this->db->escapeLikeParameter(strtolower($name)) . '%'; |
||||
223 | $qb->setParameter('query', $query); |
||||
224 | |||||
225 | $qb->setFirstResult($offset); |
||||
226 | $qb->setMaxResults($limit); |
||||
227 | |||||
228 | return $this->findEntities($qb); |
||||
229 | } |
||||
230 | |||||
231 | /** |
||||
232 | * Returns count of persons found for a given user. |
||||
233 | * |
||||
234 | * @param string $userId ID of the user |
||||
235 | * @param int $modelId ID of the model |
||||
236 | * @return int Count of persons |
||||
237 | */ |
||||
238 | 7 | public function countPersons(string $userId, int $modelId): int { |
|||
239 | 7 | return count($this->findDistinctNames($userId, $modelId)); |
|||
240 | } |
||||
241 | |||||
242 | /** |
||||
243 | * Returns count of clusters found for a given user. |
||||
244 | * |
||||
245 | * @param string $userId ID of the user |
||||
246 | * @param int $modelId ID of the model |
||||
247 | * @param bool $onlyInvalid True if client wants count of invalid clusters only, |
||||
248 | * false if client want count of all clusters |
||||
249 | * @return int Count of clusters |
||||
250 | */ |
||||
251 | 11 | public function countClusters(string $userId, int $modelId, bool $onlyInvalid=false): int { |
|||
252 | 11 | $sub = $this->db->getQueryBuilder(); |
|||
253 | 11 | $sub->select(new Literal('1')) |
|||
254 | 11 | ->from('facerecog_faces', 'f') |
|||
255 | 11 | ->innerJoin('f', 'facerecog_images' ,'i', $sub->expr()->eq('f.image', 'i.id')) |
|||
256 | 11 | ->where($sub->expr()->eq('p.id', 'f.person')) |
|||
257 | 11 | ->andWhere($sub->expr()->eq('i.user', $sub->createParameter('user_id'))) |
|||
258 | 11 | ->andWhere($sub->expr()->eq('i.model', $sub->createParameter('model_id'))); |
|||
259 | |||||
260 | 11 | $qb = $this->db->getQueryBuilder(); |
|||
261 | 11 | $qb->select($qb->createFunction('COUNT(' . $qb->getColumnName('id') . ')')) |
|||
262 | 11 | ->from($this->getTableName(), 'p') |
|||
263 | 11 | ->where('EXISTS (' . $sub->getSQL() . ')'); |
|||
264 | |||||
265 | 11 | if ($onlyInvalid) { |
|||
266 | $qb = $qb |
||||
267 | ->andWhere($qb->expr()->eq('is_valid', $qb->createParameter('is_valid'))) |
||||
268 | ->setParameter('is_valid', false, IQueryBuilder::PARAM_BOOL); |
||||
269 | } |
||||
270 | |||||
271 | 11 | $qb = $qb |
|||
272 | 11 | ->setParameter('user_id', $userId) |
|||
273 | 11 | ->setParameter('model_id', $modelId); |
|||
274 | |||||
275 | 11 | $resultStatement = $qb->execute(); |
|||
0 ignored issues
–
show
The function
OCP\DB\QueryBuilder\IQueryBuilder::execute() has been deprecated: 22.0.0 Use executeQuery or executeStatement
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||
276 | 11 | $data = $resultStatement->fetch(\PDO::FETCH_NUM); |
|||
277 | 11 | $resultStatement->closeCursor(); |
|||
278 | |||||
279 | 11 | return (int)$data[0]; |
|||
280 | } |
||||
281 | |||||
282 | /** |
||||
283 | * Based on a given image, takes all faces that belong to that image |
||||
284 | * and invalidates all person that those faces belongs to. |
||||
285 | * |
||||
286 | * @param int $imageId ID of image for which to invalidate persons for |
||||
287 | * |
||||
288 | * @return void |
||||
289 | */ |
||||
290 | 12 | public function invalidatePersons(int $imageId): void { |
|||
291 | 12 | $sub = $this->db->getQueryBuilder(); |
|||
292 | 12 | $tableNameWithPrefixWithoutQuotes = trim($sub->getTableName($this->getTableName()), '`'); |
|||
293 | 12 | $sub->select(new Literal('1')); |
|||
294 | 12 | $sub->from('facerecog_images', 'i') |
|||
295 | 12 | ->innerJoin('i', 'facerecog_faces' ,'f', $sub->expr()->eq('i.id', 'f.image')) |
|||
296 | 12 | ->where($sub->expr()->eq($tableNameWithPrefixWithoutQuotes . '.id', 'f.person')) |
|||
297 | 12 | ->andWhere($sub->expr()->eq('i.id', $sub->createParameter('image_id'))); |
|||
298 | |||||
299 | 12 | $qb = $this->db->getQueryBuilder(); |
|||
300 | 12 | $qb->update($this->getTableName()) |
|||
0 ignored issues
–
show
The function
OCP\DB\QueryBuilder\IQueryBuilder::execute() has been deprecated: 22.0.0 Use executeQuery or executeStatement
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||
301 | 12 | ->set("is_valid", $qb->createParameter('is_valid')) |
|||
302 | 12 | ->where('EXISTS (' . $sub->getSQL() . ')') |
|||
303 | 12 | ->setParameter('image_id', $imageId) |
|||
304 | 12 | ->setParameter('is_valid', false, IQueryBuilder::PARAM_BOOL) |
|||
305 | 12 | ->execute(); |
|||
306 | } |
||||
307 | |||||
308 | /** |
||||
309 | * Based on current clusters and new clusters, do database reconciliation. |
||||
310 | * It tries to do that in minimal number of SQL queries. Operation is atomic. |
||||
311 | * |
||||
312 | * Clusters are array, where keys are ID of persons, and values are indexed arrays |
||||
313 | * with values that are ID of the faces for those persons. |
||||
314 | * |
||||
315 | * @param string $userId ID of the user that clusters belong to |
||||
316 | * @param array $currentClusters Current clusters |
||||
317 | * @param array $newClusters New clusters |
||||
318 | * |
||||
319 | * @return void |
||||
320 | */ |
||||
321 | 14 | public function mergeClusterToDatabase(string $userId, $currentClusters, $newClusters): void { |
|||
322 | 14 | $this->db->beginTransaction(); |
|||
323 | 14 | $currentDateTime = new \DateTime(); |
|||
324 | |||||
325 | try { |
||||
326 | // Delete clusters that do not exist anymore |
||||
327 | 14 | foreach($currentClusters as $oldPerson => $oldFaces) { |
|||
328 | 11 | if (array_key_exists($oldPerson, $newClusters)) { |
|||
329 | 6 | continue; |
|||
330 | } |
||||
331 | |||||
332 | // OK, we bumped into cluster that existed and now it does not exist. |
||||
333 | // We need to remove all references to it and to delete it. |
||||
334 | 7 | foreach ($oldFaces as $oldFace) { |
|||
335 | 7 | $this->updateFace($oldFace, null); |
|||
336 | } |
||||
337 | |||||
338 | // todo: this is not very cool. What if user had associated linked user to this. And all lost? |
||||
339 | 7 | $qb = $this->db->getQueryBuilder(); |
|||
340 | // todo: for extra safety, we should probably add here additional condition, where (user=$userId) |
||||
341 | 7 | $qb |
|||
0 ignored issues
–
show
The function
OCP\DB\QueryBuilder\IQueryBuilder::execute() has been deprecated: 22.0.0 Use executeQuery or executeStatement
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||
342 | 7 | ->delete($this->getTableName()) |
|||
343 | 7 | ->where($qb->expr()->eq('id', $qb->createNamedParameter($oldPerson))) |
|||
344 | 7 | ->execute(); |
|||
345 | } |
||||
346 | |||||
347 | // Modify existing clusters |
||||
348 | 14 | foreach($newClusters as $newPerson=>$newFaces) { |
|||
349 | 12 | if (!array_key_exists($newPerson, $currentClusters)) { |
|||
350 | // This cluster didn't exist, there is nothing to modify |
||||
351 | // It will be processed during cluster adding operation |
||||
352 | 9 | continue; |
|||
353 | } |
||||
354 | |||||
355 | 6 | $oldFaces = $currentClusters[$newPerson]; |
|||
356 | 6 | if ($newFaces === $oldFaces) { |
|||
357 | // Set cluster as valid now |
||||
358 | 2 | $qb = $this->db->getQueryBuilder(); |
|||
359 | 2 | $qb |
|||
0 ignored issues
–
show
The function
OCP\DB\QueryBuilder\IQueryBuilder::execute() has been deprecated: 22.0.0 Use executeQuery or executeStatement
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||
360 | 2 | ->update($this->getTableName()) |
|||
361 | 2 | ->set("is_valid", $qb->createParameter('is_valid')) |
|||
362 | 2 | ->where($qb->expr()->eq('id', $qb->createNamedParameter($newPerson))) |
|||
363 | 2 | ->setParameter('is_valid', true, IQueryBuilder::PARAM_BOOL) |
|||
364 | 2 | ->execute(); |
|||
365 | 2 | continue; |
|||
366 | } |
||||
367 | |||||
368 | // OK, set of faces do differ. Now, we could potentially go into finer grain details |
||||
369 | // and add/remove each individual face, but this seems too detailed. Enough is to |
||||
370 | // reset all existing faces to null and to add new faces to new person. That should |
||||
371 | // take care of both faces that are removed from cluster, as well as for newly added |
||||
372 | // faces to this cluster. |
||||
373 | |||||
374 | // First remove all old faces from any cluster (reset them to null) |
||||
375 | 5 | foreach ($oldFaces as $oldFace) { |
|||
376 | // Reset face to null only if it wasn't moved to other cluster! |
||||
377 | // (if face is just moved to other cluster, do not reset to null, as some other |
||||
378 | // pass for some other cluster will eventually update it to proper cluster) |
||||
379 | 5 | if ($this->isFaceInClusters($oldFace, $newClusters) === false) { |
|||
380 | 1 | $this->updateFace($oldFace, null); |
|||
381 | } |
||||
382 | } |
||||
383 | |||||
384 | // Then set all new faces to belong to this cluster |
||||
385 | 5 | foreach ($newFaces as $newFace) { |
|||
386 | 5 | $this->updateFace($newFace, $newPerson); |
|||
387 | } |
||||
388 | |||||
389 | // Set cluster as valid now |
||||
390 | 5 | $qb = $this->db->getQueryBuilder(); |
|||
391 | 5 | $qb |
|||
0 ignored issues
–
show
The function
OCP\DB\QueryBuilder\IQueryBuilder::execute() has been deprecated: 22.0.0 Use executeQuery or executeStatement
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||
392 | 5 | ->update($this->getTableName()) |
|||
393 | 5 | ->set("is_valid", $qb->createParameter('is_valid')) |
|||
394 | 5 | ->where($qb->expr()->eq('id', $qb->createNamedParameter($newPerson))) |
|||
395 | 5 | ->setParameter('is_valid', true, IQueryBuilder::PARAM_BOOL) |
|||
396 | 5 | ->execute(); |
|||
397 | } |
||||
398 | |||||
399 | // Add new clusters |
||||
400 | 14 | foreach($newClusters as $newPerson=>$newFaces) { |
|||
401 | 12 | if (array_key_exists($newPerson, $currentClusters)) { |
|||
402 | // This cluster already existed, nothing to add |
||||
403 | // It was already processed during modify cluster operation |
||||
404 | 6 | continue; |
|||
405 | } |
||||
406 | |||||
407 | // Create new cluster and add all faces to it |
||||
408 | 9 | $qb = $this->db->getQueryBuilder(); |
|||
409 | 9 | $qb |
|||
0 ignored issues
–
show
The function
OCP\DB\QueryBuilder\IQueryBuilder::execute() has been deprecated: 22.0.0 Use executeQuery or executeStatement
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||
410 | 9 | ->insert($this->getTableName()) |
|||
411 | 9 | ->values([ |
|||
412 | 9 | 'user' => $qb->createNamedParameter($userId), |
|||
413 | 9 | 'is_valid' => $qb->createNamedParameter(true), |
|||
414 | 9 | 'last_generation_time' => $qb->createNamedParameter($currentDateTime, IQueryBuilder::PARAM_DATE), |
|||
0 ignored issues
–
show
OCP\DB\QueryBuilder\IQueryBuilder::PARAM_DATE of type string is incompatible with the type OCP\DB\QueryBuilder\IQueryBuilder expected by parameter $type of OCP\DB\QueryBuilder\IQue...:createNamedParameter() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
415 | 9 | 'linked_user' => $qb->createNamedParameter(null)]) |
|||
416 | 9 | ->execute(); |
|||
417 | 9 | $insertedPersonId = $qb->getLastInsertId(); |
|||
418 | 9 | foreach ($newFaces as $newFace) { |
|||
419 | 9 | $this->updateFace($newFace, $insertedPersonId); |
|||
420 | } |
||||
421 | } |
||||
422 | |||||
423 | 14 | $this->db->commit(); |
|||
424 | } catch (\Exception $e) { |
||||
425 | $this->db->rollBack(); |
||||
426 | throw $e; |
||||
427 | } |
||||
428 | } |
||||
429 | |||||
430 | /** |
||||
431 | * Deletes all persons from that user. |
||||
432 | * |
||||
433 | * @param string $userId User to drop persons from a table. |
||||
434 | * |
||||
435 | * @return void |
||||
436 | */ |
||||
437 | 28 | public function deleteUserPersons(string $userId): void { |
|||
438 | 28 | $qb = $this->db->getQueryBuilder(); |
|||
439 | 28 | $qb->delete($this->getTableName()) |
|||
0 ignored issues
–
show
The function
OCP\DB\QueryBuilder\IQueryBuilder::execute() has been deprecated: 22.0.0 Use executeQuery or executeStatement
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||
440 | 28 | ->where($qb->expr()->eq('user', $qb->createNamedParameter($userId))) |
|||
441 | 28 | ->execute(); |
|||
442 | } |
||||
443 | |||||
444 | /** |
||||
445 | * Deletes all persons from that user and model |
||||
446 | * |
||||
447 | * @param string $userId ID of user for drop from table |
||||
448 | * @param int $modelId |
||||
449 | * |
||||
450 | * @return void |
||||
451 | */ |
||||
452 | public function deleteUserModel(string $userId, int $modelId): void { |
||||
453 | //TODO: Make it atomic |
||||
454 | $qb = $this->db->getQueryBuilder(); |
||||
455 | $qb->delete($this->getTableName()) |
||||
456 | ->where($qb->expr()->eq('id', $qb->createParameter('person'))); |
||||
457 | |||||
458 | $persons = $this->findAll($userId, $modelId); |
||||
459 | foreach ($persons as $person) { |
||||
460 | $qb->setParameter('person', $person->getId())->execute(); |
||||
0 ignored issues
–
show
The function
OCP\DB\QueryBuilder\IQueryBuilder::execute() has been deprecated: 22.0.0 Use executeQuery or executeStatement
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||
461 | } |
||||
462 | } |
||||
463 | |||||
464 | /** |
||||
465 | * Deletes person if it is empty (have no faces associated to it) |
||||
466 | * |
||||
467 | * @param int $personId Person to check if it should be deleted |
||||
468 | * |
||||
469 | * @return void |
||||
470 | */ |
||||
471 | public function removeIfEmpty(int $personId): void { |
||||
472 | $sub = $this->db->getQueryBuilder(); |
||||
473 | $sub->select(new Literal('1')); |
||||
474 | $sub->from('facerecog_faces', 'f') |
||||
475 | ->where($sub->expr()->eq('f.person', $sub->createParameter('person'))); |
||||
476 | |||||
477 | $qb = $this->db->getQueryBuilder(); |
||||
478 | $qb->delete($this->getTableName()) |
||||
0 ignored issues
–
show
The function
OCP\DB\QueryBuilder\IQueryBuilder::execute() has been deprecated: 22.0.0 Use executeQuery or executeStatement
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||
479 | ->where($qb->expr()->eq('id', $qb->createParameter('person'))) |
||||
480 | ->andWhere('NOT EXISTS (' . $sub->getSQL() . ')') |
||||
481 | ->setParameter('person', $personId) |
||||
482 | ->execute(); |
||||
483 | } |
||||
484 | |||||
485 | /** |
||||
486 | * Deletes all persons that have no faces associated to them |
||||
487 | * |
||||
488 | * @param string $userId ID of user for which we are deleting orphaned persons |
||||
489 | */ |
||||
490 | 1 | public function deleteOrphaned(string $userId): int { |
|||
491 | 1 | $sub = $this->db->getQueryBuilder(); |
|||
492 | 1 | $sub->select(new Literal('1')); |
|||
493 | 1 | $sub->from('facerecog_faces', 'f') |
|||
494 | 1 | ->where($sub->expr()->eq('f.person', 'p.id')); |
|||
495 | |||||
496 | 1 | $qb = $this->db->getQueryBuilder(); |
|||
497 | 1 | $qb->select('p.id') |
|||
498 | 1 | ->from($this->getTableName(), 'p') |
|||
499 | 1 | ->where($qb->expr()->eq('p.user', $qb->createParameter('user'))) |
|||
500 | 1 | ->andWhere('NOT EXISTS (' . $sub->getSQL() . ')') |
|||
501 | 1 | ->setParameter('user', $userId); |
|||
502 | 1 | $orphanedPersons = $this->findEntities($qb); |
|||
503 | |||||
504 | 1 | $orphaned = 0; |
|||
505 | 1 | foreach ($orphanedPersons as $person) { |
|||
506 | $qb = $this->db->getQueryBuilder(); |
||||
507 | $orphaned += $qb->delete($this->getTableName()) |
||||
0 ignored issues
–
show
The function
OCP\DB\QueryBuilder\IQueryBuilder::execute() has been deprecated: 22.0.0 Use executeQuery or executeStatement
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||
508 | ->where($qb->expr()->eq('id', $qb->createNamedParameter($person->id))) |
||||
509 | ->execute(); |
||||
510 | } |
||||
511 | 1 | return $orphaned; |
|||
512 | } |
||||
513 | |||||
514 | /* |
||||
515 | * Mark the cluster as hidden or visible to user. |
||||
516 | * |
||||
517 | * @param int $personId ID of the person |
||||
518 | * @param bool $visible visibility of the person |
||||
519 | * |
||||
520 | * @return void |
||||
521 | */ |
||||
522 | public function setVisibility (int $personId, bool $visible): void { |
||||
523 | $qb = $this->db->getQueryBuilder(); |
||||
524 | if ($visible) { |
||||
525 | $qb->update($this->getTableName()) |
||||
0 ignored issues
–
show
The function
OCP\DB\QueryBuilder\IQueryBuilder::execute() has been deprecated: 22.0.0 Use executeQuery or executeStatement
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||
526 | ->set('is_visible', $qb->createNamedParameter(1)) |
||||
527 | ->where($qb->expr()->eq('id', $qb->createNamedParameter($personId))) |
||||
528 | ->execute(); |
||||
529 | } else { |
||||
530 | $qb->update($this->getTableName()) |
||||
0 ignored issues
–
show
The function
OCP\DB\QueryBuilder\IQueryBuilder::execute() has been deprecated: 22.0.0 Use executeQuery or executeStatement
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||
531 | ->set('is_visible', $qb->createNamedParameter(0)) |
||||
532 | ->set('name', $qb->createNamedParameter(null)) |
||||
533 | ->where($qb->expr()->eq('id', $qb->createNamedParameter($personId))) |
||||
534 | ->execute(); |
||||
535 | } |
||||
536 | } |
||||
537 | |||||
538 | /* |
||||
539 | * Mark the cluster as hidden or visible to user. |
||||
540 | * |
||||
541 | * @param int $personId ID of the person |
||||
542 | * @param int $faceId visibility of the person |
||||
543 | * @param string|null $name optional name to rename them. |
||||
544 | * |
||||
545 | * @return Person |
||||
546 | */ |
||||
547 | public function detachFace(int $personId, int $faceId, $name = null): Person { |
||||
548 | // Mark the face as non groupable. |
||||
549 | $qb = $this->db->getQueryBuilder(); |
||||
550 | $qb->update('facerecog_faces') |
||||
0 ignored issues
–
show
The function
OCP\DB\QueryBuilder\IQueryBuilder::execute() has been deprecated: 22.0.0 Use executeQuery or executeStatement
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||
551 | ->set('is_groupable', $qb->createParameter('is_groupable')) |
||||
552 | ->where($qb->expr()->eq('id', $qb->createNamedParameter($faceId))) |
||||
553 | ->setParameter('is_groupable', false, IQueryBuilder::PARAM_BOOL) |
||||
554 | ->execute(); |
||||
555 | |||||
556 | if ($this->countClusterFaces($personId) === 1) { |
||||
557 | // If cluster is an single face just rename it. |
||||
558 | $qb = $this->db->getQueryBuilder(); |
||||
559 | $qb->update($this->getTableName()) |
||||
0 ignored issues
–
show
The function
OCP\DB\QueryBuilder\IQueryBuilder::execute() has been deprecated: 22.0.0 Use executeQuery or executeStatement
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||
560 | ->set('name', $qb->createNamedParameter($name)) |
||||
561 | ->set('is_visible', $qb->createNamedParameter(true)) |
||||
562 | ->where($qb->expr()->eq('id', $qb->createNamedParameter($personId))) |
||||
563 | ->execute(); |
||||
564 | } else { |
||||
565 | // If there are other faces, must create a new person for that face. |
||||
566 | $qb = $this->db->getQueryBuilder(); |
||||
567 | $qb->select('user') |
||||
568 | ->from($this->getTableName()) |
||||
569 | ->where($qb->expr()->eq('id', $qb->createNamedParameter($personId))); |
||||
570 | $oldPerson = $this->findEntity($qb); |
||||
571 | |||||
572 | $qb = $this->db->getQueryBuilder(); |
||||
573 | $qb->insert($this->getTableName())->values([ |
||||
0 ignored issues
–
show
The function
OCP\DB\QueryBuilder\IQueryBuilder::execute() has been deprecated: 22.0.0 Use executeQuery or executeStatement
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||
574 | 'user' => $qb->createNamedParameter($oldPerson->getUser()), |
||||
575 | 'name' => $qb->createNamedParameter($name), |
||||
576 | 'is_valid' => $qb->createNamedParameter(true), |
||||
577 | 'last_generation_time' => $qb->createNamedParameter(new \DateTime(), IQueryBuilder::PARAM_DATE), |
||||
0 ignored issues
–
show
OCP\DB\QueryBuilder\IQueryBuilder::PARAM_DATE of type string is incompatible with the type OCP\DB\QueryBuilder\IQueryBuilder expected by parameter $type of OCP\DB\QueryBuilder\IQue...:createNamedParameter() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
578 | 'linked_user' => $qb->createNamedParameter(null), |
||||
579 | 'is_visible' => $qb->createNamedParameter(true) |
||||
580 | ])->execute(); |
||||
581 | |||||
582 | $personId = $qb->getLastInsertId(); |
||||
583 | |||||
584 | $qb = $this->db->getQueryBuilder(); |
||||
585 | $qb->update('facerecog_faces') |
||||
0 ignored issues
–
show
The function
OCP\DB\QueryBuilder\IQueryBuilder::execute() has been deprecated: 22.0.0 Use executeQuery or executeStatement
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||
586 | ->set('person', $qb->createParameter('person')) |
||||
587 | ->where($qb->expr()->eq('id', $qb->createNamedParameter($faceId))) |
||||
588 | ->setParameter('person', $personId) |
||||
589 | ->execute(); |
||||
590 | } |
||||
591 | |||||
592 | $qb = $this->db->getQueryBuilder(); |
||||
593 | $qb->select('id', 'name', 'is_valid', 'is_visible') |
||||
594 | ->from($this->getTableName()) |
||||
595 | ->where($qb->expr()->eq('id', $qb->createNamedParameter($personId))); |
||||
596 | return $this->findEntity($qb); |
||||
0 ignored issues
–
show
|
|||||
597 | } |
||||
598 | |||||
599 | public function countClusterFaces(int $personId): int { |
||||
600 | $qb = $this->db->getQueryBuilder(); |
||||
601 | $query = $qb |
||||
602 | ->select($qb->createFunction('COUNT(' . $qb->getColumnName('id') . ')')) |
||||
603 | ->from('facerecog_faces') |
||||
604 | ->where($qb->expr()->eq('person', $qb->createParameter('person'))) |
||||
605 | ->setParameter('person', $personId); |
||||
606 | $resultStatement = $query->execute(); |
||||
0 ignored issues
–
show
The function
OCP\DB\QueryBuilder\IQueryBuilder::execute() has been deprecated: 22.0.0 Use executeQuery or executeStatement
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||
607 | $data = $resultStatement->fetch(\PDO::FETCH_NUM); |
||||
608 | $resultStatement->closeCursor(); |
||||
609 | |||||
610 | return (int)$data[0]; |
||||
611 | } |
||||
612 | |||||
613 | /** |
||||
614 | * Updates one face with $faceId to database to person ID $personId. |
||||
615 | * |
||||
616 | * @param int $faceId ID of the face |
||||
617 | * @param int|null $personId ID of the person |
||||
618 | * |
||||
619 | * @return void |
||||
620 | */ |
||||
621 | 12 | private function updateFace(int $faceId, $personId): void { |
|||
622 | 12 | $qb = $this->db->getQueryBuilder(); |
|||
623 | 12 | $qb->update('facerecog_faces') |
|||
0 ignored issues
–
show
The function
OCP\DB\QueryBuilder\IQueryBuilder::execute() has been deprecated: 22.0.0 Use executeQuery or executeStatement
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||
624 | 12 | ->set("person", $qb->createNamedParameter($personId)) |
|||
625 | 12 | ->where($qb->expr()->eq('id', $qb->createNamedParameter($faceId))) |
|||
626 | 12 | ->execute(); |
|||
627 | } |
||||
628 | |||||
629 | /** |
||||
630 | * Checks if face with a given ID is in any cluster. |
||||
631 | * |
||||
632 | * @param int $faceId ID of the face to check |
||||
633 | * @param array $cluster All clusters to check into |
||||
634 | * |
||||
635 | * @return bool True if face is found in any cluster, false otherwise. |
||||
636 | */ |
||||
637 | 5 | private function isFaceInClusters(int $faceId, array $clusters): bool { |
|||
638 | 5 | foreach ($clusters as $_=>$faces) { |
|||
639 | 5 | if (in_array($faceId, $faces)) { |
|||
640 | 5 | return true; |
|||
641 | } |
||||
642 | } |
||||
643 | 1 | return false; |
|||
644 | } |
||||
645 | } |
||||
646 |
The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g.
excluded_paths: ["lib/*"]
, you can move it to the dependency path list as follows:For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths