Passed
Push — master ( bbba7b...22edb6 )
by Blizzz
09:41 queued 12s
created
lib/private/Tagging/TagMapper.php 2 patches
Indentation   +39 added lines, -39 removed lines patch added patch discarded remove patch
@@ -35,46 +35,46 @@
 block discarded – undo
35 35
  */
36 36
 class TagMapper extends Mapper {
37 37
 
38
-	/**
39
-	 * Constructor.
40
-	 *
41
-	 * @param IDBConnection $db Instance of the Db abstraction layer.
42
-	 */
43
-	public function __construct(IDBConnection $db) {
44
-		parent::__construct($db, 'vcategory', Tag::class);
45
-	}
38
+    /**
39
+     * Constructor.
40
+     *
41
+     * @param IDBConnection $db Instance of the Db abstraction layer.
42
+     */
43
+    public function __construct(IDBConnection $db) {
44
+        parent::__construct($db, 'vcategory', Tag::class);
45
+    }
46 46
 
47
-	/**
48
-	 * Load tags from the database.
49
-	 *
50
-	 * @param array|string $owners The user(s) whose tags we are going to load.
51
-	 * @param string $type The type of item for which we are loading tags.
52
-	 * @return array An array of Tag objects.
53
-	 */
54
-	public function loadTags($owners, $type) {
55
-		if(!is_array($owners)) {
56
-			$owners = [$owners];
57
-		}
47
+    /**
48
+     * Load tags from the database.
49
+     *
50
+     * @param array|string $owners The user(s) whose tags we are going to load.
51
+     * @param string $type The type of item for which we are loading tags.
52
+     * @return array An array of Tag objects.
53
+     */
54
+    public function loadTags($owners, $type) {
55
+        if(!is_array($owners)) {
56
+            $owners = [$owners];
57
+        }
58 58
 
59
-		$sql = 'SELECT `id`, `uid`, `type`, `category` FROM `' . $this->getTableName() . '` '
60
-			. 'WHERE `uid` IN (' . str_repeat('?,', count($owners)-1) . '?) AND `type` = ? ORDER BY `category`';
61
-		return $this->findEntities($sql, array_merge($owners, [$type]));
62
-	}
59
+        $sql = 'SELECT `id`, `uid`, `type`, `category` FROM `' . $this->getTableName() . '` '
60
+            . 'WHERE `uid` IN (' . str_repeat('?,', count($owners)-1) . '?) AND `type` = ? ORDER BY `category`';
61
+        return $this->findEntities($sql, array_merge($owners, [$type]));
62
+    }
63 63
 
64
-	/**
65
-	 * Check if a given Tag object already exists in the database.
66
-	 *
67
-	 * @param Tag $tag The tag to look for in the database.
68
-	 * @return bool
69
-	 */
70
-	public function tagExists($tag) {
71
-		$sql = 'SELECT `id`, `uid`, `type`, `category` FROM `' . $this->getTableName() . '` '
72
-			. 'WHERE `uid` = ? AND `type` = ? AND `category` = ?';
73
-		try {
74
-			$this->findEntity($sql, [$tag->getOwner(), $tag->getType(), $tag->getName()]);
75
-		} catch (DoesNotExistException $e) {
76
-			return false;
77
-		}
78
-		return true;
79
-	}
64
+    /**
65
+     * Check if a given Tag object already exists in the database.
66
+     *
67
+     * @param Tag $tag The tag to look for in the database.
68
+     * @return bool
69
+     */
70
+    public function tagExists($tag) {
71
+        $sql = 'SELECT `id`, `uid`, `type`, `category` FROM `' . $this->getTableName() . '` '
72
+            . 'WHERE `uid` = ? AND `type` = ? AND `category` = ?';
73
+        try {
74
+            $this->findEntity($sql, [$tag->getOwner(), $tag->getType(), $tag->getName()]);
75
+        } catch (DoesNotExistException $e) {
76
+            return false;
77
+        }
78
+        return true;
79
+    }
80 80
 }
Please login to merge, or discard this patch.
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -52,12 +52,12 @@  discard block
 block discarded – undo
52 52
 	 * @return array An array of Tag objects.
53 53
 	 */
