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