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