54 54
 	public function loadTags($owners, $type) {
55
-		if(!is_array($owners)) {
55
+		if (!is_array($owners)) {
56 56
 			$owners = [$owners];
57 57
 		}
58 58
 
59
-		$sql = 'SELECT `id`, `uid`, `type`, `category` FROM `' . $this->getTableName() . '` '
60
-			. 'WHERE `uid` IN (' . str_repeat('?,', count($owners)-1) . '?) AND `type` = ? ORDER BY `category`';
59
+		$sql = 'SELECT `id`, `uid`, `type`, `category` FROM `'.$this->getTableName().'` '
60
+			. 'WHERE `uid` IN ('.str_repeat('?,', count($owners) - 1).'?) AND `type` = ? ORDER BY `category`';
61 61
 		return $this->findEntities($sql, array_merge($owners, [$type]));
62 62
 	}
63 63
 
@@ -68,7 +68,7 @@  discard block
 block discarded – undo
68 68
 	 * @return bool
69 69
 	 */
70 70
 	public function tagExists($tag) {
71
-		$sql = 'SELECT `id`, `uid`, `type`, `category` FROM `' . $this->getTableName() . '` '
71
+		$sql = 'SELECT `id`, `uid`, `type`, `category` FROM `'.$this->getTableName().'` '
72 72
 			. 'WHERE `uid` = ? AND `type` = ? AND `category` = ?';
73 73
 		try {
74 74
 			$this->findEntity($sql, [$tag->getOwner(), $tag->getType(), $tag->getName()]);
Please login to merge, or discard this patch.
lib/private/Tagging/Tag.php 1 patch
Indentation   +47 added lines, -47 removed lines patch added patch discarded remove patch
@@ -38,54 +38,54 @@
 block discarded – undo
38 38
  */
39 39
 class Tag extends Entity {
40 40
 
41
-	protected $owner;
42
-	protected $type;
43
-	protected $name;
41
+    protected $owner;
42
+    protected $type;
43
+    protected $name;
44 44
 
45
-	/**
46
-	 * Constructor.
47
-	 *
48
-	 * @param string $owner The tag's owner
49
-	 * @param string $type The type of item this tag is used for
50
-	 * @param string $name The tag's name
51
-	 */
52
-	public function __construct($owner = null, $type = null, $name = null) {
53
-		$this->setOwner($owner);
54
-		$this->setType($type);
55
-		$this->setName($name);
56
-	}
45
+    /**
46
+     * Constructor.
47
+     *
48
+     * @param string $owner The tag's owner
49
+     * @param string $type The type of item this tag is used for
50
+     * @param string $name The tag's name
51
+     */
52
+    public function __construct($owner = null, $type = null, $name = null) {
53
+        $this->setOwner($owner);
54
+        $this->setType($type);
55
+        $this->setName($name);
56
+    }
57 57
 
58
-	/**
59
-	 * Transform a database columnname to a property
60
-	 *
61
-	 * @param string $columnName the name of the column
62
-	 * @return string the property name
63
-	 * @todo migrate existing database columns to the correct names
64
-	 * to be able to drop this direct mapping
65
-	 */
66
-	public function columnToProperty($columnName){
67
-		if ($columnName === 'category') {
68
-		    return 'name';
69
-		} elseif ($columnName === 'uid') {
70
-		    return 'owner';
71
-		} else {
72
-		    return parent::columnToProperty($columnName);
73
-		}
74
-	}
58
+    /**
59
+     * Transform a database columnname to a property
60
+     *
61
+     * @param string $columnName the name of the column
62
+     * @return string the property name
63
+     * @todo migrate existing database columns to the correct names
64
+     * to be able to drop this direct mapping
65
+     */
66
+    public function columnToProperty($columnName){
67
+        if ($columnName === 'category') {
68
+            return 'name';
69
+        } elseif ($columnName === 'uid') {
70
+            return 'owner';
71
+        } else {
72
+            return parent::columnToProperty($columnName);
73
+        }
74
+    }
75 75
 
76
-	/**
77
-	 * Transform a property to a database column name
78
-	 *
79
-	 * @param string $property the name of the property
80
-	 * @return string the column name
81
-	 */
82
-	public function propertyToColumn($property){
83
-		if ($property === 'name') {
84
-		    return 'category';
85
-		} elseif ($property === 'owner') {
86
-		    return 'uid';
87
-		} else {
88
-		    return parent::propertyToColumn($property);
89
-		}
90
-	}
76
+    /**
77
+     * Transform a property to a database column name
78
+     *
79
+     * @param string $property the name of the property
80
+     * @return string the column name
81
+     */
82
+    public function propertyToColumn($property){
83
+        if ($property === 'name') {
84
+            return 'category';
85
+        } elseif ($property === 'owner') {
86
+            return 'uid';
87
+        } else {
88
+            return parent::propertyToColumn($property);
89
+        }
90
+    }
91 91
 }
Please login to merge, or discard this patch.
lib/private/Tags.php 2 patches
Indentation   +805 added lines, -805 removed lines patch added patch discarded remove patch
@@ -54,809 +54,809 @@
 block discarded – undo
54 54
 
55 55
 class Tags implements ITags {
56 56
 
57
-	/**
58
-	 * Tags
59
-	 *
60
-	 * @var array
61
-	 */
62
-	private $tags = [];
63
-
64
-	/**
65
-	 * Used for storing objectid/categoryname pairs while rescanning.
66
-	 *
67
-	 * @var array
68
-	 */
69
-	private static $relations = [];
70
-
71
-	/**
72
-	 * Type
73
-	 *
74
-	 * @var string
75
-	 */
76
-	private $type;
77
-
78
-	/**
79
-	 * User
80
-	 *
81
-	 * @var string
82
-	 */
83
-	private $user;
84
-
85
-	/**
86
-	 * Are we including tags for shared items?
87
-	 *
88
-	 * @var bool
89
-	 */
90
-	private $includeShared = false;
91
-
92
-	/**
93
-	 * The current user, plus any owners of the items shared with the current
94
-	 * user, if $this->includeShared === true.
95
-	 *
96
-	 * @var array
97
-	 */
98
-	private $owners = [];
99
-
100
-	/**
101
-	 * The Mapper we're using to communicate our Tag objects to the database.
102
-	 *
103
-	 * @var TagMapper
104
-	 */
105
-	private $mapper;
106
-
107
-	/**
108
-	 * The sharing backend for objects of $this->type. Required if
109
-	 * $this->includeShared === true to determine ownership of items.
110
-	 *
111
-	 * @var \OCP\Share_Backend
112
-	 */
113
-	private $backend;
114
-
115
-	const TAG_TABLE = '*PREFIX*vcategory';
116
-	const RELATION_TABLE = '*PREFIX*vcategory_to_object';
117
-
118
-	/**
119
-	 * Constructor.
120
-	 *
121
-	 * @param TagMapper $mapper Instance of the TagMapper abstraction layer.
122
-	 * @param string $user The user whose data the object will operate on.
123
-	 * @param string $type The type of items for which tags will be loaded.
124
-	 * @param array $defaultTags Tags that should be created at construction.
125
-	 * @param boolean $includeShared Whether to include tags for items shared with this user by others.
126
-	 */
127
-	public function __construct(TagMapper $mapper, $user, $type, $defaultTags = [], $includeShared = false) {
128
-		$this->mapper = $mapper;
129
-		$this->user = $user;
130
-		$this->type = $type;
131
-		$this->includeShared = $includeShared;
132
-		$this->owners = [$this->user];
133
-		if ($this->includeShared) {
134
-			$this->owners = array_merge($this->owners, \OC\Share\Share::getSharedItemsOwners($this->user, $this->type, true));
135
-			$this->backend = \OC\Share\Share::getBackend($this->type);
136
-		}
137
-		$this->tags = $this->mapper->loadTags($this->owners, $this->type);
138
-
139
-		if(count($defaultTags) > 0 && count($this->tags) === 0) {
140
-			$this->addMultiple($defaultTags, true);
141
-		}
142
-	}
143
-
144
-	/**
145
-	 * Check if any tags are saved for this type and user.
146
-	 *
147
-	 * @return boolean
148
-	 */
149
-	public function isEmpty() {
150
-		return count($this->tags) === 0;
151
-	}
152
-
153
-	/**
154
-	 * Returns an array mapping a given tag's properties to its values:
155
-	 * ['id' => 0, 'name' = 'Tag', 'owner' = 'User', 'type' => 'tagtype']
156
-	 *
157
-	 * @param string $id The ID of the tag that is going to be mapped
158
-	 * @return array|false
159
-	 */
160
-	public function getTag($id) {
161
-		$key = $this->getTagById($id);
162
-		if ($key !== false) {
163
-			return $this->tagMap($this->tags[$key]);
164
-		}
165
-		return false;
166
-	}
167
-
168
-	/**
169
-	 * Get the tags for a specific user.
170
-	 *
171
-	 * This returns an array with maps containing each tag's properties:
172
-	 * [
173
-	 * 	['id' => 0, 'name' = 'First tag', 'owner' = 'User', 'type' => 'tagtype'],
174
-	 * 	['id' => 1, 'name' = 'Shared tag', 'owner' = 'Other user', 'type' => 'tagtype'],
175
-	 * ]
176
-	 *
177
-	 * @return array
178
-	 */
179
-	public function getTags() {
180
-		if(!count($this->tags)) {
181
-			return [];
182
-		}
183
-
184
-		usort($this->tags, function($a, $b) {
185
-			return strnatcasecmp($a->getName(), $b->getName());
186
-		});
187
-		$tagMap = [];
188
-
189
-		foreach($this->tags as $tag) {
190
-			if($tag->getName() !== ITags::TAG_FAVORITE) {
191
-				$tagMap[] = $this->tagMap($tag);
192
-			}
193
-		}
194
-		return $tagMap;
195
-
196
-	}
197
-
198
-	/**
199
-	 * Return only the tags owned by the given user, omitting any tags shared
200
-	 * by other users.
201
-	 *
202
-	 * @param string $user The user whose tags are to be checked.
203
-	 * @return array An array of Tag objects.
204
-	 */
205
-	public function getTagsForUser($user) {
206
-		return array_filter($this->tags,
207
-			function($tag) use($user) {
208
-				return $tag->getOwner() === $user;
209
-			}
210
-		);
211
-	}
212
-
213
-	/**
214
-	 * Get the list of tags for the given ids.
215
-	 *
216
-	 * @param array $objIds array of object ids
217
-	 * @return array|boolean of tags id as key to array of tag names
218
-	 * or false if an error occurred
219
-	 */
220
-	public function getTagsForObjects(array $objIds) {
221
-		$entries = [];
222
-
223
-		try {
224
-			$conn = \OC::$server->getDatabaseConnection();
225
-			$chunks = array_chunk($objIds, 900, false);
226
-			foreach ($chunks as $chunk) {
227
-				$result = $conn->executeQuery(
228
-					'SELECT `category`, `categoryid`, `objid` ' .
229
-					'FROM `' . self::RELATION_TABLE . '` r, `' . self::TAG_TABLE . '` ' .
230
-					'WHERE `categoryid` = `id` AND `uid` = ? AND r.`type` = ? AND `objid` IN (?)',
231
-					[$this->user, $this->type, $chunk],
232
-					[null, null, IQueryBuilder::PARAM_INT_ARRAY]
233
-				);
234
-				while ($row = $result->fetch()) {
235
-					$objId = (int)$row['objid'];
236
-					if (!isset($entries[$objId])) {
237
-						$entries[$objId] = [];
238
-					}
239
-					$entries[$objId][] = $row['category'];
240
-				}
241
-				if ($result === null) {
242
-					\OCP\Util::writeLog('core', __METHOD__. 'DB error: ' . \OC::$server->getDatabaseConnection()->getError(), ILogger::ERROR);
243
-					return false;
244
-				}
245
-			}
246
-		} catch(\Exception $e) {
247
-			\OC::$server->getLogger()->logException($e, [
248
-				'message' => __METHOD__,
249
-				'level' => ILogger::ERROR,
250
-				'app' => 'core',
251
-			]);
252
-			return false;
253
-		}
254
-
255
-		return $entries;
256
-	}
257
-
258
-	/**
259
-	 * Get the a list if items tagged with $tag.
260
-	 *
261
-	 * Throws an exception if the tag could not be found.
262
-	 *
263
-	 * @param string $tag Tag id or name.
264
-	 * @return array|false An array of object ids or false on error.
265
-	 * @throws \Exception
266
-	 */
267
-	public function getIdsForTag($tag) {
268
-		$result = null;
269
-		$tagId = false;
270
-		if(is_numeric($tag)) {
271
-			$tagId = $tag;
272
-		} elseif(is_string($tag)) {
273
-			$tag = trim($tag);
274
-			if($tag === '') {
275
-				\OCP\Util::writeLog('core', __METHOD__.', Cannot use empty tag names', ILogger::DEBUG);
276
-				return false;
277
-			}
278
-			$tagId = $this->getTagId($tag);
279
-		}
280
-
281
-		if($tagId === false) {
282
-			$l10n = \OC::$server->getL10N('core');
283
-			throw new \Exception(
284
-				$l10n->t('Could not find category "%s"', [$tag])
285
-			);
286
-		}
287
-
288
-		$ids = [];
289
-		$sql = 'SELECT `objid` FROM `' . self::RELATION_TABLE
290
-			. '` WHERE `categoryid` = ?';
291
-
292
-		try {
293
-			$stmt = \OC_DB::prepare($sql);
294
-			$result = $stmt->execute([$tagId]);
295
-			if ($result === null) {
296
-				\OCP\Util::writeLog('core', __METHOD__. 'DB error: ' . \OC::$server->getDatabaseConnection()->getError(), ILogger::ERROR);
297
-				return false;
298
-			}
299
-		} catch(\Exception $e) {
300
-			\OC::$server->getLogger()->logException($e, [
301
-				'message' => __METHOD__,
302
-				'level' => ILogger::ERROR,
303
-				'app' => 'core',
304
-			]);
305
-			return false;
306
-		}
307
-
308
-		if(!is_null($result)) {
309
-			while( $row = $result->fetchRow()) {
310
-				$id = (int)$row['objid'];
311
-
312
-				if ($this->includeShared) {
313
-					// We have to check if we are really allowed to access the
314
-					// items that are tagged with $tag. To that end, we ask the
315
-					// corresponding sharing backend if the item identified by $id
316
-					// is owned by any of $this->owners.
317
-					foreach ($this->owners as $owner) {
318
-						if ($this->backend->isValidSource($id, $owner)) {
319
-							$ids[] = $id;
320
-							break;
321
-						}
322
-					}
323
-				} else {
324
-					$ids[] = $id;
325
-				}
326
-			}
327
-		}
328
-
329
-		return $ids;
330
-	}
331
-
332
-	/**
333
-	 * Checks whether a tag is saved for the given user,
334
-	 * disregarding the ones shared with him or her.
335
-	 *
336
-	 * @param string $name The tag name to check for.
337
-	 * @param string $user The user whose tags are to be checked.
338
-	 * @return bool
339
-	 */
340
-	public function userHasTag($name, $user) {
341
-		$key = $this->array_searchi($name, $this->getTagsForUser($user));
342
-		return ($key !== false) ? $this->tags[$key]->getId() : false;
343
-	}
344
-
345
-	/**
346
-	 * Checks whether a tag is saved for or shared with the current user.
347
-	 *
348
-	 * @param string $name The tag name to check for.
349
-	 * @return bool
350
-	 */
351
-	public function hasTag($name) {
352
-		return $this->getTagId($name) !== false;
353
-	}
354
-
355
-	/**
356
-	 * Add a new tag.
357
-	 *
358
-	 * @param string $name A string with a name of the tag
359
-	 * @return false|int the id of the added tag or false on error.
360
-	 */
361
-	public function add($name) {
362
-		$name = trim($name);
363
-
364
-		if($name === '') {
365
-			\OCP\Util::writeLog('core', __METHOD__.', Cannot add an empty tag', ILogger::DEBUG);
366
-			return false;
367
-		}
368
-		if($this->userHasTag($name, $this->user)) {
369
-			\OCP\Util::writeLog('core', __METHOD__.', name: ' . $name. ' exists already', ILogger::DEBUG);
370
-			return false;
371
-		}
372
-		try {
373
-			$tag = new Tag($this->user, $this->type, $name);
374
-			$tag = $this->mapper->insert($tag);
375
-			$this->tags[] = $tag;
376
-		} catch(\Exception $e) {
377
-			\OC::$server->getLogger()->logException($e, [
378
-				'message' => __METHOD__,
379
-				'level' => ILogger::ERROR,
380
-				'app' => 'core',
381
-			]);
382
-			return false;
383
-		}
384
-		\OCP\Util::writeLog('core', __METHOD__.', id: ' . $tag->getId(), ILogger::DEBUG);
385
-		return $tag->getId();
386
-	}
387
-
388
-	/**
389
-	 * Rename tag.
390
-	 *
391
-	 * @param string|integer $from The name or ID of the existing tag
392
-	 * @param string $to The new name of the tag.
393
-	 * @return bool
394
-	 */
395
-	public function rename($from, $to) {
396
-		$from = trim($from);
397
-		$to = trim($to);
398
-
399
-		if($to === '' || $from === '') {
400
-			\OCP\Util::writeLog('core', __METHOD__.', Cannot use empty tag names', ILogger::DEBUG);
401
-			return false;
402
-		}
403
-
404
-		if (is_numeric($from)) {
405
-			$key = $this->getTagById($from);
406
-		} else {
407
-			$key = $this->getTagByName($from);
408
-		}
409
-		if($key === false) {
410
-			\OCP\Util::writeLog('core', __METHOD__.', tag: ' . $from. ' does not exist', ILogger::DEBUG);
411
-			return false;
412
-		}
413
-		$tag = $this->tags[$key];
414
-
415
-		if($this->userHasTag($to, $tag->getOwner())) {
416
-			\OCP\Util::writeLog('core', __METHOD__.', A tag named ' . $to. ' already exists for user ' . $tag->getOwner() . '.', ILogger::DEBUG);
417
-			return false;
418
-		}
419
-
420
-		try {
421
-			$tag->setName($to);
422
-			$this->tags[$key] = $this->mapper->update($tag);
423
-		} catch(\Exception $e) {
424
-			\OC::$server->getLogger()->logException($e, [
425
-				'message' => __METHOD__,
426
-				'level' => ILogger::ERROR,
427
-				'app' => 'core',
428
-			]);
429
-			return false;
430
-		}
431
-		return true;
432
-	}
433
-
434
-	/**
435
-	 * Add a list of new tags.
436
-	 *
437
-	 * @param string[] $names A string with a name or an array of strings containing
438
-	 * the name(s) of the tag(s) to add.
439
-	 * @param bool $sync When true, save the tags
440
-	 * @param int|null $id int Optional object id to add to this|these tag(s)
441
-	 * @return bool Returns false on error.
442
-	 */
443
-	public function addMultiple($names, $sync=false, $id = null) {
444
-		if(!is_array($names)) {
445
-			$names = [$names];
446
-		}
447
-		$names = array_map('trim', $names);
448
-		array_filter($names);
449
-
450
-		$newones = [];
451
-		foreach($names as $name) {
452
-			if(!$this->hasTag($name) && $name !== '') {
453
-				$newones[] = new Tag($this->user, $this->type, $name);
454
-			}
455
-			if(!is_null($id) ) {
456
-				// Insert $objectid, $categoryid  pairs if not exist.
457
-				self::$relations[] = ['objid' => $id, 'tag' => $name];
458
-			}
459
-		}
460
-		$this->tags = array_merge($this->tags, $newones);
461
-		if($sync === true) {
462
-			$this->save();
463
-		}
464
-
465
-		return true;
466
-	}
467
-
468
-	/**
469
-	 * Save the list of tags and their object relations
470
-	 */
471
-	protected function save() {
472
-		if(is_array($this->tags)) {
473
-			foreach($this->tags as $tag) {
474
-				try {
475
-					if (!$this->mapper->tagExists($tag)) {
476
-						$this->mapper->insert($tag);
477
-					}
478
-				} catch(\Exception $e) {
479
-					\OC::$server->getLogger()->logException($e, [
480
-						'message' => __METHOD__,
481
-						'level' => ILogger::ERROR,
482
-						'app' => 'core',
483
-					]);
484
-				}
485
-			}
486
-
487
-			// reload tags to get the proper ids.
488
-			$this->tags = $this->mapper->loadTags($this->owners, $this->type);
489
-			\OCP\Util::writeLog('core', __METHOD__.', tags: ' . print_r($this->tags, true),
490
-				ILogger::DEBUG);
491
-			// Loop through temporarily cached objectid/tagname pairs
492
-			// and save relations.
493
-			$tags = $this->tags;
494
-			// For some reason this is needed or array_search(i) will return 0..?
495
-			ksort($tags);
496
-			$dbConnection = \OC::$server->getDatabaseConnection();
497
-			foreach(self::$relations as $relation) {
498
-				$tagId = $this->getTagId($relation['tag']);
499
-				\OCP\Util::writeLog('core', __METHOD__ . 'catid, ' . $relation['tag'] . ' ' . $tagId, ILogger::DEBUG);
500
-				if($tagId) {
501
-					try {
502
-						$dbConnection->insertIfNotExist(self::RELATION_TABLE,
503
-							[
504
-								'objid' => $relation['objid'],
505
-								'categoryid' => $tagId,
506
-								'type' => $this->type,
507
-								]);
508
-					} catch(\Exception $e) {
509
-						\OC::$server->getLogger()->logException($e, [
510
-							'message' => __METHOD__,
511
-							'level' => ILogger::ERROR,
512
-							'app' => 'core',
513
-						]);
514
-					}
515
-				}
516
-			}
517
-			self::$relations = []; // reset
518
-		} else {
519
-			\OCP\Util::writeLog('core', __METHOD__.', $this->tags is not an array! '
520
-				. print_r($this->tags, true), ILogger::ERROR);
521
-		}
522
-	}
523
-
524
-	/**
525
-	 * Delete tags and tag/object relations for a user.
526
-	 *
527
-	 * For hooking up on post_deleteUser
528
-	 *
529
-	 * @param array $arguments
530
-	 */
531
-	public static function post_deleteUser($arguments) {
532
-		// Find all objectid/tagId pairs.
533
-		$result = null;
534
-		try {
535
-			$stmt = \OC_DB::prepare('SELECT `id` FROM `' . self::TAG_TABLE . '` '
536
-				. 'WHERE `uid` = ?');
537
-			$result = $stmt->execute([$arguments['uid']]);
538
-			if ($result === null) {
539
-				\OCP\Util::writeLog('core', __METHOD__. 'DB error: ' . \OC::$server->getDatabaseConnection()->getError(), ILogger::ERROR);
540
-			}
541
-		} catch(\Exception $e) {
542
-			\OC::$server->getLogger()->logException($e, [
543
-				'message' => __METHOD__,
544
-				'level' => ILogger::ERROR,
545
-				'app' => 'core',
546
-			]);
547
-		}
548
-
549
-		if(!is_null($result)) {
550
-			try {
551
-				$stmt = \OC_DB::prepare('DELETE FROM `' . self::RELATION_TABLE . '` '
552
-					. 'WHERE `categoryid` = ?');
553
-				while( $row = $result->fetchRow()) {
554
-					try {
555
-						$stmt->execute([$row['id']]);
556
-					} catch(\Exception $e) {
557
-						\OC::$server->getLogger()->logException($e, [
558
-							'message' => __METHOD__,
559
-							'level' => ILogger::ERROR,
560
-							'app' => 'core',
561
-						]);
562
-					}
563
-				}
564
-			} catch(\Exception $e) {
565
-				\OC::$server->getLogger()->logException($e, [
566
-					'message' => __METHOD__,
567
-					'level' => ILogger::ERROR,
568
-					'app' => 'core',
569
-				]);
570
-			}
571
-		}
572
-		try {
573
-			$stmt = \OC_DB::prepare('DELETE FROM `' . self::TAG_TABLE . '` '
574
-				. 'WHERE `uid` = ?');
575
-			$result = $stmt->execute([$arguments['uid']]);
576
-			if ($result === null) {
577
-				\OCP\Util::writeLog('core', __METHOD__. ', DB error: ' . \OC::$server->getDatabaseConnection()->getError(), ILogger::ERROR);
578
-			}
579
-		} catch(\Exception $e) {
580
-			\OC::$server->getLogger()->logException($e, [
581
-				'message' => __METHOD__,
582
-				'level' => ILogger::ERROR,
583
-				'app' => 'core',
584
-			]);
585
-		}
586
-	}
587
-
588
-	/**
589
-	 * Delete tag/object relations from the db
590
-	 *
591
-	 * @param array $ids The ids of the objects
592
-	 * @return boolean Returns false on error.
593
-	 */
594
-	public function purgeObjects(array $ids) {
595
-		if(count($ids) === 0) {
596
-			// job done ;)
597
-			return true;
598
-		}
599
-		$updates = $ids;
600
-		try {
601
-			$query = 'DELETE FROM `' . self::RELATION_TABLE . '` ';
602
-			$query .= 'WHERE `objid` IN (' . str_repeat('?,', count($ids)-1) . '?) ';
603
-			$query .= 'AND `type`= ?';
604
-			$updates[] = $this->type;
605
-			$stmt = \OC_DB::prepare($query);
606
-			$result = $stmt->execute($updates);
607
-			if ($result === null) {
608
-				\OCP\Util::writeLog('core', __METHOD__. 'DB error: ' . \OC::$server->getDatabaseConnection()->getError(), ILogger::ERROR);
609
-				return false;
610
-			}
611
-		} catch(\Exception $e) {
612
-			\OC::$server->getLogger()->logException($e, [
613
-				'message' => __METHOD__,
614
-				'level' => ILogger::ERROR,
615
-				'app' => 'core',
616
-			]);
617
-			return false;
618
-		}
619
-		return true;
620
-	}
621
-
622
-	/**
623
-	 * Get favorites for an object type
624
-	 *
625
-	 * @return array|false An array of object ids.
626
-	 */
627
-	public function getFavorites() {
628
-		if(!$this->userHasTag(ITags::TAG_FAVORITE, $this->user)) {
629
-			return [];
630
-		}
631
-
632
-		try {
633
-			return $this->getIdsForTag(ITags::TAG_FAVORITE);
634
-		} catch(\Exception $e) {
635
-			\OC::$server->getLogger()->logException($e, [
636
-				'message' => __METHOD__,
637
-				'level' => ILogger::ERROR,
638
-				'app' => 'core',
639
-			]);
640
-			return [];
641
-		}
642
-	}
643
-
644
-	/**
645
-	 * Add an object to favorites
646
-	 *
647
-	 * @param int $objid The id of the object
648
-	 * @return boolean
649
-	 */
650
-	public function addToFavorites($objid) {
651
-		if(!$this->userHasTag(ITags::TAG_FAVORITE, $this->user)) {
652
-			$this->add(ITags::TAG_FAVORITE);
653
-		}
654
-		return $this->tagAs($objid, ITags::TAG_FAVORITE);
655
-	}
656
-
657
-	/**
658
-	 * Remove an object from favorites
659
-	 *
660
-	 * @param int $objid The id of the object
661
-	 * @return boolean
662
-	 */
663
-	public function removeFromFavorites($objid) {
664
-		return $this->unTag($objid, ITags::TAG_FAVORITE);
665
-	}
666
-
667
-	/**
668
-	 * Creates a tag/object relation.
669
-	 *
670
-	 * @param int $objid The id of the object
671
-	 * @param string $tag The id or name of the tag
672
-	 * @return boolean Returns false on error.
673
-	 */
674
-	public function tagAs($objid, $tag) {
675
-		if(is_string($tag) && !is_numeric($tag)) {
676
-			$tag = trim($tag);
677
-			if($tag === '') {
678
-				\OCP\Util::writeLog('core', __METHOD__.', Cannot add an empty tag', ILogger::DEBUG);
679
-				return false;
680
-			}
681
-			if(!$this->hasTag($tag)) {
682
-				$this->add($tag);
683
-			}
684
-			$tagId =  $this->getTagId($tag);
685
-		} else {
686
-			$tagId = $tag;
687
-		}
688
-		try {
689
-			\OC::$server->getDatabaseConnection()->insertIfNotExist(self::RELATION_TABLE,
690
-				[
691
-					'objid' => $objid,
692
-					'categoryid' => $tagId,
693
-					'type' => $this->type,
694
-				]);
695
-		} catch(\Exception $e) {
696
-			\OC::$server->getLogger()->logException($e, [
697
-				'message' => __METHOD__,
698
-				'level' => ILogger::ERROR,
699
-				'app' => 'core',
700
-			]);
701
-			return false;
702
-		}
703
-		return true;
704
-	}
705
-
706
-	/**
707
-	 * Delete single tag/object relation from the db
708
-	 *
709
-	 * @param int $objid The id of the object
710
-	 * @param string $tag The id or name of the tag
711
-	 * @return boolean
712
-	 */
713
-	public function unTag($objid, $tag) {
714
-		if(is_string($tag) && !is_numeric($tag)) {
715
-			$tag = trim($tag);
716
-			if($tag === '') {
717
-				\OCP\Util::writeLog('core', __METHOD__.', Tag name is empty', ILogger::DEBUG);
718
-				return false;
719
-			}
720
-			$tagId =  $this->getTagId($tag);
721
-		} else {
722
-			$tagId = $tag;
723
-		}
724
-
725
-		try {
726
-			$sql = 'DELETE FROM `' . self::RELATION_TABLE . '` '
727
-					. 'WHERE `objid` = ? AND `categoryid` = ? AND `type` = ?';
728
-			$stmt = \OC_DB::prepare($sql);
729
-			$stmt->execute([$objid, $tagId, $this->type]);
730
-		} catch(\Exception $e) {
731
-			\OC::$server->getLogger()->logException($e, [
732
-				'message' => __METHOD__,
733
-				'level' => ILogger::ERROR,
734
-				'app' => 'core',
735
-			]);
736
-			return false;
737
-		}
738
-		return true;
739
-	}
740
-
741
-	/**
742
-	 * Delete tags from the database.
743
-	 *
744
-	 * @param string[]|integer[] $names An array of tags (names or IDs) to delete
745
-	 * @return bool Returns false on error
746
-	 */
747
-	public function delete($names) {
748
-		if(!is_array($names)) {
749
-			$names = [$names];
750
-		}
751
-
752
-		$names = array_map('trim', $names);
753
-		array_filter($names);
754
-
755
-		\OCP\Util::writeLog('core', __METHOD__ . ', before: '
756
-			. print_r($this->tags, true), ILogger::DEBUG);
757
-		foreach($names as $name) {
758
-			$id = null;
759
-
760
-			if (is_numeric($name)) {
761
-				$key = $this->getTagById($name);
762
-			} else {
763
-				$key = $this->getTagByName($name);
764
-			}
765
-			if ($key !== false) {
766
-				$tag = $this->tags[$key];
767
-				$id = $tag->getId();
768
-				unset($this->tags[$key]);
769
-				$this->mapper->delete($tag);
770
-			} else {
771
-				\OCP\Util::writeLog('core', __METHOD__ . 'Cannot delete tag ' . $name
772
-					. ': not found.', ILogger::ERROR);
773
-			}
774
-			if(!is_null($id) && $id !== false) {
775
-				try {
776
-					$sql = 'DELETE FROM `' . self::RELATION_TABLE . '` '
777
-							. 'WHERE `categoryid` = ?';
778
-					$stmt = \OC_DB::prepare($sql);
779
-					$result = $stmt->execute([$id]);
780
-					if ($result === null) {
781
-						\OCP\Util::writeLog('core',
782
-							__METHOD__. 'DB error: ' . \OC::$server->getDatabaseConnection()->getError(),
783
-							ILogger::ERROR);
784
-						return false;
785
-					}
786
-				} catch(\Exception $e) {
787
-					\OC::$server->getLogger()->logException($e, [
788
-						'message' => __METHOD__,
789
-						'level' => ILogger::ERROR,
790
-						'app' => 'core',
791
-					]);
792
-					return false;
793
-				}
794
-			}
795
-		}
796
-		return true;
797
-	}
798
-
799
-	// case-insensitive array_search
800
-	protected function array_searchi($needle, $haystack, $mem='getName') {
801
-		if(!is_array($haystack)) {
802
-			return false;
803
-		}
804
-		return array_search(strtolower($needle), array_map(
805
-			function($tag) use($mem) {
806
-				return strtolower(call_user_func([$tag, $mem]));
807
-			}, $haystack)
808
-		);
809
-	}
810
-
811
-	/**
812
-	 * Get a tag's ID.
813
-	 *
814
-	 * @param string $name The tag name to look for.
815
-	 * @return string|bool The tag's id or false if no matching tag is found.
816
-	 */
817
-	private function getTagId($name) {
818
-		$key = $this->array_searchi($name, $this->tags);
819
-		if ($key !== false) {
820
-			return $this->tags[$key]->getId();
821
-		}
822
-		return false;
823
-	}
824
-
825
-	/**
826
-	 * Get a tag by its name.
827
-	 *
828
-	 * @param string $name The tag name.
829
-	 * @return integer|bool The tag object's offset within the $this->tags
830
-	 *                      array or false if it doesn't exist.
831
-	 */
832
-	private function getTagByName($name) {
833
-		return $this->array_searchi($name, $this->tags, 'getName');
834
-	}
835
-
836
-	/**
837
-	 * Get a tag by its ID.
838
-	 *
839
-	 * @param string $id The tag ID to look for.
840
-	 * @return integer|bool The tag object's offset within the $this->tags
841
-	 *                      array or false if it doesn't exist.
842
-	 */
843
-	private function getTagById($id) {
844
-		return $this->array_searchi($id, $this->tags, 'getId');
845
-	}
846
-
847
-	/**
848
-	 * Returns an array mapping a given tag's properties to its values:
849
-	 * ['id' => 0, 'name' = 'Tag', 'owner' = 'User', 'type' => 'tagtype']
850
-	 *
851
-	 * @param Tag $tag The tag that is going to be mapped
852
-	 * @return array
853
-	 */
854
-	private function tagMap(Tag $tag) {
855
-		return [
856
-			'id'    => $tag->getId(),
857
-			'name'  => $tag->getName(),
858
-			'owner' => $tag->getOwner(),
859
-			'type'  => $tag->getType()
860
-		];
861
-	}
57
+    /**
58
+     * Tags
59
+     *
60
+     * @var array
61
+     */
62
+    private $tags = [];
63
+
64
+    /**
65
+     * Used for storing objectid/categoryname pairs while rescanning.
66
+     *
67
+     * @var array
68
+     */
69
+    private static $relations = [];
70
+
71
+    /**
72
+     * Type
73
+     *
74
+     * @var string
75
+     */
76
+    private $type;
77
+
78
+    /**
79
+     * User
80
+     *
81
+     * @var string
82
+     */
83
+    private $user;
84
+
85
+    /**
86
+     * Are we including tags for shared items?
87
+     *
88
+     * @var bool
89
+     */
90
+    private $includeShared = false;
91
+
92
+    /**
93
+     * The current user, plus any owners of the items shared with the current
94
+     * user, if $this->includeShared === true.
95
+     *
96
+     * @var array
97
+     */
98
+    private $owners = [];
99
+
100
+    /**
101
+     * The Mapper we're using to communicate our Tag objects to the database.
102
+     *
103
+     * @var TagMapper
104
+     */
105
+    private $mapper;
106
+
107
+    /**
108
+     * The sharing backend for objects of $this->type. Required if
109
+     * $this->includeShared === true to determine ownership of items.
110
+     *
111
+     * @var \OCP\Share_Backend
112
+     */
113
+    private $backend;
114
+
115
+    const TAG_TABLE = '*PREFIX*vcategory';
116
+    const RELATION_TABLE = '*PREFIX*vcategory_to_object';
117
+
118
+    /**
119
+     * Constructor.
120
+     *
121
+     * @param TagMapper $mapper Instance of the TagMapper abstraction layer.
122
+     * @param string $user The user whose data the object will operate on.
123
+     * @param string $type The type of items for which tags will be loaded.
124
+     * @param array $defaultTags Tags that should be created at construction.
125
+     * @param boolean $includeShared Whether to include tags for items shared with this user by others.
126
+     */
127
+    public function __construct(TagMapper $mapper, $user, $type, $defaultTags = [], $includeShared = false) {
128
+        $this->mapper = $mapper;
129
+        $this->user = $user;
130
+        $this->type = $type;
131
+        $this->includeShared = $includeShared;
132
+        $this->owners = [$this->user];
133
+        if ($this->includeShared) {
134
+            $this->owners = array_merge($this->owners, \OC\Share\Share::getSharedItemsOwners($this->user, $this->type, true));
135
+            $this->backend = \OC\Share\Share::getBackend($this->type);
136
+        }
137
+        $this->tags = $this->mapper->loadTags($this->owners, $this->type);
138
+
139
+        if(count($defaultTags) > 0 && count($this->tags) === 0) {
140
+            $this->addMultiple($defaultTags, true);
141
+        }
142
+    }
143
+
144
+    /**
145
+     * Check if any tags are saved for this type and user.
146
+     *
147
+     * @return boolean
148
+     */
149
+    public function isEmpty() {
150
+        return count($this->tags) === 0;
151
+    }
152
+
153
+    /**
154
+     * Returns an array mapping a given tag's properties to its values:
155
+     * ['id' => 0, 'name' = 'Tag', 'owner' = 'User', 'type' => 'tagtype']
156
+     *
157
+     * @param string $id The ID of the tag that is going to be mapped
158
+     * @return array|false
159
+     */
160
+    public function getTag($id) {
161
+        $key = $this->getTagById($id);
162
+        if ($key !== false) {
163
+            return $this->tagMap($this->tags[$key]);
164
+        }
165
+        return false;
166
+    }
167
+
168
+    /**
169
+     * Get the tags for a specific user.
170
+     *
171
+     * This returns an array with maps containing each tag's properties:
172
+     * [
173
+     * 	['id' => 0, 'name' = 'First tag', 'owner' = 'User', 'type' => 'tagtype'],
174
+     * 	['id' => 1, 'name' = 'Shared tag', 'owner' = 'Other user', 'type' => 'tagtype'],
175
+     * ]
176
+     *
177
+     * @return array
178
+     */
179
+    public function getTags() {
180
+        if(!count($this->tags)) {
181
+            return [];
182
+        }
183
+
184
+        usort($this->tags, function($a, $b) {
185
+            return strnatcasecmp($a->getName(), $b->getName());
186
+        });
187
+        $tagMap = [];
188
+
189
+        foreach($this->tags as $tag) {
190
+            if($tag->getName() !== ITags::TAG_FAVORITE) {
191
+                $tagMap[] = $this->tagMap($tag);
192
+            }
193
+        }
194
+        return $tagMap;
195
+
196
+    }
197
+
198
+    /**
199
+     * Return only the tags owned by the given user, omitting any tags shared
200
+     * by other users.
201
+     *
202
+     * @param string $user The user whose tags are to be checked.
203
+     * @return array An array of Tag objects.
204
+     */
205
+    public function getTagsForUser($user) {
206
+        return array_filter($this->tags,
207
+            function($tag) use($user) {
208
+                return $tag->getOwner() === $user;
209
+            }
210
+        );
211
+    }
212
+
213
+    /**
214
+     * Get the list of tags for the given ids.
215
+     *
216
+     * @param array $objIds array of object ids
217
+     * @return array|boolean of tags id as key to array of tag names
218
+     * or false if an error occurred
219
+     */
220
+    public function getTagsForObjects(array $objIds) {
221
+        $entries = [];
222
+
223
+        try {
224
+            $conn = \OC::$server->getDatabaseConnection();
225
+            $chunks = array_chunk($objIds, 900, false);
226
+            foreach ($chunks as $chunk) {
227
+                $result = $conn->executeQuery(
228
+                    'SELECT `category`, `categoryid`, `objid` ' .
229
+                    'FROM `' . self::RELATION_TABLE . '` r, `' . self::TAG_TABLE . '` ' .
230
+                    'WHERE `categoryid` = `id` AND `uid` = ? AND r.`type` = ? AND `objid` IN (?)',
231
+                    [$this->user, $this->type, $chunk],
232
+                    [null, null, IQueryBuilder::PARAM_INT_ARRAY]
233
+                );
234
+                while ($row = $result->fetch()) {
235
+                    $objId = (int)$row['objid'];
236
+                    if (!isset($entries[$objId])) {
237
+                        $entries[$objId] = [];
238
+                    }
239
+                    $entries[$objId][] = $row['category'];
240
+                }
241
+                if ($result === null) {
242
+                    \OCP\Util::writeLog('core', __METHOD__. 'DB error: ' . \OC::$server->getDatabaseConnection()->getError(), ILogger::ERROR);
243
+                    return false;
244
+                }
245
+            }
246
+        } catch(\Exception $e) {
247
+            \OC::$server->getLogger()->logException($e, [
248
+                'message' => __METHOD__,
249
+                'level' => ILogger::ERROR,
250
+                'app' => 'core',
251
+            ]);
252
+            return false;
253
+        }
254
+
255
+        return $entries;
256
+    }
257
+
258
+    /**
259
+     * Get the a list if items tagged with $tag.
260
+     *
261
+     * Throws an exception if the tag could not be found.
262
+     *
263
+     * @param string $tag Tag id or name.
264
+     * @return array|false An array of object ids or false on error.
265
+     * @throws \Exception
266
+     */
267
+    public function getIdsForTag($tag) {
268
+        $result = null;
269
+        $tagId = false;
270
+        if(is_numeric($tag)) {
271
+            $tagId = $tag;
272
+        } elseif(is_string($tag)) {
273
+            $tag = trim($tag);
274
+            if($tag === '') {
275
+                \OCP\Util::writeLog('core', __METHOD__.', Cannot use empty tag names', ILogger::DEBUG);
276
+                return false;
277
+            }
278
+            $tagId = $this->getTagId($tag);
279
+        }
280
+
281
+        if($tagId === false) {
282
+            $l10n = \OC::$server->getL10N('core');
283
+            throw new \Exception(
284
+                $l10n->t('Could not find category "%s"', [$tag])
285
+            );
286
+        }
287
+
288
+        $ids = [];
289
+        $sql = 'SELECT `objid` FROM `' . self::RELATION_TABLE
290
+            . '` WHERE `categoryid` = ?';
291
+
292
+        try {
293
+            $stmt = \OC_DB::prepare($sql);
294
+            $result = $stmt->execute([$tagId]);
295
+            if ($result === null) {
296
+                \OCP\Util::writeLog('core', __METHOD__. 'DB error: ' . \OC::$server->getDatabaseConnection()->getError(), ILogger::ERROR);
297
+                return false;
298
+            }
299
+        } catch(\Exception $e) {
300
+            \OC::$server->getLogger()->logException($e, [
301
+                'message' => __METHOD__,
302
+                'level' => ILogger::ERROR,
303
+                'app' => 'core',
304
+            ]);
305
+            return false;
306
+        }
307
+
308
+        if(!is_null($result)) {
309
+            while( $row = $result->fetchRow()) {
310
+                $id = (int)$row['objid'];
311
+
312
+                if ($this->includeShared) {
313
+                    // We have to check if we are really allowed to access the
314
+                    // items that are tagged with $tag. To that end, we ask the
315
+                    // corresponding sharing backend if the item identified by $id
316
+                    // is owned by any of $this->owners.
317
+                    foreach ($this->owners as $owner) {
318
+                        if ($this->backend->isValidSource($id, $owner)) {
319
+                            $ids[] = $id;
320
+                            break;
321
+                        }
322
+                    }
323
+                } else {
324
+                    $ids[] = $id;
325
+                }
326
+            }
327
+        }
328
+
329
+        return $ids;
330
+    }
331
+
332
+    /**
333
+     * Checks whether a tag is saved for the given user,
334
+     * disregarding the ones shared with him or her.
335
+     *
336
+     * @param string $name The tag name to check for.
337
+     * @param string $user The user whose tags are to be checked.
338
+     * @return bool
339
+     */
340
+    public function userHasTag($name, $user) {
341
+        $key = $this->array_searchi($name, $this->getTagsForUser($user));
342
+        return ($key !== false) ? $this->tags[$key]->getId() : false;
343
+    }
344
+
345
+    /**
346
+     * Checks whether a tag is saved for or shared with the current user.
347
+     *
348
+     * @param string $name The tag name to check for.
349
+     * @return bool
350
+     */
351
+    public function hasTag($name) {
352
+        return $this->getTagId($name) !== false;
353
+    }
354
+
355
+    /**
356
+     * Add a new tag.
357
+     *
358
+     * @param string $name A string with a name of the tag
359
+     * @return false|int the id of the added tag or false on error.
360
+     */
361
+    public function add($name) {
362
+        $name = trim($name);
363
+
364
+        if($name === '') {
365
+            \OCP\Util::writeLog('core', __METHOD__.', Cannot add an empty tag', ILogger::DEBUG);
366
+            return false;
367
+        }
368
+        if($this->userHasTag($name, $this->user)) {
369
+            \OCP\Util::writeLog('core', __METHOD__.', name: ' . $name. ' exists already', ILogger::DEBUG);
370
+            return false;
371
+        }
372
+        try {
373
+            $tag = new Tag($this->user, $this->type, $name);
374
+            $tag = $this->mapper->insert($tag);
375
+            $this->tags[] = $tag;
376
+        } catch(\Exception $e) {
377
+            \OC::$server->getLogger()->logException($e, [
378
+                'message' => __METHOD__,
379
+                'level' => ILogger::ERROR,
380
+                'app' => 'core',
381
+            ]);
382
+            return false;
383
+        }
384
+        \OCP\Util::writeLog('core', __METHOD__.', id: ' . $tag->getId(), ILogger::DEBUG);
385
+        return $tag->getId();
386
+    }
387
+
388
+    /**
389
+     * Rename tag.
390
+     *
391
+     * @param string|integer $from The name or ID of the existing tag
392
+     * @param string $to The new name of the tag.
393
+     * @return bool
394
+     */
395
+    public function rename($from, $to) {
396
+        $from = trim($from);
397
+        $to = trim($to);
398
+
399
+        if($to === '' || $from === '') {
400
+            \OCP\Util::writeLog('core', __METHOD__.', Cannot use empty tag names', ILogger::DEBUG);
401
+            return false;
402
+        }
403
+
404
+        if (is_numeric($from)) {
405
+            $key = $this->getTagById($from);
406
+        } else {
407
+            $key = $this->getTagByName($from);
408
+        }
409
+        if($key === false) {
410
+            \OCP\Util::writeLog('core', __METHOD__.', tag: ' . $from. ' does not exist', ILogger::DEBUG);
411
+            return false;
412
+        }
413
+        $tag = $this->tags[$key];
414
+
415
+        if($this->userHasTag($to, $tag->getOwner())) {
416
+            \OCP\Util::writeLog('core', __METHOD__.', A tag named ' . $to. ' already exists for user ' . $tag->getOwner() . '.', ILogger::DEBUG);
417
+            return false;
418
+        }
419
+
420
+        try {
421
+            $tag->setName($to);
422
+            $this->tags[$key] = $this->mapper->update($tag);
423
+        } catch(\Exception $e) {
424
+            \OC::$server->getLogger()->logException($e, [
425
+                'message' => __METHOD__,
426
+                'level' => ILogger::ERROR,
427
+                'app' => 'core',
428
+            ]);
429
+            return false;
430
+        }
431
+        return true;
432
+    }
433
+
434
+    /**
435
+     * Add a list of new tags.
436
+     *
437
+     * @param string[] $names A string with a name or an array of strings containing
438
+     * the name(s) of the tag(s) to add.
439
+     * @param bool $sync When true, save the tags
440
+     * @param int|null $id int Optional object id to add to this|these tag(s)
441
+     * @return bool Returns false on error.
442
+     */
443
+    public function addMultiple($names, $sync=false, $id = null) {
444
+        if(!is_array($names)) {
445
+            $names = [$names];
446
+        }
447
+        $names = array_map('trim', $names);
448
+        array_filter($names);
449
+
450
+        $newones = [];
451
+        foreach($names as $name) {
452
+            if(!$this->hasTag($name) && $name !== '') {
453
+                $newones[] = new Tag($this->user, $this->type, $name);
454
+            }
455
+            if(!is_null($id) ) {
456
+                // Insert $objectid, $categoryid  pairs if not exist.
457
+                self::$relations[] = ['objid' => $id, 'tag' => $name];
458
+            }
459
+        }
460
+        $this->tags = array_merge($this->tags, $newones);
461
+        if($sync === true) {
462
+            $this->save();
463
+        }
464
+
465
+        return true;
466
+    }
467
+
468
+    /**
469
+     * Save the list of tags and their object relations
470
+     */
471
+    protected function save() {
472
+        if(is_array($this->tags)) {
473
+            foreach($this->tags as $tag) {
474
+                try {
475
+                    if (!$this->mapper->tagExists($tag)) {
476
+                        $this->mapper->insert($tag);
477
+                    }
478
+                } catch(\Exception $e) {
479
+                    \OC::$server->getLogger()->logException($e, [
480
+                        'message' => __METHOD__,
481
+                        'level' => ILogger::ERROR,
482
+                        'app' => 'core',
483
+                    ]);
484
+                }
485
+            }
486
+
487
+            // reload tags to get the proper ids.
488
+            $this->tags = $this->mapper->loadTags($this->owners, $this->type);
489
+            \OCP\Util::writeLog('core', __METHOD__.', tags: ' . print_r($this->tags, true),
490
+                ILogger::DEBUG);
491
+            // Loop through temporarily cached objectid/tagname pairs
492
+            // and save relations.
493
+            $tags = $this->tags;
494
+            // For some reason this is needed or array_search(i) will return 0..?
495
+            ksort($tags);
496
+            $dbConnection = \OC::$server->getDatabaseConnection();
497
+            foreach(self::$relations as $relation) {
498
+                $tagId = $this->getTagId($relation['tag']);
499
+                \OCP\Util::writeLog('core', __METHOD__ . 'catid, ' . $relation['tag'] . ' ' . $tagId, ILogger::DEBUG);
500
+                if($tagId) {
501
+                    try {
502
+                        $dbConnection->insertIfNotExist(self::RELATION_TABLE,
503
+                            [
504
+                                'objid' => $relation['objid'],
505
+                                'categoryid' => $tagId,
506
+                                'type' => $this->type,
507
+                                ]);
508
+                    } catch(\Exception $e) {
509
+                        \OC::$server->getLogger()->logException($e, [
510
+                            'message' => __METHOD__,
511
+                            'level' => ILogger::ERROR,
512
+                            'app' => 'core',
513
+                        ]);
514
+                    }
515
+                }
516
+            }
517
+            self::$relations = []; // reset
518
+        } else {
519
+            \OCP\Util::writeLog('core', __METHOD__.', $this->tags is not an array! '
520
+                . print_r($this->tags, true), ILogger::ERROR);
521
+        }
522
+    }
523
+
524
+    /**
525
+     * Delete tags and tag/object relations for a user.
526
+     *
527
+     * For hooking up on post_deleteUser
528
+     *
529
+     * @param array $arguments
530
+     */
531
+    public static function post_deleteUser($arguments) {
532
+        // Find all objectid/tagId pairs.
533
+        $result = null;
534
+        try {
535
+            $stmt = \OC_DB::prepare('SELECT `id` FROM `' . self::TAG_TABLE . '` '
536
+                . 'WHERE `uid` = ?');
537
+            $result = $stmt->execute([$arguments['uid']]);
538
+            if ($result === null) {
539
+                \OCP\Util::writeLog('core', __METHOD__. 'DB error: ' . \OC::$server->getDatabaseConnection()->getError(), ILogger::ERROR);
540
+            }
541
+        } catch(\Exception $e) {
542
+            \OC::$server->getLogger()->logException($e, [
543
+                'message' => __METHOD__,
544
+                'level' => ILogger::ERROR,
545
+                'app' => 'core',
546
+            ]);
547
+        }
548
+
549
+        if(!is_null($result)) {
550
+            try {
551
+                $stmt = \OC_DB::prepare('DELETE FROM `' . self::RELATION_TABLE . '` '
552
+                    . 'WHERE `categoryid` = ?');
553
+                while( $row = $result->fetchRow()) {
554
+                    try {
555
+                        $stmt->execute([$row['id']]);
556
+                    } catch(\Exception $e) {
557
+                        \OC::$server->getLogger()->logException($e, [
558
+                            'message' => __METHOD__,
559
+                            'level' => ILogger::ERROR,
560
+                            'app' => 'core',
561
+                        ]);
562
+                    }
563
+                }
564
+            } catch(\Exception $e) {
565
+                \OC::$server->getLogger()->logException($e, [
566
+                    'message' => __METHOD__,
567
+                    'level' => ILogger::ERROR,
568
+                    'app' => 'core',
569
+                ]);
570
+            }
571
+        }
572
+        try {
573
+            $stmt = \OC_DB::prepare('DELETE FROM `' . self::TAG_TABLE . '` '
574
+                . 'WHERE `uid` = ?');
575
+            $result = $stmt->execute([$arguments['uid']]);
576
+            if ($result === null) {
577
+                \OCP\Util::writeLog('core', __METHOD__. ', DB error: ' . \OC::$server->getDatabaseConnection()->getError(), ILogger::ERROR);
578
+            }
579
+        } catch(\Exception $e) {
580
+            \OC::$server->getLogger()->logException($e, [
581
+                'message' => __METHOD__,
582
+                'level' => ILogger::ERROR,
583
+                'app' => 'core',
584
+            ]);
585
+        }
586
+    }
587
+
588
+    /**
589
+     * Delete tag/object relations from the db
590
+     *
591
+     * @param array $ids The ids of the objects
592
+     * @return boolean Returns false on error.
593
+     */
594
+    public function purgeObjects(array $ids) {
595
+        if(count($ids) === 0) {
596
+            // job done ;)
597
+            return true;
598
+        }
599
+        $updates = $ids;
600
+        try {
601
+            $query = 'DELETE FROM `' . self::RELATION_TABLE . '` ';
602
+            $query .= 'WHERE `objid` IN (' . str_repeat('?,', count($ids)-1) . '?) ';
603
+            $query .= 'AND `type`= ?';
604
+            $updates[] = $this->type;
605
+            $stmt = \OC_DB::prepare($query);
606
+            $result = $stmt->execute($updates);
607
+            if ($result === null) {
608
+                \OCP\Util::writeLog('core', __METHOD__. 'DB error: ' . \OC::$server->getDatabaseConnection()->getError(), ILogger::ERROR);
609
+                return false;
610
+            }
611
+        } catch(\Exception $e) {
612
+            \OC::$server->getLogger()->logException($e, [
613
+                'message' => __METHOD__,
614
+                'level' => ILogger::ERROR,
615
+                'app' => 'core',
616
+            ]);
617
+            return false;
618
+        }
619
+        return true;
620
+    }
621
+
622
+    /**
623
+     * Get favorites for an object type
624
+     *
625
+     * @return array|false An array of object ids.
626
+     */
627
+    public function getFavorites() {
628
+        if(!$this->userHasTag(ITags::TAG_FAVORITE, $this->user)) {
629
+            return [];
630
+        }
631
+
632
+        try {
633
+            return $this->getIdsForTag(ITags::TAG_FAVORITE);
634
+        } catch(\Exception $e) {
635
+            \OC::$server->getLogger()->logException($e, [
636
+                'message' => __METHOD__,
637
+                'level' => ILogger::ERROR,
638
+                'app' => 'core',
639
+            ]);
640
+            return [];
641
+        }
642
+    }
643
+
644
+    /**
645
+     * Add an object to favorites
646
+     *
647
+     * @param int $objid The id of the object
648
+     * @return boolean
649
+     */
650
+    public function addToFavorites($objid) {
651
+        if(!$this->userHasTag(ITags::TAG_FAVORITE, $this->user)) {
652
+            $this->add(ITags::TAG_FAVORITE);
653
+        }
654
+        return $this->tagAs($objid, ITags::TAG_FAVORITE);
655
+    }
656
+
657
+    /**
658
+     * Remove an object from favorites
659
+     *
660
+     * @param int $objid The id of the object
661
+     * @return boolean
662
+     */
663
+    public function removeFromFavorites($objid) {
664
+        return $this->unTag($objid, ITags::TAG_FAVORITE);
665
+    }
666
+
667
+    /**
668
+     * Creates a tag/object relation.
669
+     *
670
+     * @param int $objid The id of the object
671
+     * @param string $tag The id or name of the tag
672
+     * @return boolean Returns false on error.
673
+     */
674
+    public function tagAs($objid, $tag) {
675
+        if(is_string($tag) && !is_numeric($tag)) {
676
+            $tag = trim($tag);
677
+            if($tag === '') {
678
+                \OCP\Util::writeLog('core', __METHOD__.', Cannot add an empty tag', ILogger::DEBUG);
679
+                return false;
680
+            }
681
+            if(!$this->hasTag($tag)) {
682
+                $this->add($tag);
683
+            }
684
+            $tagId =  $this->getTagId($tag);
685
+        } else {
686
+            $tagId = $tag;
687
+        }
688
+        try {
689
+            \OC::$server->getDatabaseConnection()->insertIfNotExist(self::RELATION_TABLE,
690
+                [
691
+                    'objid' => $objid,
692
+                    'categoryid' => $tagId,
693
+                    'type' => $this->type,
694
+                ]);
695
+        } catch(\Exception $e) {
696
+            \OC::$server->getLogger()->logException($e, [
697
+                'message' => __METHOD__,
698
+                'level' => ILogger::ERROR,
699
+                'app' => 'core',
700
+            ]);
701
+            return false;
702
+        }
703
+        return true;
704
+    }
705
+
706
+    /**
707
+     * Delete single tag/object relation from the db
708
+     *
709
+     * @param int $objid The id of the object
710
+     * @param string $tag The id or name of the tag
711
+     * @return boolean
712
+     */
713
+    public function unTag($objid, $tag) {
714
+        if(is_string($tag) && !is_numeric($tag)) {
715
+            $tag = trim($tag);
716
+            if($tag === '') {
717
+                \OCP\Util::writeLog('core', __METHOD__.', Tag name is empty', ILogger::DEBUG);
718
+                return false;
719
+            }
720
+            $tagId =  $this->getTagId($tag);
721
+        } else {
722
+            $tagId = $tag;
723
+        }
724
+
725
+        try {
726
+            $sql = 'DELETE FROM `' . self::RELATION_TABLE . '` '
727
+                    . 'WHERE `objid` = ? AND `categoryid` = ? AND `type` = ?';
728
+            $stmt = \OC_DB::prepare($sql);
729
+            $stmt->execute([$objid, $tagId, $this->type]);
730
+        } catch(\Exception $e) {
731
+            \OC::$server->getLogger()->logException($e, [
732
+                'message' => __METHOD__,
733
+                'level' => ILogger::ERROR,
734
+                'app' => 'core',
735
+            ]);
736
+            return false;
737
+        }
738
+        return true;
739
+    }
740
+
741
+    /**
742
+     * Delete tags from the database.
743
+     *
744
+     * @param string[]|integer[] $names An array of tags (names or IDs) to delete
745
+     * @return bool Returns false on error
746
+     */
747
+    public function delete($names) {
748
+        if(!is_array($names)) {
749
+            $names = [$names];
750
+        }
751
+
752
+        $names = array_map('trim', $names);
753
+        array_filter($names);
754
+
755
+        \OCP\Util::writeLog('core', __METHOD__ . ', before: '
756
+            . print_r($this->tags, true), ILogger::DEBUG);
757
+        foreach($names as $name) {
758
+            $id = null;
759
+
760
+            if (is_numeric($name)) {
761
+                $key = $this->getTagById($name);
762
+            } else {
763
+                $key = $this->getTagByName($name);
764
+            }
765
+            if ($key !== false) {
766
+                $tag = $this->tags[$key];
767
+                $id = $tag->getId();
768
+                unset($this->tags[$key]);
769
+                $this->mapper->delete($tag);
770
+            } else {
771
+                \OCP\Util::writeLog('core', __METHOD__ . 'Cannot delete tag ' . $name
772
+                    . ': not found.', ILogger::ERROR);
773
+            }
774
+            if(!is_null($id) && $id !== false) {
775
+                try {
776
+                    $sql = 'DELETE FROM `' . self::RELATION_TABLE . '` '
777
+                            . 'WHERE `categoryid` = ?';
778
+                    $stmt = \OC_DB::prepare($sql);
779
+                    $result = $stmt->execute([$id]);
780
+                    if ($result === null) {
781
+                        \OCP\Util::writeLog('core',
782
+                            __METHOD__. 'DB error: ' . \OC::$server->getDatabaseConnection()->getError(),
783
+                            ILogger::ERROR);
784
+                        return false;
785
+                    }
786
+                } catch(\Exception $e) {
787
+                    \OC::$server->getLogger()->logException($e, [
788
+                        'message' => __METHOD__,
789
+                        'level' => ILogger::ERROR,
790
+                        'app' => 'core',
791
+                    ]);
792
+                    return false;
793
+                }
794
+            }
795
+        }
796
+        return true;
797
+    }
798
+
799
+    // case-insensitive array_search
800
+    protected function array_searchi($needle, $haystack, $mem='getName') {
801
+        if(!is_array($haystack)) {
802
+            return false;
803
+        }
804
+        return array_search(strtolower($needle), array_map(
805
+            function($tag) use($mem) {
806
+                return strtolower(call_user_func([$tag, $mem]));
807
+            }, $haystack)
808
+        );
809
+    }
810
+
811
+    /**
812
+     * Get a tag's ID.
813
+     *
814
+     * @param string $name The tag name to look for.
815
+     * @return string|bool The tag's id or false if no matching tag is found.
816
+     */
817
+    private function getTagId($name) {
818
+        $key = $this->array_searchi($name, $this->tags);
819
+        if ($key !== false) {
820
+            return $this->tags[$key]->getId();
821
+        }
822
+        return false;
823
+    }
824
+
825
+    /**
826
+     * Get a tag by its name.
827
+     *
828
+     * @param string $name The tag name.
829
+     * @return integer|bool The tag object's offset within the $this->tags
830
+     *                      array or false if it doesn't exist.
831
+     */
832
+    private function getTagByName($name) {
833
+        return $this->array_searchi($name, $this->tags, 'getName');
834
+    }
835
+
836
+    /**
837
+     * Get a tag by its ID.
838
+     *
839
+     * @param string $id The tag ID to look for.
840
+     * @return integer|bool The tag object's offset within the $this->tags
841
+     *                      array or false if it doesn't exist.
842
+     */
843
+    private function getTagById($id) {
844
+        return $this->array_searchi($id, $this->tags, 'getId');
845
+    }
846
+
847
+    /**
848
+     * Returns an array mapping a given tag's properties to its values:
849
+     * ['id' => 0, 'name' = 'Tag', 'owner' = 'User', 'type' => 'tagtype']
850
+     *
851
+     * @param Tag $tag The tag that is going to be mapped
852
+     * @return array
853
+     */
854
+    private function tagMap(Tag $tag) {
855
+        return [
856
+            'id'    => $tag->getId(),
857
+            'name'  => $tag->getName(),
858
+            'owner' => $tag->getOwner(),
859
+            'type'  => $tag->getType()
860
+        ];
861
+    }
862 862
 }
Please login to merge, or discard this patch.
Spacing   +83 added lines, -83 removed lines patch added patch discarded remove patch
@@ -136,7 +136,7 @@  discard block
 block discarded – undo
136 136
 		}
137 137
 		$this->tags = $this->mapper->loadTags($this->owners, $this->type);
138 138
 
139
-		if(count($defaultTags) > 0 && count($this->tags) === 0) {
139
+		if (count($defaultTags) > 0 && count($this->tags) === 0) {
140 140
 			$this->addMultiple($defaultTags, true);
141 141
 		}
142 142
 	}
@@ -177,7 +177,7 @@  discard block
 block discarded – undo
177 177
 	 * @return array
178 178
 	 */
179 179
 	public function getTags() {
180
-		if(!count($this->tags)) {
180
+		if (!count($this->tags)) {
181 181
 			return [];
182 182
 		}
183 183
 
@@ -186,8 +186,8 @@  discard block
 block discarded – undo
186 186
 		});
187 187
 		$tagMap = [];
188 188
 
189
-		foreach($this->tags as $tag) {
190
-			if($tag->getName() !== ITags::TAG_FAVORITE) {
189
+		foreach ($this->tags as $tag) {
190
+			if ($tag->getName() !== ITags::TAG_FAVORITE) {
191 191
 				$tagMap[] = $this->tagMap($tag);
192 192
 			}
193 193
 		}
@@ -225,25 +225,25 @@  discard block
 block discarded – undo
225 225
 			$chunks = array_chunk($objIds, 900, false);
226 226
 			foreach ($chunks as $chunk) {
227 227
 				$result = $conn->executeQuery(
228
-					'SELECT `category`, `categoryid`, `objid` ' .
229
-					'FROM `' . self::RELATION_TABLE . '` r, `' . self::TAG_TABLE . '` ' .
228
+					'SELECT `category`, `categoryid`, `objid` '.
229
+					'FROM `'.self::RELATION_TABLE.'` r, `'.self::TAG_TABLE.'` '.
230 230
 					'WHERE `categoryid` = `id` AND `uid` = ? AND r.`type` = ? AND `objid` IN (?)',
231 231
 					[$this->user, $this->type, $chunk],
232 232
 					[null, null, IQueryBuilder::PARAM_INT_ARRAY]
233 233
 				);
234 234
 				while ($row = $result->fetch()) {
235
-					$objId = (int)$row['objid'];
235
+					$objId = (int) $row['objid'];
236 236
 					if (!isset($entries[$objId])) {
237 237
 						$entries[$objId] = [];
238 238
 					}
239 239
 					$entries[$objId][] = $row['category'];
240 240
 				}
241 241
 				if ($result === null) {
242
-					\OCP\Util::writeLog('core', __METHOD__. 'DB error: ' . \OC::$server->getDatabaseConnection()->getError(), ILogger::ERROR);
242
+					\OCP\Util::writeLog('core', __METHOD__.'DB error: '.\OC::$server->getDatabaseConnection()->getError(), ILogger::ERROR);
243 243
 					return false;
244 244
 				}
245 245
 			}
246
-		} catch(\Exception $e) {
246
+		} catch (\Exception $e) {
247 247
 			\OC::$server->getLogger()->logException($e, [
248 248
 				'message' => __METHOD__,
249 249
 				'level' => ILogger::ERROR,
@@ -267,18 +267,18 @@  discard block
 block discarded – undo
267 267
 	public function getIdsForTag($tag) {
268 268
 		$result = null;
269 269
 		$tagId = false;
270
-		if(is_numeric($tag)) {
270
+		if (is_numeric($tag)) {
271 271
 			$tagId = $tag;
272
-		} elseif(is_string($tag)) {
272
+		} elseif (is_string($tag)) {
273 273
 			$tag = trim($tag);
274
-			if($tag === '') {
274
+			if ($tag === '') {
275 275
 				\OCP\Util::writeLog('core', __METHOD__.', Cannot use empty tag names', ILogger::DEBUG);
276 276
 				return false;
277 277
 			}
278 278
 			$tagId = $this->getTagId($tag);
279 279
 		}
280 280
 
281
-		if($tagId === false) {
281
+		if ($tagId === false) {
282 282
 			$l10n = \OC::$server->getL10N('core');
283 283
 			throw new \Exception(
284 284
 				$l10n->t('Could not find category "%s"', [$tag])
@@ -286,17 +286,17 @@  discard block
 block discarded – undo
286 286
 		}
287 287
 
288 288
 		$ids = [];
289
-		$sql = 'SELECT `objid` FROM `' . self::RELATION_TABLE
289
+		$sql = 'SELECT `objid` FROM `'.self::RELATION_TABLE
290 290
 			. '` WHERE `categoryid` = ?';
291 291
 
292 292
 		try {
293 293
 			$stmt = \OC_DB::prepare($sql);
294 294
 			$result = $stmt->execute([$tagId]);
295 295
 			if ($result === null) {
296
-				\OCP\Util::writeLog('core', __METHOD__. 'DB error: ' . \OC::$server->getDatabaseConnection()->getError(), ILogger::ERROR);
296
+				\OCP\Util::writeLog('core', __METHOD__.'DB error: '.\OC::$server->getDatabaseConnection()->getError(), ILogger::ERROR);
297 297
 				return false;
298 298
 			}
299
-		} catch(\Exception $e) {
299
+		} catch (\Exception $e) {
300 300
 			\OC::$server->getLogger()->logException($e, [
301 301
 				'message' => __METHOD__,
302 302
 				'level' => ILogger::ERROR,
@@ -305,9 +305,9 @@  discard block
 block discarded – undo
305 305
 			return false;
306 306
 		}
307 307
 
308
-		if(!is_null($result)) {
309
-			while( $row = $result->fetchRow()) {
310
-				$id = (int)$row['objid'];
308
+		if (!is_null($result)) {
309
+			while ($row = $result->fetchRow()) {
310
+				$id = (int) $row['objid'];
311 311
 
312 312
 				if ($this->includeShared) {
313 313
 					// We have to check if we are really allowed to access the
@@ -361,19 +361,19 @@  discard block
 block discarded – undo
361 361
 	public function add($name) {
362 362
 		$name = trim($name);
363 363
 
364
-		if($name === '') {
364
+		if ($name === '') {
365 365
 			\OCP\Util::writeLog('core', __METHOD__.', Cannot add an empty tag', ILogger::DEBUG);
366 366
 			return false;
367 367
 		}
368
-		if($this->userHasTag($name, $this->user)) {
369
-			\OCP\Util::writeLog('core', __METHOD__.', name: ' . $name. ' exists already', ILogger::DEBUG);
368
+		if ($this->userHasTag($name, $this->user)) {
369
+			\OCP\Util::writeLog('core', __METHOD__.', name: '.$name.' exists already', ILogger::DEBUG);
370 370
 			return false;
371 371
 		}
372 372
 		try {
373 373
 			$tag = new Tag($this->user, $this->type, $name);
374 374
 			$tag = $this->mapper->insert($tag);
375 375
 			$this->tags[] = $tag;
376
-		} catch(\Exception $e) {
376
+		} catch (\Exception $e) {
377 377
 			\OC::$server->getLogger()->logException($e, [
378 378
 				'message' => __METHOD__,
379 379
 				'level' => ILogger::ERROR,
@@ -381,7 +381,7 @@  discard block
 block discarded – undo
381 381
 			]);
382 382
 			return false;
383 383
 		}
384
-		\OCP\Util::writeLog('core', __METHOD__.', id: ' . $tag->getId(), ILogger::DEBUG);
384
+		\OCP\Util::writeLog('core', __METHOD__.', id: '.$tag->getId(), ILogger::DEBUG);
385 385
 		return $tag->getId();
386 386
 	}
387 387
 
@@ -396,7 +396,7 @@  discard block
 block discarded – undo
396 396
 		$from = trim($from);
397 397
 		$to = trim($to);
398 398
 
399
-		if($to === '' || $from === '') {
399
+		if ($to === '' || $from === '') {
400 400
 			\OCP\Util::writeLog('core', __METHOD__.', Cannot use empty tag names', ILogger::DEBUG);
401 401
 			return false;
402 402
 		}
@@ -406,21 +406,21 @@  discard block
 block discarded – undo
406 406
 		} else {
407 407
 			$key = $this->getTagByName($from);
408 408
 		}
409
-		if($key === false) {
410
-			\OCP\Util::writeLog('core', __METHOD__.', tag: ' . $from. ' does not exist', ILogger::DEBUG);
409
+		if ($key === false) {
410
+			\OCP\Util::writeLog('core', __METHOD__.', tag: '.$from.' does not exist', ILogger::DEBUG);
411 411
 			return false;
412 412
 		}
413 413
 		$tag = $this->tags[$key];
414 414
 
415
-		if($this->userHasTag($to, $tag->getOwner())) {
416
-			\OCP\Util::writeLog('core', __METHOD__.', A tag named ' . $to. ' already exists for user ' . $tag->getOwner() . '.', ILogger::DEBUG);
415
+		if ($this->userHasTag($to, $tag->getOwner())) {
416
+			\OCP\Util::writeLog('core', __METHOD__.', A tag named '.$to.' already exists for user '.$tag->getOwner().'.', ILogger::DEBUG);
417 417
 			return false;
418 418
 		}
419 419
 
420 420
 		try {
421 421
 			$tag->setName($to);
422 422
 			$this->tags[$key] = $this->mapper->update($tag);
423
-		} catch(\Exception $e) {
423
+		} catch (\Exception $e) {
424 424
 			\OC::$server->getLogger()->logException($e, [
425 425
 				'message' => __METHOD__,
426 426
 				'level' => ILogger::ERROR,
@@ -440,25 +440,25 @@  discard block
 block discarded – undo
440 440
 	 * @param int|null $id int Optional object id to add to this|these tag(s)
441 441
 	 * @return bool Returns false on error.
442 442
 	 */
443
-	public function addMultiple($names, $sync=false, $id = null) {
444
-		if(!is_array($names)) {
443
+	public function addMultiple($names, $sync = false, $id = null) {
444
+		if (!is_array($names)) {
445 445
 			$names = [$names];
446 446
 		}
447 447
 		$names = array_map('trim', $names);
448 448
 		array_filter($names);
449 449
 
450 450
 		$newones = [];
451
-		foreach($names as $name) {
452
-			if(!$this->hasTag($name) && $name !== '') {
451
+		foreach ($names as $name) {
452
+			if (!$this->hasTag($name) && $name !== '') {
453 453
 				$newones[] = new Tag($this->user, $this->type, $name);
454 454
 			}
455
-			if(!is_null($id) ) {
455
+			if (!is_null($id)) {
456 456
 				// Insert $objectid, $categoryid  pairs if not exist.
457 457
 				self::$relations[] = ['objid' => $id, 'tag' => $name];
458 458
 			}
459 459
 		}
460 460
 		$this->tags = array_merge($this->tags, $newones);
461
-		if($sync === true) {
461
+		if ($sync === true) {
462 462
 			$this->save();
463 463
 		}
464 464
 
@@ -469,13 +469,13 @@  discard block
 block discarded – undo
469 469
 	 * Save the list of tags and their object relations
470 470
 	 */
471 471
 	protected function save() {
472
-		if(is_array($this->tags)) {
473
-			foreach($this->tags as $tag) {
472
+		if (is_array($this->tags)) {
473
+			foreach ($this->tags as $tag) {
474 474
 				try {
475 475
 					if (!$this->mapper->tagExists($tag)) {
476 476
 						$this->mapper->insert($tag);
477 477
 					}
478
-				} catch(\Exception $e) {
478
+				} catch (\Exception $e) {
479 479
 					\OC::$server->getLogger()->logException($e, [
480 480
 						'message' => __METHOD__,
481 481
 						'level' => ILogger::ERROR,
@@ -486,7 +486,7 @@  discard block
 block discarded – undo
486 486
 
487 487
 			// reload tags to get the proper ids.
488 488
 			$this->tags = $this->mapper->loadTags($this->owners, $this->type);
489
-			\OCP\Util::writeLog('core', __METHOD__.', tags: ' . print_r($this->tags, true),
489
+			\OCP\Util::writeLog('core', __METHOD__.', tags: '.print_r($this->tags, true),
490 490
 				ILogger::DEBUG);
491 491
 			// Loop through temporarily cached objectid/tagname pairs
492 492
 			// and save relations.
@@ -494,10 +494,10 @@  discard block
 block discarded – undo
494 494
 			// For some reason this is needed or array_search(i) will return 0..?
495 495
 			ksort($tags);
496 496
 			$dbConnection = \OC::$server->getDatabaseConnection();
497
-			foreach(self::$relations as $relation) {
497
+			foreach (self::$relations as $relation) {
498 498
 				$tagId = $this->getTagId($relation['tag']);
499
-				\OCP\Util::writeLog('core', __METHOD__ . 'catid, ' . $relation['tag'] . ' ' . $tagId, ILogger::DEBUG);
500
-				if($tagId) {
499
+				\OCP\Util::writeLog('core', __METHOD__.'catid, '.$relation['tag'].' '.$tagId, ILogger::DEBUG);
500
+				if ($tagId) {
501 501
 					try {
502 502
 						$dbConnection->insertIfNotExist(self::RELATION_TABLE,
503 503
 							[
@@ -505,7 +505,7 @@  discard block
 block discarded – undo
505 505
 								'categoryid' => $tagId,
506 506
 								'type' => $this->type,
507 507
 								]);
508
-					} catch(\Exception $e) {
508
+					} catch (\Exception $e) {
509 509
 						\OC::$server->getLogger()->logException($e, [
510 510
 							'message' => __METHOD__,
511 511
 							'level' => ILogger::ERROR,
@@ -532,13 +532,13 @@  discard block
 block discarded – undo
532 532
 		// Find all objectid/tagId pairs.
533 533
 		$result = null;
534 534
 		try {
535
-			$stmt = \OC_DB::prepare('SELECT `id` FROM `' . self::TAG_TABLE . '` '
535
+			$stmt = \OC_DB::prepare('SELECT `id` FROM `'.self::TAG_TABLE.'` '
536 536
 				. 'WHERE `uid` = ?');
537 537
 			$result = $stmt->execute([$arguments['uid']]);
538 538
 			if ($result === null) {
539
-				\OCP\Util::writeLog('core', __METHOD__. 'DB error: ' . \OC::$server->getDatabaseConnection()->getError(), ILogger::ERROR);
539
+				\OCP\Util::writeLog('core', __METHOD__.'DB error: '.\OC::$server->getDatabaseConnection()->getError(), ILogger::ERROR);
540 540
 			}
541
-		} catch(\Exception $e) {
541
+		} catch (\Exception $e) {
542 542
 			\OC::$server->getLogger()->logException($e, [
543 543
 				'message' => __METHOD__,
544 544
 				'level' => ILogger::ERROR,
@@ -546,14 +546,14 @@  discard block
 block discarded – undo
546 546
 			]);
547 547
 		}
548 548
 
549
-		if(!is_null($result)) {
549
+		if (!is_null($result)) {
550 550
 			try {
551
-				$stmt = \OC_DB::prepare('DELETE FROM `' . self::RELATION_TABLE . '` '
551
+				$stmt = \OC_DB::prepare('DELETE FROM `'.self::RELATION_TABLE.'` '
552 552
 					. 'WHERE `categoryid` = ?');
553
-				while( $row = $result->fetchRow()) {
553
+				while ($row = $result->fetchRow()) {
554 554
 					try {
555 555
 						$stmt->execute([$row['id']]);
556
-					} catch(\Exception $e) {
556
+					} catch (\Exception $e) {
557 557
 						\OC::$server->getLogger()->logException($e, [
558 558
 							'message' => __METHOD__,
559 559
 							'level' => ILogger::ERROR,
@@ -561,7 +561,7 @@  discard block
 block discarded – undo
561 561
 						]);
562 562
 					}
563 563
 				}
564
-			} catch(\Exception $e) {
564
+			} catch (\Exception $e) {
565 565
 				\OC::$server->getLogger()->logException($e, [
566 566
 					'message' => __METHOD__,
567 567
 					'level' => ILogger::ERROR,
@@ -570,13 +570,13 @@  discard block
 block discarded – undo
570 570
 			}
571 571
 		}
572 572
 		try {
573
-			$stmt = \OC_DB::prepare('DELETE FROM `' . self::TAG_TABLE . '` '
573
+			$stmt = \OC_DB::prepare('DELETE FROM `'.self::TAG_TABLE.'` '
574 574
 				. 'WHERE `uid` = ?');
575 575
 			$result = $stmt->execute([$arguments['uid']]);
576 576
 			if ($result === null) {
577
-				\OCP\Util::writeLog('core', __METHOD__. ', DB error: ' . \OC::$server->getDatabaseConnection()->getError(), ILogger::ERROR);
577
+				\OCP\Util::writeLog('core', __METHOD__.', DB error: '.\OC::$server->getDatabaseConnection()->getError(), ILogger::ERROR);
578 578
 			}
579
-		} catch(\Exception $e) {
579
+		} catch (\Exception $e) {
580 580
 			\OC::$server->getLogger()->logException($e, [
581 581
 				'message' => __METHOD__,
582 582
 				'level' => ILogger::ERROR,
@@ -592,23 +592,23 @@  discard block
 block discarded – undo
592 592
 	 * @return boolean Returns false on error.
593 593
 	 */
594 594
 	public function purgeObjects(array $ids) {
595
-		if(count($ids) === 0) {
595
+		if (count($ids) === 0) {
596 596
 			// job done ;)
597 597
 			return true;
598 598
 		}
599 599
 		$updates = $ids;
600 600
 		try {
601
-			$query = 'DELETE FROM `' . self::RELATION_TABLE . '` ';
602
-			$query .= 'WHERE `objid` IN (' . str_repeat('?,', count($ids)-1) . '?) ';
601
+			$query = 'DELETE FROM `'.self::RELATION_TABLE.'` ';
602
+			$query .= 'WHERE `objid` IN ('.str_repeat('?,', count($ids) - 1).'?) ';
603 603
 			$query .= 'AND `type`= ?';
604 604
 			$updates[] = $this->type;
605 605
 			$stmt = \OC_DB::prepare($query);
606 606
 			$result = $stmt->execute($updates);
607 607
 			if ($result === null) {
608
-				\OCP\Util::writeLog('core', __METHOD__. 'DB error: ' . \OC::$server->getDatabaseConnection()->getError(), ILogger::ERROR);
608
+				\OCP\Util::writeLog('core', __METHOD__.'DB error: '.\OC::$server->getDatabaseConnection()->getError(), ILogger::ERROR);
609 609
 				return false;
610 610
 			}
611
-		} catch(\Exception $e) {
611
+		} catch (\Exception $e) {
612 612
 			\OC::$server->getLogger()->logException($e, [
613 613
 				'message' => __METHOD__,
614 614
 				'level' => ILogger::ERROR,
@@ -625,13 +625,13 @@  discard block
 block discarded – undo
625 625
 	 * @return array|false An array of object ids.
626 626
 	 */
627 627
 	public function getFavorites() {
628
-		if(!$this->userHasTag(ITags::TAG_FAVORITE, $this->user)) {
628
+		if (!$this->userHasTag(ITags::TAG_FAVORITE, $this->user)) {
629 629
 			return [];
630 630
 		}
631 631
 
632 632
 		try {
633 633
 			return $this->getIdsForTag(ITags::TAG_FAVORITE);
634
-		} catch(\Exception $e) {
634
+		} catch (\Exception $e) {
635 635
 			\OC::$server->getLogger()->logException($e, [
636 636
 				'message' => __METHOD__,
637 637
 				'level' => ILogger::ERROR,
@@ -648,7 +648,7 @@  discard block
 block discarded – undo
648 648
 	 * @return boolean
649 649
 	 */
650 650
 	public function addToFavorites($objid) {
651
-		if(!$this->userHasTag(ITags::TAG_FAVORITE, $this->user)) {
651
+		if (!$this->userHasTag(ITags::TAG_FAVORITE, $this->user)) {
652 652
 			$this->add(ITags::TAG_FAVORITE);
653 653
 		}
654 654
 		return $this->tagAs($objid, ITags::TAG_FAVORITE);
@@ -672,16 +672,16 @@  discard block
 block discarded – undo
672 672
 	 * @return boolean Returns false on error.
673 673
 	 */
674 674
 	public function tagAs($objid, $tag) {
675
-		if(is_string($tag) && !is_numeric($tag)) {
675
+		if (is_string($tag) && !is_numeric($tag)) {
676 676
 			$tag = trim($tag);
677
-			if($tag === '') {
677
+			if ($tag === '') {
678 678
 				\OCP\Util::writeLog('core', __METHOD__.', Cannot add an empty tag', ILogger::DEBUG);
679 679
 				return false;
680 680
 			}
681
-			if(!$this->hasTag($tag)) {
681
+			if (!$this->hasTag($tag)) {
682 682
 				$this->add($tag);
683 683
 			}
684
-			$tagId =  $this->getTagId($tag);
684
+			$tagId = $this->getTagId($tag);
685 685
 		} else {
686 686
 			$tagId = $tag;
687 687
 		}
@@ -692,7 +692,7 @@  discard block
 block discarded – undo
692 692
 					'categoryid' => $tagId,
693 693
 					'type' => $this->type,
694 694
 				]);
695
-		} catch(\Exception $e) {
695
+		} catch (\Exception $e) {
696 696
 			\OC::$server->getLogger()->logException($e, [
697 697
 				'message' => __METHOD__,
698 698
 				'level' => ILogger::ERROR,
@@ -711,23 +711,23 @@  discard block
 block discarded – undo
711 711
 	 * @return boolean
712 712
 	 */
713 713
 	public function unTag($objid, $tag) {
714
-		if(is_string($tag) && !is_numeric($tag)) {
714
+		if (is_string($tag) && !is_numeric($tag)) {
715 715
 			$tag = trim($tag);
716
-			if($tag === '') {
716
+			if ($tag === '') {
717 717
 				\OCP\Util::writeLog('core', __METHOD__.', Tag name is empty', ILogger::DEBUG);
718 718
 				return false;
719 719
 			}
720
-			$tagId =  $this->getTagId($tag);
720
+			$tagId = $this->getTagId($tag);
721 721
 		} else {
722 722
 			$tagId = $tag;
723 723
 		}
724 724
 
725 725
 		try {
726
-			$sql = 'DELETE FROM `' . self::RELATION_TABLE . '` '
726
+			$sql = 'DELETE FROM `'.self::RELATION_TABLE.'` '
727 727
 					. 'WHERE `objid` = ? AND `categoryid` = ? AND `type` = ?';
728 728
 			$stmt = \OC_DB::prepare($sql);
729 729
 			$stmt->execute([$objid, $tagId, $this->type]);
730
-		} catch(\Exception $e) {
730
+		} catch (\Exception $e) {
731 731
 			\OC::$server->getLogger()->logException($e, [
732 732
 				'message' => __METHOD__,
733 733
 				'level' => ILogger::ERROR,
@@ -745,16 +745,16 @@  discard block
 block discarded – undo
745 745
 	 * @return bool Returns false on error
746 746
 	 */
747 747
 	public function delete($names) {
748
-		if(!is_array($names)) {
748
+		if (!is_array($names)) {
749 749
 			$names = [$names];
750 750
 		}
751 751
 
752 752
 		$names = array_map('trim', $names);
753 753
 		array_filter($names);
754 754
 
755
-		\OCP\Util::writeLog('core', __METHOD__ . ', before: '
755
+		\OCP\Util::writeLog('core', __METHOD__.', before: '
756 756
 			. print_r($this->tags, true), ILogger::DEBUG);
757
-		foreach($names as $name) {
757
+		foreach ($names as $name) {
758 758
 			$id = null;
759 759
 
760 760
 			if (is_numeric($name)) {
@@ -768,22 +768,22 @@  discard block
 block discarded – undo
768 768
 				unset($this->tags[$key]);
769 769
 				$this->mapper->delete($tag);
770 770
 			} else {
771
-				\OCP\Util::writeLog('core', __METHOD__ . 'Cannot delete tag ' . $name
771
+				\OCP\Util::writeLog('core', __METHOD__.'Cannot delete tag '.$name
772 772
 					. ': not found.', ILogger::ERROR);
773 773
 			}
774
-			if(!is_null($id) && $id !== false) {
774
+			if (!is_null($id) && $id !== false) {
775 775
 				try {
776
-					$sql = 'DELETE FROM `' . self::RELATION_TABLE . '` '
776
+					$sql = 'DELETE FROM `'.self::RELATION_TABLE.'` '
777 777
 							. 'WHERE `categoryid` = ?';
778 778
 					$stmt = \OC_DB::prepare($sql);
779 779
 					$result = $stmt->execute([$id]);
780 780
 					if ($result === null) {
781 781
 						\OCP\Util::writeLog('core',
782
-							__METHOD__. 'DB error: ' . \OC::$server->getDatabaseConnection()->getError(),
782
+							__METHOD__.'DB error: '.\OC::$server->getDatabaseConnection()->getError(),
783 783
 							ILogger::ERROR);
784 784
 						return false;
785 785
 					}
786
-				} catch(\Exception $e) {
786
+				} catch (\Exception $e) {
787 787
 					\OC::$server->getLogger()->logException($e, [
788 788
 						'message' => __METHOD__,
789 789
 						'level' => ILogger::ERROR,
@@ -797,8 +797,8 @@  discard block
 block discarded – undo
797 797
 	}
798 798
 
799 799
 	// case-insensitive array_search
800
-	protected function array_searchi($needle, $haystack, $mem='getName') {
801
-		if(!is_array($haystack)) {
800
+	protected function array_searchi($needle, $haystack, $mem = 'getName') {
801
+		if (!is_array($haystack)) {
802 802
 			return false;
803 803
 		}
804 804
 		return array_search(strtolower($needle), array_map(
Please login to merge, or discard this patch.
core/Command/Background/Base.php 2 patches
Indentation   +31 added lines, -31 removed lines patch added patch discarded remove patch
@@ -39,39 +39,39 @@
 block discarded – undo
39 39
 abstract class Base extends Command {
40 40
 
41 41
 
42
-	abstract protected function getMode();
42
+    abstract protected function getMode();
43 43
 
44
-	/**
45
-	 * @var \OCP\IConfig
46
-	 */
47
-	protected $config;
44
+    /**
45
+     * @var \OCP\IConfig
46
+     */
47
+    protected $config;
48 48
 
49
-	/**
50
-	 * @param \OCP\IConfig $config
51
-	 */
52
-	public function __construct(IConfig $config) {
53
-		$this->config = $config;
54
-		parent::__construct();
55
-	}
49
+    /**
50
+     * @param \OCP\IConfig $config
51
+     */
52
+    public function __construct(IConfig $config) {
53
+        $this->config = $config;
54
+        parent::__construct();
55
+    }
56 56
 
57
-	protected function configure() {
58
-		$mode = $this->getMode();
59
-		$this
60
-			->setName("background:$mode")
61
-			->setDescription("Use $mode to run background jobs");
62
-	}
57
+    protected function configure() {
58
+        $mode = $this->getMode();
59
+        $this
60
+            ->setName("background:$mode")
61
+            ->setDescription("Use $mode to run background jobs");
62
+    }
63 63
 
64
-	/**
65
-	 * Executing this command will set the background job mode for owncloud.
66
-	 * The mode to set is specified by the concrete sub class by implementing the
67
-	 * getMode() function.
68
-	 *
69
-	 * @param InputInterface $input
70
-	 * @param OutputInterface $output
71
-	 */
72
-	protected function execute(InputInterface $input, OutputInterface $output) {
73
-		$mode = $this->getMode();
74
-		$this->config->setAppValue( 'core', 'backgroundjobs_mode', $mode );
75
-		$output->writeln("Set mode for background jobs to '$mode'");
76
-	}
64
+    /**
65
+     * Executing this command will set the background job mode for owncloud.
66
+     * The mode to set is specified by the concrete sub class by implementing the
67
+     * getMode() function.
68
+     *
69
+     * @param InputInterface $input
70
+     * @param OutputInterface $output
71
+     */
72
+    protected function execute(InputInterface $input, OutputInterface $output) {
73
+        $mode = $this->getMode();
74
+        $this->config->setAppValue( 'core', 'backgroundjobs_mode', $mode );
75
+        $output->writeln("Set mode for background jobs to '$mode'");
76
+    }
77 77
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -71,7 +71,7 @@
 block discarded – undo
71 71
 	 */
72 72
 	protected function execute(InputInterface $input, OutputInterface $output) {
73 73
 		$mode = $this->getMode();
74
-		$this->config->setAppValue( 'core', 'backgroundjobs_mode', $mode );
74
+		$this->config->setAppValue('core', 'backgroundjobs_mode', $mode);
75 75
 		$output->writeln("Set mode for background jobs to '$mode'");
76 76
 	}
77 77
 }
Please login to merge, or discard this patch.
core/Controller/WebAuthnController.php 2 patches
Indentation   +76 added lines, -76 removed lines patch added patch discarded remove patch
@@ -38,80 +38,80 @@
 block discarded – undo
38 38
 
39 39
 class WebAuthnController extends Controller {
40 40
 
41
-	private const WEBAUTHN_LOGIN = 'webauthn_login';
42
-	private const WEBAUTHN_LOGIN_UID = 'webauthn_login_uid';
43
-
44
-	/** @var Manager */
45
-	private $webAuthnManger;
46
-
47
-	/** @var ISession */
48
-	private $session;
49
-
50
-	/** @var ILogger */
51
-	private $logger;
52
-
53
-	/** @var WebAuthnChain */
54
-	private $webAuthnChain;
55
-
56
-	public function __construct($appName, IRequest $request, Manager $webAuthnManger, ISession $session, ILogger $logger, WebAuthnChain $webAuthnChain) {
57
-		parent::__construct($appName, $request);
58
-
59
-		$this->webAuthnManger = $webAuthnManger;
60
-		$this->session = $session;
61
-		$this->logger = $logger;
62
-		$this->webAuthnChain = $webAuthnChain;
63
-	}
64
-
65
-	/**
66
-	 * @NoAdminRequired
67
-	 * @PublicPage
68
-	 * @UseSession
69
-	 */
70
-	public function startAuthentication(string $loginName): JSONResponse {
71
-		$this->logger->debug('Starting WebAuthn login');
72
-
73
-		$this->logger->debug('Converting login name to UID');
74
-		$uid = $loginName;
75
-		Util::emitHook(
76
-			'\OCA\Files_Sharing\API\Server2Server',
77
-			'preLoginNameUsedAsUserName',
78
-			['uid' => &$uid]
79
-		);
80
-		$this->logger->debug('Got UID: ' . $uid);
81
-
82
-		$publicKeyCredentialRequestOptions = $this->webAuthnManger->startAuthentication($uid, $this->request->getServerHost());
83
-		$this->session->set(self::WEBAUTHN_LOGIN, json_encode($publicKeyCredentialRequestOptions));
84
-		$this->session->set(self::WEBAUTHN_LOGIN_UID, $uid);
85
-
86
-		return new JSONResponse($publicKeyCredentialRequestOptions);
87
-	}
88
-
89
-	/**
90
-	 * @NoAdminRequired
91
-	 * @PublicPage
92
-	 * @UseSession
93
-	 */
94
-	public function finishAuthentication(string $data): JSONResponse {
95
-		$this->logger->debug('Validating WebAuthn login');
96
-
97
-		if (!$this->session->exists(self::WEBAUTHN_LOGIN) || !$this->session->exists(self::WEBAUTHN_LOGIN_UID)) {
98
-			$this->logger->debug('Trying to finish WebAuthn login without session data');
99
-			return new JSONResponse([], Http::STATUS_BAD_REQUEST);
100
-		}
101
-
102
-		// Obtain the publicKeyCredentialOptions from when we started the registration
103
-		$publicKeyCredentialRequestOptions = PublicKeyCredentialRequestOptions::createFromString($this->session->get(self::WEBAUTHN_LOGIN));
104
-		$uid = $this->session->get(self::WEBAUTHN_LOGIN_UID);
105
-		$this->webAuthnManger->finishAuthentication($publicKeyCredentialRequestOptions, $data, $uid);
106
-
107
-		//TODO: add other parameters
108
-		$loginData = new LoginData(
109
-			$this->request,
110
-			$uid,
111
-			''
112
-		);
113
-		$this->webAuthnChain->process($loginData);
114
-
115
-		return new JSONResponse([]);
116
-	}
41
+    private const WEBAUTHN_LOGIN = 'webauthn_login';
42
+    private const WEBAUTHN_LOGIN_UID = 'webauthn_login_uid';
43
+
44
+    /** @var Manager */
45
+    private $webAuthnManger;
46
+
47
+    /** @var ISession */
48
+    private $session;
49
+
50
+    /** @var ILogger */
51
+    private $logger;
52
+
53
+    /** @var WebAuthnChain */
54
+    private $webAuthnChain;
55
+
56
+    public function __construct($appName, IRequest $request, Manager $webAuthnManger, ISession $session, ILogger $logger, WebAuthnChain $webAuthnChain) {
57
+        parent::__construct($appName, $request);
58
+
59
+        $this->webAuthnManger = $webAuthnManger;
60
+        $this->session = $session;
61
+        $this->logger = $logger;
62
+        $this->webAuthnChain = $webAuthnChain;
63
+    }
64
+
65
+    /**
66
+     * @NoAdminRequired
67
+     * @PublicPage
68
+     * @UseSession
69
+     */
70
+    public function startAuthentication(string $loginName): JSONResponse {
71
+        $this->logger->debug('Starting WebAuthn login');
72
+
73
+        $this->logger->debug('Converting login name to UID');
74
+        $uid = $loginName;
75
+        Util::emitHook(
76
+            '\OCA\Files_Sharing\API\Server2Server',
77
+            'preLoginNameUsedAsUserName',
78
+            ['uid' => &$uid]
79
+        );
80
+        $this->logger->debug('Got UID: ' . $uid);
81
+
82
+        $publicKeyCredentialRequestOptions = $this->webAuthnManger->startAuthentication($uid, $this->request->getServerHost());
83
+        $this->session->set(self::WEBAUTHN_LOGIN, json_encode($publicKeyCredentialRequestOptions));
84
+        $this->session->set(self::WEBAUTHN_LOGIN_UID, $uid);
85
+
86
+        return new JSONResponse($publicKeyCredentialRequestOptions);
87
+    }
88
+
89
+    /**
90
+     * @NoAdminRequired
91
+     * @PublicPage
92
+     * @UseSession
93
+     */
94
+    public function finishAuthentication(string $data): JSONResponse {
95
+        $this->logger->debug('Validating WebAuthn login');
96
+
97
+        if (!$this->session->exists(self::WEBAUTHN_LOGIN) || !$this->session->exists(self::WEBAUTHN_LOGIN_UID)) {
98
+            $this->logger->debug('Trying to finish WebAuthn login without session data');
99
+            return new JSONResponse([], Http::STATUS_BAD_REQUEST);
100
+        }
101
+
102
+        // Obtain the publicKeyCredentialOptions from when we started the registration
103
+        $publicKeyCredentialRequestOptions = PublicKeyCredentialRequestOptions::createFromString($this->session->get(self::WEBAUTHN_LOGIN));
104
+        $uid = $this->session->get(self::WEBAUTHN_LOGIN_UID);
105
+        $this->webAuthnManger->finishAuthentication($publicKeyCredentialRequestOptions, $data, $uid);
106
+
107
+        //TODO: add other parameters
108
+        $loginData = new LoginData(
109
+            $this->request,
110
+            $uid,
111
+            ''
112
+        );
113
+        $this->webAuthnChain->process($loginData);
114
+
115
+        return new JSONResponse([]);
116
+    }
117 117
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -77,7 +77,7 @@
 block discarded – undo
77 77
 			'preLoginNameUsedAsUserName',
78 78
 			['uid' => &$uid]
79 79
 		);
80
-		$this->logger->debug('Got UID: ' . $uid);
80
+		$this->logger->debug('Got UID: '.$uid);
81 81
 
82 82
 		$publicKeyCredentialRequestOptions = $this->webAuthnManger->startAuthentication($uid, $this->request->getServerHost());
83 83
 		$this->session->set(self::WEBAUTHN_LOGIN, json_encode($publicKeyCredentialRequestOptions));
Please login to merge, or discard this patch.
core/Controller/AvatarController.php 1 patch
Indentation   +289 added lines, -289 removed lines patch added patch discarded remove patch
@@ -53,293 +53,293 @@
 block discarded – undo
53 53
  */
54 54
 class AvatarController extends Controller {
55 55
 
56
-	/** @var IAvatarManager */
57
-	protected $avatarManager;
58
-
59
-	/** @var ICache */
60
-	protected $cache;
61
-
62
-	/** @var IL10N */
63
-	protected $l;
64
-
65
-	/** @var IUserManager */
66
-	protected $userManager;
67
-
68
-	/** @var IUserSession */
69
-	protected $userSession;
70
-
71
-	/** @var IRootFolder */
72
-	protected $rootFolder;
73
-
74
-	/** @var ILogger */
75
-	protected $logger;
76
-
77
-	/** @var string */
78
-	protected $userId;
79
-
80
-	/** @var TimeFactory */
81
-	protected $timeFactory;
82
-	/** @var IAccountManager */
83
-	private $accountManager;
84
-
85
-	public function __construct($appName,
86
-								IRequest $request,
87
-								IAvatarManager $avatarManager,
88
-								ICache $cache,
89
-								IL10N $l10n,
90
-								IUserManager $userManager,
91
-								IRootFolder $rootFolder,
92
-								ILogger $logger,
93
-								$userId,
94
-								TimeFactory $timeFactory,
95
-								IAccountManager $accountManager) {
96
-		parent::__construct($appName, $request);
97
-
98
-		$this->avatarManager = $avatarManager;
99
-		$this->cache = $cache;
100
-		$this->l = $l10n;
101
-		$this->userManager = $userManager;
102
-		$this->rootFolder = $rootFolder;
103
-		$this->logger = $logger;
104
-		$this->userId = $userId;
105
-		$this->timeFactory = $timeFactory;
106
-		$this->accountManager = $accountManager;
107
-	}
108
-
109
-
110
-	/**
111
-	 * @NoAdminRequired
112
-	 * @NoCSRFRequired
113
-	 * @NoSameSiteCookieRequired
114
-	 * @PublicPage
115
-	 *
116
-	 * @param string $userId
117
-	 * @param int $size
118
-	 * @return JSONResponse|FileDisplayResponse
119
-	 */
120
-	public function getAvatar($userId, $size) {
121
-		// min/max size
122
-		if ($size > 2048) {
123
-			$size = 2048;
124
-		} elseif ($size <= 0) {
125
-			$size = 64;
126
-		}
127
-
128
-		$user = $this->userManager->get($userId);
129
-		if ($user === null) {
130
-			return new JSONResponse([], Http::STATUS_NOT_FOUND);
131
-		}
132
-
133
-		$account = $this->accountManager->getAccount($user);
134
-		$scope = $account->getProperty(IAccountManager::PROPERTY_AVATAR)->getScope();
135
-
136
-		if ($scope !== IAccountManager::VISIBILITY_PUBLIC && $this->userId === null) {
137
-			// Public avatar access is not allowed
138
-			$response = new JSONResponse([], Http::STATUS_NOT_FOUND);
139
-			$response->cacheFor(1800);
140
-			return $response;
141
-		}
142
-
143
-		try {
144
-			$avatar = $this->avatarManager->getAvatar($userId);
145
-			$avatarFile = $avatar->getFile($size);
146
-			$response = new FileDisplayResponse(
147
-				$avatarFile,
148
-				Http::STATUS_OK,
149
-				['Content-Type' => $avatarFile->getMimeType(), 'X-NC-IsCustomAvatar' => (int)$avatar->isCustomAvatar()]
150
-			);
151
-		} catch (\Exception $e) {
152
-			return new JSONResponse([], Http::STATUS_NOT_FOUND);
153
-		}
154
-
155
-		// Cache for 30 minutes
156
-		$response->cacheFor(1800);
157
-		return $response;
158
-	}
159
-
160
-	/**
161
-	 * @NoAdminRequired
162
-	 *
163
-	 * @param string $path
164
-	 * @return JSONResponse
165
-	 */
166
-	public function postAvatar($path) {
167
-		$files = $this->request->getUploadedFile('files');
168
-
169
-		if (isset($path)) {
170
-			$path = stripslashes($path);
171
-			$userFolder = $this->rootFolder->getUserFolder($this->userId);
172
-			/** @var File $node */
173
-			$node = $userFolder->get($path);
174
-			if (!($node instanceof File)) {
175
-				return new JSONResponse(['data' => ['message' => $this->l->t('Please select a file.')]]);
176
-			}
177
-			if ($node->getSize() > 20*1024*1024) {
178
-				return new JSONResponse(
179
-					['data' => ['message' => $this->l->t('File is too big')]],
180
-					Http::STATUS_BAD_REQUEST
181
-				);
182
-			}
183
-
184
-			if ($node->getMimeType() !== 'image/jpeg' && $node->getMimeType() !== 'image/png') {
185
-				return new JSONResponse(
186
-					['data' => ['message' => $this->l->t('The selected file is not an image.')]],
187
-					Http::STATUS_BAD_REQUEST
188
-				);
189
-			}
190
-
191
-			try {
192
-				$content = $node->getContent();
193
-			} catch (\OCP\Files\NotPermittedException $e) {
194
-				return new JSONResponse(
195
-					['data' => ['message' => $this->l->t('The selected file cannot be read.')]],
196
-					Http::STATUS_BAD_REQUEST
197
-				);
198
-			}
199
-		} elseif (!is_null($files)) {
200
-			if (
201
-				$files['error'][0] === 0 &&
202
-				 is_uploaded_file($files['tmp_name'][0]) &&
203
-				!\OC\Files\Filesystem::isFileBlacklisted($files['tmp_name'][0])
204
-			) {
205
-				if ($files['size'][0] > 20*1024*1024) {
206
-					return new JSONResponse(
207
-						['data' => ['message' => $this->l->t('File is too big')]],
208
-						Http::STATUS_BAD_REQUEST
209
-					);
210
-				}
211
-				$this->cache->set('avatar_upload', file_get_contents($files['tmp_name'][0]), 7200);
212
-				$content = $this->cache->get('avatar_upload');
213
-				unlink($files['tmp_name'][0]);
214
-			} else {
215
-				return new JSONResponse(
216
-					['data' => ['message' => $this->l->t('Invalid file provided')]],
217
-					Http::STATUS_BAD_REQUEST
218
-				);
219
-			}
220
-		} else {
221
-			//Add imgfile
222
-			return new JSONResponse(
223
-				['data' => ['message' => $this->l->t('No image or file provided')]],
224
-				Http::STATUS_BAD_REQUEST
225
-			);
226
-		}
227
-
228
-		try {
229
-			$image = new \OC_Image();
230
-			$image->loadFromData($content);
231
-			$image->readExif($content);
232
-			$image->fixOrientation();
233
-
234
-			if ($image->valid()) {
235
-				$mimeType = $image->mimeType();
236
-				if ($mimeType !== 'image/jpeg' && $mimeType !== 'image/png') {
237
-					return new JSONResponse(
238
-						['data' => ['message' => $this->l->t('Unknown filetype')]],
239
-						Http::STATUS_OK
240
-					);
241
-				}
242
-
243
-				$this->cache->set('tmpAvatar', $image->data(), 7200);
244
-				return new JSONResponse(
245
-					['data' => 'notsquare'],
246
-					Http::STATUS_OK
247
-				);
248
-			} else {
249
-				return new JSONResponse(
250
-					['data' => ['message' => $this->l->t('Invalid image')]],
251
-					Http::STATUS_OK
252
-				);
253
-			}
254
-		} catch (\Exception $e) {
255
-			$this->logger->logException($e, ['app' => 'core']);
256
-			return new JSONResponse(['data' => ['message' => $this->l->t('An error occurred. Please contact your admin.')]], Http::STATUS_OK);
257
-		}
258
-	}
259
-
260
-	/**
261
-	 * @NoAdminRequired
262
-	 *
263
-	 * @return JSONResponse
264
-	 */
265
-	public function deleteAvatar() {
266
-		try {
267
-			$avatar = $this->avatarManager->getAvatar($this->userId);
268
-			$avatar->remove();
269
-			return new JSONResponse();
270
-		} catch (\Exception $e) {
271
-			$this->logger->logException($e, ['app' => 'core']);
272
-			return new JSONResponse(['data' => ['message' => $this->l->t('An error occurred. Please contact your admin.')]], Http::STATUS_BAD_REQUEST);
273
-		}
274
-	}
275
-
276
-	/**
277
-	 * @NoAdminRequired
278
-	 *
279
-	 * @return JSONResponse|DataDisplayResponse
280
-	 */
281
-	public function getTmpAvatar() {
282
-		$tmpAvatar = $this->cache->get('tmpAvatar');
283
-		if (is_null($tmpAvatar)) {
284
-			return new JSONResponse(['data' => [
285
-										'message' => $this->l->t("No temporary profile picture available, try again")
286
-									]],
287
-									Http::STATUS_NOT_FOUND);
288
-		}
289
-
290
-		$image = new \OC_Image();
291
-		$image->loadFromData($tmpAvatar);
292
-
293
-		$resp = new DataDisplayResponse($image->data(),
294
-				Http::STATUS_OK,
295
-				['Content-Type' => $image->mimeType()]);
296
-
297
-		$resp->setETag((string)crc32($image->data()));
298
-		$resp->cacheFor(0);
299
-		$resp->setLastModified(new \DateTime('now', new \DateTimeZone('GMT')));
300
-		return $resp;
301
-	}
302
-
303
-	/**
304
-	 * @NoAdminRequired
305
-	 *
306
-	 * @param array $crop
307
-	 * @return JSONResponse
308
-	 */
309
-	public function postCroppedAvatar($crop) {
310
-		if (is_null($crop)) {
311
-			return new JSONResponse(['data' => ['message' => $this->l->t("No crop data provided")]],
312
-									Http::STATUS_BAD_REQUEST);
313
-		}
314
-
315
-		if (!isset($crop['x'], $crop['y'], $crop['w'], $crop['h'])) {
316
-			return new JSONResponse(['data' => ['message' => $this->l->t("No valid crop data provided")]],
317
-									Http::STATUS_BAD_REQUEST);
318
-		}
319
-
320
-		$tmpAvatar = $this->cache->get('tmpAvatar');
321
-		if (is_null($tmpAvatar)) {
322
-			return new JSONResponse(['data' => [
323
-										'message' => $this->l->t("No temporary profile picture available, try again")
324
-									]],
325
-									Http::STATUS_BAD_REQUEST);
326
-		}
327
-
328
-		$image = new \OC_Image();
329
-		$image->loadFromData($tmpAvatar);
330
-		$image->crop($crop['x'], $crop['y'], (int)round($crop['w']), (int)round($crop['h']));
331
-		try {
332
-			$avatar = $this->avatarManager->getAvatar($this->userId);
333
-			$avatar->set($image);
334
-			// Clean up
335
-			$this->cache->remove('tmpAvatar');
336
-			return new JSONResponse(['status' => 'success']);
337
-		} catch (\OC\NotSquareException $e) {
338
-			return new JSONResponse(['data' => ['message' => $this->l->t('Crop is not square')]],
339
-									Http::STATUS_BAD_REQUEST);
340
-		} catch (\Exception $e) {
341
-			$this->logger->logException($e, ['app' => 'core']);
342
-			return new JSONResponse(['data' => ['message' => $this->l->t('An error occurred. Please contact your admin.')]], Http::STATUS_BAD_REQUEST);
343
-		}
344
-	}
56
+    /** @var IAvatarManager */
57
+    protected $avatarManager;
58
+
59
+    /** @var ICache */
60
+    protected $cache;
61
+
62
+    /** @var IL10N */
63
+    protected $l;
64
+
65
+    /** @var IUserManager */
66
+    protected $userManager;
67
+
68
+    /** @var IUserSession */
69
+    protected $userSession;
70
+
71
+    /** @var IRootFolder */
72
+    protected $rootFolder;
73
+
74
+    /** @var ILogger */
75
+    protected $logger;
76
+
77
+    /** @var string */
78
+    protected $userId;
79
+
80
+    /** @var TimeFactory */
81
+    protected $timeFactory;
82
+    /** @var IAccountManager */
83
+    private $accountManager;
84
+
85
+    public function __construct($appName,
86
+                                IRequest $request,
87
+                                IAvatarManager $avatarManager,
88
+                                ICache $cache,
89
+                                IL10N $l10n,
90
+                                IUserManager $userManager,
91
+                                IRootFolder $rootFolder,
92
+                                ILogger $logger,
93
+                                $userId,
94
+                                TimeFactory $timeFactory,
95
+                                IAccountManager $accountManager) {
96
+        parent::__construct($appName, $request);
97
+
98
+        $this->avatarManager = $avatarManager;
99
+        $this->cache = $cache;
100
+        $this->l = $l10n;
101
+        $this->userManager = $userManager;
102
+        $this->rootFolder = $rootFolder;
103
+        $this->logger = $logger;
104
+        $this->userId = $userId;
105
+        $this->timeFactory = $timeFactory;
106
+        $this->accountManager = $accountManager;
107
+    }
108
+
109
+
110
+    /**
111
+     * @NoAdminRequired
112
+     * @NoCSRFRequired
113
+     * @NoSameSiteCookieRequired
114
+     * @PublicPage
115
+     *
116
+     * @param string $userId
117
+     * @param int $size
118
+     * @return JSONResponse|FileDisplayResponse
119
+     */
120
+    public function getAvatar($userId, $size) {
121
+        // min/max size
122
+        if ($size > 2048) {
123
+            $size = 2048;
124
+        } elseif ($size <= 0) {
125
+            $size = 64;
126
+        }
127
+
128
+        $user = $this->userManager->get($userId);
129
+        if ($user === null) {
130
+            return new JSONResponse([], Http::STATUS_NOT_FOUND);
131
+        }
132
+
133
+        $account = $this->accountManager->getAccount($user);
134
+        $scope = $account->getProperty(IAccountManager::PROPERTY_AVATAR)->getScope();
135
+
136
+        if ($scope !== IAccountManager::VISIBILITY_PUBLIC && $this->userId === null) {
137
+            // Public avatar access is not allowed
138
+            $response = new JSONResponse([], Http::STATUS_NOT_FOUND);
139
+            $response->cacheFor(1800);
140
+            return $response;
141
+        }
142
+
143
+        try {
144
+            $avatar = $this->avatarManager->getAvatar($userId);
145
+            $avatarFile = $avatar->getFile($size);
146
+            $response = new FileDisplayResponse(
147
+                $avatarFile,
148
+                Http::STATUS_OK,
149
+                ['Content-Type' => $avatarFile->getMimeType(), 'X-NC-IsCustomAvatar' => (int)$avatar->isCustomAvatar()]
150
+            );
151
+        } catch (\Exception $e) {
152
+            return new JSONResponse([], Http::STATUS_NOT_FOUND);
153
+        }
154
+
155
+        // Cache for 30 minutes
156
+        $response->cacheFor(1800);
157
+        return $response;
158
+    }
159
+
160
+    /**
161
+     * @NoAdminRequired
162
+     *
163
+     * @param string $path
164
+     * @return JSONResponse
165
+     */
166
+    public function postAvatar($path) {
167
+        $files = $this->request->getUploadedFile('files');
168
+
169
+        if (isset($path)) {
170
+            $path = stripslashes($path);
171
+            $userFolder = $this->rootFolder->getUserFolder($this->userId);
172
+            /** @var File $node */
173
+            $node = $userFolder->get($path);
174
+            if (!($node instanceof File)) {
175
+                return new JSONResponse(['data' => ['message' => $this->l->t('Please select a file.')]]);
176
+            }
177
+            if ($node->getSize() > 20*1024*1024) {
178
+                return new JSONResponse(
179
+                    ['data' => ['message' => $this->l->t('File is too big')]],
180
+                    Http::STATUS_BAD_REQUEST
181
+                );
182
+            }
183
+
184
+            if ($node->getMimeType() !== 'image/jpeg' && $node->getMimeType() !== 'image/png') {
185
+                return new JSONResponse(
186
+                    ['data' => ['message' => $this->l->t('The selected file is not an image.')]],
187
+                    Http::STATUS_BAD_REQUEST
188
+                );
189
+            }
190
+
191
+            try {
192
+                $content = $node->getContent();
193
+            } catch (\OCP\Files\NotPermittedException $e) {
194
+                return new JSONResponse(
195
+                    ['data' => ['message' => $this->l->t('The selected file cannot be read.')]],
196
+                    Http::STATUS_BAD_REQUEST
197
+                );
198
+            }
199
+        } elseif (!is_null($files)) {
200
+            if (
201
+                $files['error'][0] === 0 &&
202
+                 is_uploaded_file($files['tmp_name'][0]) &&
203
+                !\OC\Files\Filesystem::isFileBlacklisted($files['tmp_name'][0])
204
+            ) {
205
+                if ($files['size'][0] > 20*1024*1024) {
206
+                    return new JSONResponse(
207
+                        ['data' => ['message' => $this->l->t('File is too big')]],
208
+                        Http::STATUS_BAD_REQUEST
209
+                    );
210
+                }
211
+                $this->cache->set('avatar_upload', file_get_contents($files['tmp_name'][0]), 7200);
212
+                $content = $this->cache->get('avatar_upload');
213
+                unlink($files['tmp_name'][0]);
214
+            } else {
215
+                return new JSONResponse(
216
+                    ['data' => ['message' => $this->l->t('Invalid file provided')]],
217
+                    Http::STATUS_BAD_REQUEST
218
+                );
219
+            }
220
+        } else {
221
+            //Add imgfile
222
+            return new JSONResponse(
223
+                ['data' => ['message' => $this->l->t('No image or file provided')]],
224
+                Http::STATUS_BAD_REQUEST
225
+            );
226
+        }
227
+
228
+        try {
229
+            $image = new \OC_Image();
230
+            $image->loadFromData($content);
231
+            $image->readExif($content);
232
+            $image->fixOrientation();
233
+
234
+            if ($image->valid()) {
235
+                $mimeType = $image->mimeType();
236
+                if ($mimeType !== 'image/jpeg' && $mimeType !== 'image/png') {
237
+                    return new JSONResponse(
238
+                        ['data' => ['message' => $this->l->t('Unknown filetype')]],
239
+                        Http::STATUS_OK
240
+                    );
241
+                }
242
+
243
+                $this->cache->set('tmpAvatar', $image->data(), 7200);
244
+                return new JSONResponse(
245
+                    ['data' => 'notsquare'],
246
+                    Http::STATUS_OK
247
+                );
248
+            } else {
249
+                return new JSONResponse(
250
+                    ['data' => ['message' => $this->l->t('Invalid image')]],
251
+                    Http::STATUS_OK
252
+                );
253
+            }
254
+        } catch (\Exception $e) {
255
+            $this->logger->logException($e, ['app' => 'core']);
256
+            return new JSONResponse(['data' => ['message' => $this->l->t('An error occurred. Please contact your admin.')]], Http::STATUS_OK);
257
+        }
258
+    }
259
+
260
+    /**
261
+     * @NoAdminRequired
262
+     *
263
+     * @return JSONResponse
264
+     */
265
+    public function deleteAvatar() {
266
+        try {
267
+            $avatar = $this->avatarManager->getAvatar($this->userId);
268
+            $avatar->remove();
269
+            return new JSONResponse();
270
+        } catch (\Exception $e) {
271
+            $this->logger->logException($e, ['app' => 'core']);
272
+            return new JSONResponse(['data' => ['message' => $this->l->t('An error occurred. Please contact your admin.')]], Http::STATUS_BAD_REQUEST);
273
+        }
274
+    }
275
+
276
+    /**
277
+     * @NoAdminRequired
278
+     *
279
+     * @return JSONResponse|DataDisplayResponse
280
+     */
281
+    public function getTmpAvatar() {
282
+        $tmpAvatar = $this->cache->get('tmpAvatar');
283
+        if (is_null($tmpAvatar)) {
284
+            return new JSONResponse(['data' => [
285
+                                        'message' => $this->l->t("No temporary profile picture available, try again")
286
+                                    ]],
287
+                                    Http::STATUS_NOT_FOUND);
288
+        }
289
+
290
+        $image = new \OC_Image();
291
+        $image->loadFromData($tmpAvatar);
292
+
293
+        $resp = new DataDisplayResponse($image->data(),
294
+                Http::STATUS_OK,
295
+                ['Content-Type' => $image->mimeType()]);
296
+
297
+        $resp->setETag((string)crc32($image->data()));
298
+        $resp->cacheFor(0);
299
+        $resp->setLastModified(new \DateTime('now', new \DateTimeZone('GMT')));
300
+        return $resp;
301
+    }
302
+
303
+    /**
304
+     * @NoAdminRequired
305
+     *
306
+     * @param array $crop
307
+     * @return JSONResponse
308
+     */
309
+    public function postCroppedAvatar($crop) {
310
+        if (is_null($crop)) {
311
+            return new JSONResponse(['data' => ['message' => $this->l->t("No crop data provided")]],
312
+                                    Http::STATUS_BAD_REQUEST);
313
+        }
314
+
315
+        if (!isset($crop['x'], $crop['y'], $crop['w'], $crop['h'])) {
316
+            return new JSONResponse(['data' => ['message' => $this->l->t("No valid crop data provided")]],
317
+                                    Http::STATUS_BAD_REQUEST);
318
+        }
319
+
320
+        $tmpAvatar = $this->cache->get('tmpAvatar');
321
+        if (is_null($tmpAvatar)) {
322
+            return new JSONResponse(['data' => [
323
+                                        'message' => $this->l->t("No temporary profile picture available, try again")
324
+                                    ]],
325
+                                    Http::STATUS_BAD_REQUEST);
326
+        }
327
+
328
+        $image = new \OC_Image();
329
+        $image->loadFromData($tmpAvatar);
330
+        $image->crop($crop['x'], $crop['y'], (int)round($crop['w']), (int)round($crop['h']));
331
+        try {
332
+            $avatar = $this->avatarManager->getAvatar($this->userId);
333
+            $avatar->set($image);
334
+            // Clean up
335
+            $this->cache->remove('tmpAvatar');
336
+            return new JSONResponse(['status' => 'success']);
337
+        } catch (\OC\NotSquareException $e) {
338
+            return new JSONResponse(['data' => ['message' => $this->l->t('Crop is not square')]],
339
+                                    Http::STATUS_BAD_REQUEST);
340
+        } catch (\Exception $e) {
341
+            $this->logger->logException($e, ['app' => 'core']);
342
+            return new JSONResponse(['data' => ['message' => $this->l->t('An error occurred. Please contact your admin.')]], Http::STATUS_BAD_REQUEST);
343
+        }
344
+    }
345 345
 }
Please login to merge, or discard this patch.