Passed
Push — master ( 645109...008e6d )
by Christoph
12:14 queued 12s
created
lib/private/DateTimeZone.php 1 patch
Indentation   +86 added lines, -86 removed lines patch added patch discarded remove patch
@@ -30,100 +30,100 @@
 block discarded – undo
30 30
 use OCP\ISession;
31 31
 
32 32
 class DateTimeZone implements IDateTimeZone {
33
-	/** @var IConfig */
34
-	protected $config;
33
+    /** @var IConfig */
34
+    protected $config;
35 35
 
36
-	/** @var ISession */
37
-	protected $session;
36
+    /** @var ISession */
37
+    protected $session;
38 38
 
39
-	/**
40
-	 * Constructor
41
-	 *
42
-	 * @param IConfig $config
43
-	 * @param ISession $session
44
-	 */
45
-	public function __construct(IConfig $config, ISession $session) {
46
-		$this->config = $config;
47
-		$this->session = $session;
48
-	}
39
+    /**
40
+     * Constructor
41
+     *
42
+     * @param IConfig $config
43
+     * @param ISession $session
44
+     */
45
+    public function __construct(IConfig $config, ISession $session) {
46
+        $this->config = $config;
47
+        $this->session = $session;
48
+    }
49 49
 
50
-	/**
51
-	 * Get the timezone of the current user, based on his session information and config data
52
-	 *
53
-	 * @param bool|int $timestamp
54
-	 * @return \DateTimeZone
55
-	 */
56
-	public function getTimeZone($timestamp = false) {
57
-		$timeZone = $this->config->getUserValue($this->session->get('user_id'), 'core', 'timezone', null);
58
-		if ($timeZone === null) {
59
-			if ($this->session->exists('timezone')) {
60
-				return $this->guessTimeZoneFromOffset($this->session->get('timezone'), $timestamp);
61
-			}
62
-			$timeZone = $this->getDefaultTimeZone();
63
-		}
50
+    /**
51
+     * Get the timezone of the current user, based on his session information and config data
52
+     *
53
+     * @param bool|int $timestamp
54
+     * @return \DateTimeZone
55
+     */
56
+    public function getTimeZone($timestamp = false) {
57
+        $timeZone = $this->config->getUserValue($this->session->get('user_id'), 'core', 'timezone', null);
58
+        if ($timeZone === null) {
59
+            if ($this->session->exists('timezone')) {
60
+                return $this->guessTimeZoneFromOffset($this->session->get('timezone'), $timestamp);
61
+            }
62
+            $timeZone = $this->getDefaultTimeZone();
63
+        }
64 64
 
65
-		try {
66
-			return new \DateTimeZone($timeZone);
67
-		} catch (\Exception $e) {
68
-			\OCP\Util::writeLog('datetimezone', 'Failed to created DateTimeZone "' . $timeZone . "'", ILogger::DEBUG);
69
-			return new \DateTimeZone($this->getDefaultTimeZone());
70
-		}
71
-	}
65
+        try {
66
+            return new \DateTimeZone($timeZone);
67
+        } catch (\Exception $e) {
68
+            \OCP\Util::writeLog('datetimezone', 'Failed to created DateTimeZone "' . $timeZone . "'", ILogger::DEBUG);
69
+            return new \DateTimeZone($this->getDefaultTimeZone());
70
+        }
71
+    }
72 72
 
73
-	/**
74
-	 * Guess the DateTimeZone for a given offset
75
-	 *
76
-	 * We first try to find a Etc/GMT* timezone, if that does not exist,
77
-	 * we try to find it manually, before falling back to UTC.
78
-	 *
79
-	 * @param mixed $offset
80
-	 * @param bool|int $timestamp
81
-	 * @return \DateTimeZone
82
-	 */
83
-	protected function guessTimeZoneFromOffset($offset, $timestamp) {
84
-		try {
85
-			// Note: the timeZone name is the inverse to the offset,
86
-			// so a positive offset means negative timeZone
87
-			// and the other way around.
88
-			if ($offset > 0) {
89
-				$timeZone = 'Etc/GMT-' . $offset;
90
-			} else {
91
-				$timeZone = 'Etc/GMT+' . abs($offset);
92
-			}
73
+    /**
74
+     * Guess the DateTimeZone for a given offset
75
+     *
76
+     * We first try to find a Etc/GMT* timezone, if that does not exist,
77
+     * we try to find it manually, before falling back to UTC.
78
+     *
79
+     * @param mixed $offset
80
+     * @param bool|int $timestamp
81
+     * @return \DateTimeZone
82
+     */
83
+    protected function guessTimeZoneFromOffset($offset, $timestamp) {
84
+        try {
85
+            // Note: the timeZone name is the inverse to the offset,
86
+            // so a positive offset means negative timeZone
87
+            // and the other way around.
88
+            if ($offset > 0) {
89
+                $timeZone = 'Etc/GMT-' . $offset;
90
+            } else {
91
+                $timeZone = 'Etc/GMT+' . abs($offset);
92
+            }
93 93
 
94
-			return new \DateTimeZone($timeZone);
95
-		} catch (\Exception $e) {
96
-			// If the offset has no Etc/GMT* timezone,
97
-			// we try to guess one timezone that has the same offset
98
-			foreach (\DateTimeZone::listIdentifiers() as $timeZone) {
99
-				$dtz = new \DateTimeZone($timeZone);
100
-				$dateTime = new \DateTime();
94
+            return new \DateTimeZone($timeZone);
95
+        } catch (\Exception $e) {
96
+            // If the offset has no Etc/GMT* timezone,
97
+            // we try to guess one timezone that has the same offset
98
+            foreach (\DateTimeZone::listIdentifiers() as $timeZone) {
99
+                $dtz = new \DateTimeZone($timeZone);
100
+                $dateTime = new \DateTime();
101 101
 
102
-				if ($timestamp !== false) {
103
-					$dateTime->setTimestamp($timestamp);
104
-				}
102
+                if ($timestamp !== false) {
103
+                    $dateTime->setTimestamp($timestamp);
104
+                }
105 105
 
106
-				$dtOffset = $dtz->getOffset($dateTime);
107
-				if ($dtOffset == 3600 * $offset) {
108
-					return $dtz;
109
-				}
110
-			}
106
+                $dtOffset = $dtz->getOffset($dateTime);
107
+                if ($dtOffset == 3600 * $offset) {
108
+                    return $dtz;
109
+                }
110
+            }
111 111
 
112
-			// No timezone found, fallback to UTC
113
-			\OCP\Util::writeLog('datetimezone', 'Failed to find DateTimeZone for offset "' . $offset . "'", ILogger::DEBUG);
114
-			return new \DateTimeZone($this->getDefaultTimeZone());
115
-		}
116
-	}
112
+            // No timezone found, fallback to UTC
113
+            \OCP\Util::writeLog('datetimezone', 'Failed to find DateTimeZone for offset "' . $offset . "'", ILogger::DEBUG);
114
+            return new \DateTimeZone($this->getDefaultTimeZone());
115
+        }
116
+    }
117 117
 
118
-	/**
119
-	 * Get the default timezone of the server
120
-	 *
121
-	 * Falls back to UTC if it is not yet set.
122
-	 *
123
-	 * @return string
124
-	 */
125
-	protected function getDefaultTimeZone() {
126
-		$serverTimeZone = date_default_timezone_get();
127
-		return $serverTimeZone ?: 'UTC';
128
-	}
118
+    /**
119
+     * Get the default timezone of the server
120
+     *
121
+     * Falls back to UTC if it is not yet set.
122
+     *
123
+     * @return string
124
+     */
125
+    protected function getDefaultTimeZone() {
126
+        $serverTimeZone = date_default_timezone_get();
127
+        return $serverTimeZone ?: 'UTC';
128
+    }
129 129
 }
Please login to merge, or discard this patch.
lib/private/Tags.php 1 patch
Indentation   +805 added lines, -805 removed lines patch added patch discarded remove patch
@@ -54,809 +54,809 @@
 block discarded – undo
54 54
 
55 55
 class Tags implements ITags {
56 56
 
57
-	/**
58
-	 * Tags
59
-	 *
60
-	 * @var array
61
-	 */
62
-	private $tags = [];
63
-
64
-	/**
65
-	 * Used for storing objectid/categoryname pairs while rescanning.
66
-	 *
67
-	 * @var array
68
-	 */
69
-	private static $relations = [];
70
-
71
-	/**
72
-	 * Type
73
-	 *
74
-	 * @var string
75
-	 */
76
-	private $type;
77
-
78
-	/**
79
-	 * User
80
-	 *
81
-	 * @var string
82
-	 */
83
-	private $user;
84
-
85
-	/**
86
-	 * Are we including tags for shared items?
87
-	 *
88
-	 * @var bool
89
-	 */
90
-	private $includeShared = false;
91
-
92
-	/**
93
-	 * The current user, plus any owners of the items shared with the current
94
-	 * user, if $this->includeShared === true.
95
-	 *
96
-	 * @var array
97
-	 */
98
-	private $owners = [];
99
-
100
-	/**
101
-	 * The Mapper we're using to communicate our Tag objects to the database.
102
-	 *
103
-	 * @var TagMapper
104
-	 */
105
-	private $mapper;
106
-
107
-	/**
108
-	 * The sharing backend for objects of $this->type. Required if
109
-	 * $this->includeShared === true to determine ownership of items.
110
-	 *
111
-	 * @var \OCP\Share_Backend
112
-	 */
113
-	private $backend;
114
-
115
-	const TAG_TABLE = '*PREFIX*vcategory';
116
-	const RELATION_TABLE = '*PREFIX*vcategory_to_object';
117
-
118
-	/**
119
-	 * Constructor.
120
-	 *
121
-	 * @param TagMapper $mapper Instance of the TagMapper abstraction layer.
122
-	 * @param string $user The user whose data the object will operate on.
123
-	 * @param string $type The type of items for which tags will be loaded.
124
-	 * @param array $defaultTags Tags that should be created at construction.
125
-	 * @param boolean $includeShared Whether to include tags for items shared with this user by others.
126
-	 */
127
-	public function __construct(TagMapper $mapper, $user, $type, $defaultTags = [], $includeShared = false) {
128
-		$this->mapper = $mapper;
129
-		$this->user = $user;
130
-		$this->type = $type;
131
-		$this->includeShared = $includeShared;
132
-		$this->owners = [$this->user];
133
-		if ($this->includeShared) {
134
-			$this->owners = array_merge($this->owners, \OC\Share\Share::getSharedItemsOwners($this->user, $this->type, true));
135
-			$this->backend = \OC\Share\Share::getBackend($this->type);
136
-		}
137
-		$this->tags = $this->mapper->loadTags($this->owners, $this->type);
138
-
139
-		if(count($defaultTags) > 0 && count($this->tags) === 0) {
140
-			$this->addMultiple($defaultTags, true);
141
-		}
142
-	}
143
-
144
-	/**
145
-	 * Check if any tags are saved for this type and user.
146
-	 *
147
-	 * @return boolean
148
-	 */
149
-	public function isEmpty() {
150
-		return count($this->tags) === 0;
151
-	}
152
-
153
-	/**
154
-	 * Returns an array mapping a given tag's properties to its values:
155
-	 * ['id' => 0, 'name' = 'Tag', 'owner' = 'User', 'type' => 'tagtype']
156
-	 *
157
-	 * @param string $id The ID of the tag that is going to be mapped
158
-	 * @return array|false
159
-	 */
160
-	public function getTag($id) {
161
-		$key = $this->getTagById($id);
162
-		if ($key !== false) {
163
-			return $this->tagMap($this->tags[$key]);
164
-		}
165
-		return false;
166
-	}
167
-
168
-	/**
169
-	 * Get the tags for a specific user.
170
-	 *
171
-	 * This returns an array with maps containing each tag's properties:
172
-	 * [
173
-	 * 	['id' => 0, 'name' = 'First tag', 'owner' = 'User', 'type' => 'tagtype'],
174
-	 * 	['id' => 1, 'name' = 'Shared tag', 'owner' = 'Other user', 'type' => 'tagtype'],
175
-	 * ]
176
-	 *
177
-	 * @return array
178
-	 */
179
-	public function getTags() {
180
-		if(!count($this->tags)) {
181
-			return [];
182
-		}
183
-
184
-		usort($this->tags, function ($a, $b) {
185
-			return strnatcasecmp($a->getName(), $b->getName());
186
-		});
187
-		$tagMap = [];
188
-
189
-		foreach($this->tags as $tag) {
190
-			if($tag->getName() !== ITags::TAG_FAVORITE) {
191
-				$tagMap[] = $this->tagMap($tag);
192
-			}
193
-		}
194
-		return $tagMap;
195
-
196
-	}
197
-
198
-	/**
199
-	 * Return only the tags owned by the given user, omitting any tags shared
200
-	 * by other users.
201
-	 *
202
-	 * @param string $user The user whose tags are to be checked.
203
-	 * @return array An array of Tag objects.
204
-	 */
205
-	public function getTagsForUser($user) {
206
-		return array_filter($this->tags,
207
-			function ($tag) use ($user) {
208
-				return $tag->getOwner() === $user;
209
-			}
210
-		);
211
-	}
212
-
213
-	/**
214
-	 * Get the list of tags for the given ids.
215
-	 *
216
-	 * @param array $objIds array of object ids
217
-	 * @return array|boolean of tags id as key to array of tag names
218
-	 * or false if an error occurred
219
-	 */
220
-	public function getTagsForObjects(array $objIds) {
221
-		$entries = [];
222
-
223
-		try {
224
-			$conn = \OC::$server->getDatabaseConnection();
225
-			$chunks = array_chunk($objIds, 900, false);
226
-			foreach ($chunks as $chunk) {
227
-				$result = $conn->executeQuery(
228
-					'SELECT `category`, `categoryid`, `objid` ' .
229
-					'FROM `' . self::RELATION_TABLE . '` r, `' . self::TAG_TABLE . '` ' .
230
-					'WHERE `categoryid` = `id` AND `uid` = ? AND r.`type` = ? AND `objid` IN (?)',
231
-					[$this->user, $this->type, $chunk],
232
-					[null, null, IQueryBuilder::PARAM_INT_ARRAY]
233
-				);
234
-				while ($row = $result->fetch()) {
235
-					$objId = (int)$row['objid'];
236
-					if (!isset($entries[$objId])) {
237
-						$entries[$objId] = [];
238
-					}
239
-					$entries[$objId][] = $row['category'];
240
-				}
241
-				if ($result === null) {
242
-					\OCP\Util::writeLog('core', __METHOD__. 'DB error: ' . \OC::$server->getDatabaseConnection()->getError(), ILogger::ERROR);
243
-					return false;
244
-				}
245
-			}
246
-		} catch(\Exception $e) {
247
-			\OC::$server->getLogger()->logException($e, [
248
-				'message' => __METHOD__,
249
-				'level' => ILogger::ERROR,
250
-				'app' => 'core',
251
-			]);
252
-			return false;
253
-		}
254
-
255
-		return $entries;
256
-	}
257
-
258
-	/**
259
-	 * Get the a list if items tagged with $tag.
260
-	 *
261
-	 * Throws an exception if the tag could not be found.
262
-	 *
263
-	 * @param string $tag Tag id or name.
264
-	 * @return array|false An array of object ids or false on error.
265
-	 * @throws \Exception
266
-	 */
267
-	public function getIdsForTag($tag) {
268
-		$result = null;
269
-		$tagId = false;
270
-		if(is_numeric($tag)) {
271
-			$tagId = $tag;
272
-		} elseif(is_string($tag)) {
273
-			$tag = trim($tag);
274
-			if($tag === '') {
275
-				\OCP\Util::writeLog('core', __METHOD__.', Cannot use empty tag names', ILogger::DEBUG);
276
-				return false;
277
-			}
278
-			$tagId = $this->getTagId($tag);
279
-		}
280
-
281
-		if($tagId === false) {
282
-			$l10n = \OC::$server->getL10N('core');
283
-			throw new \Exception(
284
-				$l10n->t('Could not find category "%s"', [$tag])
285
-			);
286
-		}
287
-
288
-		$ids = [];
289
-		$sql = 'SELECT `objid` FROM `' . self::RELATION_TABLE
290
-			. '` WHERE `categoryid` = ?';
291
-
292
-		try {
293
-			$stmt = \OC_DB::prepare($sql);
294
-			$result = $stmt->execute([$tagId]);
295
-			if ($result === null) {
296
-				\OCP\Util::writeLog('core', __METHOD__. 'DB error: ' . \OC::$server->getDatabaseConnection()->getError(), ILogger::ERROR);
297
-				return false;
298
-			}
299
-		} catch(\Exception $e) {
300
-			\OC::$server->getLogger()->logException($e, [
301
-				'message' => __METHOD__,
302
-				'level' => ILogger::ERROR,
303
-				'app' => 'core',
304
-			]);
305
-			return false;
306
-		}
307
-
308
-		if(!is_null($result)) {
309
-			while($row = $result->fetchRow()) {
310
-				$id = (int)$row['objid'];
311
-
312
-				if ($this->includeShared) {
313
-					// We have to check if we are really allowed to access the
314
-					// items that are tagged with $tag. To that end, we ask the
315
-					// corresponding sharing backend if the item identified by $id
316
-					// is owned by any of $this->owners.
317
-					foreach ($this->owners as $owner) {
318
-						if ($this->backend->isValidSource($id, $owner)) {
319
-							$ids[] = $id;
320
-							break;
321
-						}
322
-					}
323
-				} else {
324
-					$ids[] = $id;
325
-				}
326
-			}
327
-		}
328
-
329
-		return $ids;
330
-	}
331
-
332
-	/**
333
-	 * Checks whether a tag is saved for the given user,
334
-	 * disregarding the ones shared with him or her.
335
-	 *
336
-	 * @param string $name The tag name to check for.
337
-	 * @param string $user The user whose tags are to be checked.
338
-	 * @return bool
339
-	 */
340
-	public function userHasTag($name, $user) {
341
-		$key = $this->array_searchi($name, $this->getTagsForUser($user));
342
-		return ($key !== false) ? $this->tags[$key]->getId() : false;
343
-	}
344
-
345
-	/**
346
-	 * Checks whether a tag is saved for or shared with the current user.
347
-	 *
348
-	 * @param string $name The tag name to check for.
349
-	 * @return bool
350
-	 */
351
-	public function hasTag($name) {
352
-		return $this->getTagId($name) !== false;
353
-	}
354
-
355
-	/**
356
-	 * Add a new tag.
357
-	 *
358
-	 * @param string $name A string with a name of the tag
359
-	 * @return false|int the id of the added tag or false on error.
360
-	 */
361
-	public function add($name) {
362
-		$name = trim($name);
363
-
364
-		if($name === '') {
365
-			\OCP\Util::writeLog('core', __METHOD__.', Cannot add an empty tag', ILogger::DEBUG);
366
-			return false;
367
-		}
368
-		if($this->userHasTag($name, $this->user)) {
369
-			\OCP\Util::writeLog('core', __METHOD__.', name: ' . $name. ' exists already', ILogger::DEBUG);
370
-			return false;
371
-		}
372
-		try {
373
-			$tag = new Tag($this->user, $this->type, $name);
374
-			$tag = $this->mapper->insert($tag);
375
-			$this->tags[] = $tag;
376
-		} catch(\Exception $e) {
377
-			\OC::$server->getLogger()->logException($e, [
378
-				'message' => __METHOD__,
379
-				'level' => ILogger::ERROR,
380
-				'app' => 'core',
381
-			]);
382
-			return false;
383
-		}
384
-		\OCP\Util::writeLog('core', __METHOD__.', id: ' . $tag->getId(), ILogger::DEBUG);
385
-		return $tag->getId();
386
-	}
387
-
388
-	/**
389
-	 * Rename tag.
390
-	 *
391
-	 * @param string|integer $from The name or ID of the existing tag
392
-	 * @param string $to The new name of the tag.
393
-	 * @return bool
394
-	 */
395
-	public function rename($from, $to) {
396
-		$from = trim($from);
397
-		$to = trim($to);
398
-
399
-		if($to === '' || $from === '') {
400
-			\OCP\Util::writeLog('core', __METHOD__.', Cannot use empty tag names', ILogger::DEBUG);
401
-			return false;
402
-		}
403
-
404
-		if (is_numeric($from)) {
405
-			$key = $this->getTagById($from);
406
-		} else {
407
-			$key = $this->getTagByName($from);
408
-		}
409
-		if($key === false) {
410
-			\OCP\Util::writeLog('core', __METHOD__.', tag: ' . $from. ' does not exist', ILogger::DEBUG);
411
-			return false;
412
-		}
413
-		$tag = $this->tags[$key];
414
-
415
-		if($this->userHasTag($to, $tag->getOwner())) {
416
-			\OCP\Util::writeLog('core', __METHOD__.', A tag named ' . $to. ' already exists for user ' . $tag->getOwner() . '.', ILogger::DEBUG);
417
-			return false;
418
-		}
419
-
420
-		try {
421
-			$tag->setName($to);
422
-			$this->tags[$key] = $this->mapper->update($tag);
423
-		} catch(\Exception $e) {
424
-			\OC::$server->getLogger()->logException($e, [
425
-				'message' => __METHOD__,
426
-				'level' => ILogger::ERROR,
427
-				'app' => 'core',
428
-			]);
429
-			return false;
430
-		}
431
-		return true;
432
-	}
433
-
434
-	/**
435
-	 * Add a list of new tags.
436
-	 *
437
-	 * @param string[] $names A string with a name or an array of strings containing
438
-	 * the name(s) of the tag(s) to add.
439
-	 * @param bool $sync When true, save the tags
440
-	 * @param int|null $id int Optional object id to add to this|these tag(s)
441
-	 * @return bool Returns false on error.
442
-	 */
443
-	public function addMultiple($names, $sync=false, $id = null) {
444
-		if(!is_array($names)) {
445
-			$names = [$names];
446
-		}
447
-		$names = array_map('trim', $names);
448
-		array_filter($names);
449
-
450
-		$newones = [];
451
-		foreach($names as $name) {
452
-			if(!$this->hasTag($name) && $name !== '') {
453
-				$newones[] = new Tag($this->user, $this->type, $name);
454
-			}
455
-			if(!is_null($id)) {
456
-				// Insert $objectid, $categoryid  pairs if not exist.
457
-				self::$relations[] = ['objid' => $id, 'tag' => $name];
458
-			}
459
-		}
460
-		$this->tags = array_merge($this->tags, $newones);
461
-		if($sync === true) {
462
-			$this->save();
463
-		}
464
-
465
-		return true;
466
-	}
467
-
468
-	/**
469
-	 * Save the list of tags and their object relations
470
-	 */
471
-	protected function save() {
472
-		if(is_array($this->tags)) {
473
-			foreach($this->tags as $tag) {
474
-				try {
475
-					if (!$this->mapper->tagExists($tag)) {
476
-						$this->mapper->insert($tag);
477
-					}
478
-				} catch(\Exception $e) {
479
-					\OC::$server->getLogger()->logException($e, [
480
-						'message' => __METHOD__,
481
-						'level' => ILogger::ERROR,
482
-						'app' => 'core',
483
-					]);
484
-				}
485
-			}
486
-
487
-			// reload tags to get the proper ids.
488
-			$this->tags = $this->mapper->loadTags($this->owners, $this->type);
489
-			\OCP\Util::writeLog('core', __METHOD__.', tags: ' . print_r($this->tags, true),
490
-				ILogger::DEBUG);
491
-			// Loop through temporarily cached objectid/tagname pairs
492
-			// and save relations.
493
-			$tags = $this->tags;
494
-			// For some reason this is needed or array_search(i) will return 0..?
495
-			ksort($tags);
496
-			$dbConnection = \OC::$server->getDatabaseConnection();
497
-			foreach(self::$relations as $relation) {
498
-				$tagId = $this->getTagId($relation['tag']);
499
-				\OCP\Util::writeLog('core', __METHOD__ . 'catid, ' . $relation['tag'] . ' ' . $tagId, ILogger::DEBUG);
500
-				if($tagId) {
501
-					try {
502
-						$dbConnection->insertIfNotExist(self::RELATION_TABLE,
503
-							[
504
-								'objid' => $relation['objid'],
505
-								'categoryid' => $tagId,
506
-								'type' => $this->type,
507
-							]);
508
-					} catch(\Exception $e) {
509
-						\OC::$server->getLogger()->logException($e, [
510
-							'message' => __METHOD__,
511
-							'level' => ILogger::ERROR,
512
-							'app' => 'core',
513
-						]);
514
-					}
515
-				}
516
-			}
517
-			self::$relations = []; // reset
518
-		} else {
519
-			\OCP\Util::writeLog('core', __METHOD__.', $this->tags is not an array! '
520
-				. print_r($this->tags, true), ILogger::ERROR);
521
-		}
522
-	}
523
-
524
-	/**
525
-	 * Delete tags and tag/object relations for a user.
526
-	 *
527
-	 * For hooking up on post_deleteUser
528
-	 *
529
-	 * @param array $arguments
530
-	 */
531
-	public static function post_deleteUser($arguments) {
532
-		// Find all objectid/tagId pairs.
533
-		$result = null;
534
-		try {
535
-			$stmt = \OC_DB::prepare('SELECT `id` FROM `' . self::TAG_TABLE . '` '
536
-				. 'WHERE `uid` = ?');
537
-			$result = $stmt->execute([$arguments['uid']]);
538
-			if ($result === null) {
539
-				\OCP\Util::writeLog('core', __METHOD__. 'DB error: ' . \OC::$server->getDatabaseConnection()->getError(), ILogger::ERROR);
540
-			}
541
-		} catch(\Exception $e) {
542
-			\OC::$server->getLogger()->logException($e, [
543
-				'message' => __METHOD__,
544
-				'level' => ILogger::ERROR,
545
-				'app' => 'core',
546
-			]);
547
-		}
548
-
549
-		if(!is_null($result)) {
550
-			try {
551
-				$stmt = \OC_DB::prepare('DELETE FROM `' . self::RELATION_TABLE . '` '
552
-					. 'WHERE `categoryid` = ?');
553
-				while($row = $result->fetchRow()) {
554
-					try {
555
-						$stmt->execute([$row['id']]);
556
-					} catch(\Exception $e) {
557
-						\OC::$server->getLogger()->logException($e, [
558
-							'message' => __METHOD__,
559
-							'level' => ILogger::ERROR,
560
-							'app' => 'core',
561
-						]);
562
-					}
563
-				}
564
-			} catch(\Exception $e) {
565
-				\OC::$server->getLogger()->logException($e, [
566
-					'message' => __METHOD__,
567
-					'level' => ILogger::ERROR,
568
-					'app' => 'core',
569
-				]);
570
-			}
571
-		}
572
-		try {
573
-			$stmt = \OC_DB::prepare('DELETE FROM `' . self::TAG_TABLE . '` '
574
-				. 'WHERE `uid` = ?');
575
-			$result = $stmt->execute([$arguments['uid']]);
576
-			if ($result === null) {
577
-				\OCP\Util::writeLog('core', __METHOD__. ', DB error: ' . \OC::$server->getDatabaseConnection()->getError(), ILogger::ERROR);
578
-			}
579
-		} catch(\Exception $e) {
580
-			\OC::$server->getLogger()->logException($e, [
581
-				'message' => __METHOD__,
582
-				'level' => ILogger::ERROR,
583
-				'app' => 'core',
584
-			]);
585
-		}
586
-	}
587
-
588
-	/**
589
-	 * Delete tag/object relations from the db
590
-	 *
591
-	 * @param array $ids The ids of the objects
592
-	 * @return boolean Returns false on error.
593
-	 */
594
-	public function purgeObjects(array $ids) {
595
-		if(count($ids) === 0) {
596
-			// job done ;)
597
-			return true;
598
-		}
599
-		$updates = $ids;
600
-		try {
601
-			$query = 'DELETE FROM `' . self::RELATION_TABLE . '` ';
602
-			$query .= 'WHERE `objid` IN (' . str_repeat('?,', count($ids)-1) . '?) ';
603
-			$query .= 'AND `type`= ?';
604
-			$updates[] = $this->type;
605
-			$stmt = \OC_DB::prepare($query);
606
-			$result = $stmt->execute($updates);
607
-			if ($result === null) {
608
-				\OCP\Util::writeLog('core', __METHOD__. 'DB error: ' . \OC::$server->getDatabaseConnection()->getError(), ILogger::ERROR);
609
-				return false;
610
-			}
611
-		} catch(\Exception $e) {
612
-			\OC::$server->getLogger()->logException($e, [
613
-				'message' => __METHOD__,
614
-				'level' => ILogger::ERROR,
615
-				'app' => 'core',
616
-			]);
617
-			return false;
618
-		}
619
-		return true;
620
-	}
621
-
622
-	/**
623
-	 * Get favorites for an object type
624
-	 *
625
-	 * @return array|false An array of object ids.
626
-	 */
627
-	public function getFavorites() {
628
-		if(!$this->userHasTag(ITags::TAG_FAVORITE, $this->user)) {
629
-			return [];
630
-		}
631
-
632
-		try {
633
-			return $this->getIdsForTag(ITags::TAG_FAVORITE);
634
-		} catch(\Exception $e) {
635
-			\OC::$server->getLogger()->logException($e, [
636
-				'message' => __METHOD__,
637
-				'level' => ILogger::ERROR,
638
-				'app' => 'core',
639
-			]);
640
-			return [];
641
-		}
642
-	}
643
-
644
-	/**
645
-	 * Add an object to favorites
646
-	 *
647
-	 * @param int $objid The id of the object
648
-	 * @return boolean
649
-	 */
650
-	public function addToFavorites($objid) {
651
-		if(!$this->userHasTag(ITags::TAG_FAVORITE, $this->user)) {
652
-			$this->add(ITags::TAG_FAVORITE);
653
-		}
654
-		return $this->tagAs($objid, ITags::TAG_FAVORITE);
655
-	}
656
-
657
-	/**
658
-	 * Remove an object from favorites
659
-	 *
660
-	 * @param int $objid The id of the object
661
-	 * @return boolean
662
-	 */
663
-	public function removeFromFavorites($objid) {
664
-		return $this->unTag($objid, ITags::TAG_FAVORITE);
665
-	}
666
-
667
-	/**
668
-	 * Creates a tag/object relation.
669
-	 *
670
-	 * @param int $objid The id of the object
671
-	 * @param string $tag The id or name of the tag
672
-	 * @return boolean Returns false on error.
673
-	 */
674
-	public function tagAs($objid, $tag) {
675
-		if(is_string($tag) && !is_numeric($tag)) {
676
-			$tag = trim($tag);
677
-			if($tag === '') {
678
-				\OCP\Util::writeLog('core', __METHOD__.', Cannot add an empty tag', ILogger::DEBUG);
679
-				return false;
680
-			}
681
-			if(!$this->hasTag($tag)) {
682
-				$this->add($tag);
683
-			}
684
-			$tagId =  $this->getTagId($tag);
685
-		} else {
686
-			$tagId = $tag;
687
-		}
688
-		try {
689
-			\OC::$server->getDatabaseConnection()->insertIfNotExist(self::RELATION_TABLE,
690
-				[
691
-					'objid' => $objid,
692
-					'categoryid' => $tagId,
693
-					'type' => $this->type,
694
-				]);
695
-		} catch(\Exception $e) {
696
-			\OC::$server->getLogger()->logException($e, [
697
-				'message' => __METHOD__,
698
-				'level' => ILogger::ERROR,
699
-				'app' => 'core',
700
-			]);
701
-			return false;
702
-		}
703
-		return true;
704
-	}
705
-
706
-	/**
707
-	 * Delete single tag/object relation from the db
708
-	 *
709
-	 * @param int $objid The id of the object
710
-	 * @param string $tag The id or name of the tag
711
-	 * @return boolean
712
-	 */
713
-	public function unTag($objid, $tag) {
714
-		if(is_string($tag) && !is_numeric($tag)) {
715
-			$tag = trim($tag);
716
-			if($tag === '') {
717
-				\OCP\Util::writeLog('core', __METHOD__.', Tag name is empty', ILogger::DEBUG);
718
-				return false;
719
-			}
720
-			$tagId =  $this->getTagId($tag);
721
-		} else {
722
-			$tagId = $tag;
723
-		}
724
-
725
-		try {
726
-			$sql = 'DELETE FROM `' . self::RELATION_TABLE . '` '
727
-					. 'WHERE `objid` = ? AND `categoryid` = ? AND `type` = ?';
728
-			$stmt = \OC_DB::prepare($sql);
729
-			$stmt->execute([$objid, $tagId, $this->type]);
730
-		} catch(\Exception $e) {
731
-			\OC::$server->getLogger()->logException($e, [
732
-				'message' => __METHOD__,
733
-				'level' => ILogger::ERROR,
734
-				'app' => 'core',
735
-			]);
736
-			return false;
737
-		}
738
-		return true;
739
-	}
740
-
741
-	/**
742
-	 * Delete tags from the database.
743
-	 *
744
-	 * @param string[]|integer[] $names An array of tags (names or IDs) to delete
745
-	 * @return bool Returns false on error
746
-	 */
747
-	public function delete($names) {
748
-		if(!is_array($names)) {
749
-			$names = [$names];
750
-		}
751
-
752
-		$names = array_map('trim', $names);
753
-		array_filter($names);
754
-
755
-		\OCP\Util::writeLog('core', __METHOD__ . ', before: '
756
-			. print_r($this->tags, true), ILogger::DEBUG);
757
-		foreach($names as $name) {
758
-			$id = null;
759
-
760
-			if (is_numeric($name)) {
761
-				$key = $this->getTagById($name);
762
-			} else {
763
-				$key = $this->getTagByName($name);
764
-			}
765
-			if ($key !== false) {
766
-				$tag = $this->tags[$key];
767
-				$id = $tag->getId();
768
-				unset($this->tags[$key]);
769
-				$this->mapper->delete($tag);
770
-			} else {
771
-				\OCP\Util::writeLog('core', __METHOD__ . 'Cannot delete tag ' . $name
772
-					. ': not found.', ILogger::ERROR);
773
-			}
774
-			if(!is_null($id) && $id !== false) {
775
-				try {
776
-					$sql = 'DELETE FROM `' . self::RELATION_TABLE . '` '
777
-							. 'WHERE `categoryid` = ?';
778
-					$stmt = \OC_DB::prepare($sql);
779
-					$result = $stmt->execute([$id]);
780
-					if ($result === null) {
781
-						\OCP\Util::writeLog('core',
782
-							__METHOD__. 'DB error: ' . \OC::$server->getDatabaseConnection()->getError(),
783
-							ILogger::ERROR);
784
-						return false;
785
-					}
786
-				} catch(\Exception $e) {
787
-					\OC::$server->getLogger()->logException($e, [
788
-						'message' => __METHOD__,
789
-						'level' => ILogger::ERROR,
790
-						'app' => 'core',
791
-					]);
792
-					return false;
793
-				}
794
-			}
795
-		}
796
-		return true;
797
-	}
798
-
799
-	// case-insensitive array_search
800
-	protected function array_searchi($needle, $haystack, $mem='getName') {
801
-		if(!is_array($haystack)) {
802
-			return false;
803
-		}
804
-		return array_search(strtolower($needle), array_map(
805
-			function ($tag) use ($mem) {
806
-				return strtolower(call_user_func([$tag, $mem]));
807
-			}, $haystack)
808
-		);
809
-	}
810
-
811
-	/**
812
-	 * Get a tag's ID.
813
-	 *
814
-	 * @param string $name The tag name to look for.
815
-	 * @return string|bool The tag's id or false if no matching tag is found.
816
-	 */
817
-	private function getTagId($name) {
818
-		$key = $this->array_searchi($name, $this->tags);
819
-		if ($key !== false) {
820
-			return $this->tags[$key]->getId();
821
-		}
822
-		return false;
823
-	}
824
-
825
-	/**
826
-	 * Get a tag by its name.
827
-	 *
828
-	 * @param string $name The tag name.
829
-	 * @return integer|bool The tag object's offset within the $this->tags
830
-	 *                      array or false if it doesn't exist.
831
-	 */
832
-	private function getTagByName($name) {
833
-		return $this->array_searchi($name, $this->tags, 'getName');
834
-	}
835
-
836
-	/**
837
-	 * Get a tag by its ID.
838
-	 *
839
-	 * @param string $id The tag ID to look for.
840
-	 * @return integer|bool The tag object's offset within the $this->tags
841
-	 *                      array or false if it doesn't exist.
842
-	 */
843
-	private function getTagById($id) {
844
-		return $this->array_searchi($id, $this->tags, 'getId');
845
-	}
846
-
847
-	/**
848
-	 * Returns an array mapping a given tag's properties to its values:
849
-	 * ['id' => 0, 'name' = 'Tag', 'owner' = 'User', 'type' => 'tagtype']
850
-	 *
851
-	 * @param Tag $tag The tag that is going to be mapped
852
-	 * @return array
853
-	 */
854
-	private function tagMap(Tag $tag) {
855
-		return [
856
-			'id'    => $tag->getId(),
857
-			'name'  => $tag->getName(),
858
-			'owner' => $tag->getOwner(),
859
-			'type'  => $tag->getType()
860
-		];
861
-	}
57
+    /**
58
+     * Tags
59
+     *
60
+     * @var array
61
+     */
62
+    private $tags = [];
63
+
64
+    /**
65
+     * Used for storing objectid/categoryname pairs while rescanning.
66
+     *
67
+     * @var array
68
+     */
69
+    private static $relations = [];
70
+
71
+    /**
72
+     * Type
73
+     *
74
+     * @var string
75
+     */
76
+    private $type;
77
+
78
+    /**
79
+     * User
80
+     *
81
+     * @var string
82
+     */
83
+    private $user;
84
+
85
+    /**
86
+     * Are we including tags for shared items?
87
+     *
88
+     * @var bool
89
+     */
90
+    private $includeShared = false;
91
+
92
+    /**
93
+     * The current user, plus any owners of the items shared with the current
94
+     * user, if $this->includeShared === true.
95
+     *
96
+     * @var array
97
+     */
98
+    private $owners = [];
99
+
100
+    /**
101
+     * The Mapper we're using to communicate our Tag objects to the database.
102
+     *
103
+     * @var TagMapper
104
+     */
105
+    private $mapper;
106
+
107
+    /**
108
+     * The sharing backend for objects of $this->type. Required if
109
+     * $this->includeShared === true to determine ownership of items.
110
+     *
111
+     * @var \OCP\Share_Backend
112
+     */
113
+    private $backend;
114
+
115
+    const TAG_TABLE = '*PREFIX*vcategory';
116
+    const RELATION_TABLE = '*PREFIX*vcategory_to_object';
117
+
118
+    /**
119
+     * Constructor.
120
+     *
121
+     * @param TagMapper $mapper Instance of the TagMapper abstraction layer.
122
+     * @param string $user The user whose data the object will operate on.
123
+     * @param string $type The type of items for which tags will be loaded.
124
+     * @param array $defaultTags Tags that should be created at construction.
125
+     * @param boolean $includeShared Whether to include tags for items shared with this user by others.
126
+     */
127
+    public function __construct(TagMapper $mapper, $user, $type, $defaultTags = [], $includeShared = false) {
128
+        $this->mapper = $mapper;
129
+        $this->user = $user;
130
+        $this->type = $type;
131
+        $this->includeShared = $includeShared;
132
+        $this->owners = [$this->user];
133
+        if ($this->includeShared) {
134
+            $this->owners = array_merge($this->owners, \OC\Share\Share::getSharedItemsOwners($this->user, $this->type, true));
135
+            $this->backend = \OC\Share\Share::getBackend($this->type);
136
+        }
137
+        $this->tags = $this->mapper->loadTags($this->owners, $this->type);
138
+
139
+        if(count($defaultTags) > 0 && count($this->tags) === 0) {
140
+            $this->addMultiple($defaultTags, true);
141
+        }
142
+    }
143
+
144
+    /**
145
+     * Check if any tags are saved for this type and user.
146
+     *
147
+     * @return boolean
148
+     */
149
+    public function isEmpty() {
150
+        return count($this->tags) === 0;
151
+    }
152
+
153
+    /**
154
+     * Returns an array mapping a given tag's properties to its values:
155
+     * ['id' => 0, 'name' = 'Tag', 'owner' = 'User', 'type' => 'tagtype']
156
+     *
157
+     * @param string $id The ID of the tag that is going to be mapped
158
+     * @return array|false
159
+     */
160
+    public function getTag($id) {
161
+        $key = $this->getTagById($id);
162
+        if ($key !== false) {
163
+            return $this->tagMap($this->tags[$key]);
164
+        }
165
+        return false;
166
+    }
167
+
168
+    /**
169
+     * Get the tags for a specific user.
170
+     *
171
+     * This returns an array with maps containing each tag's properties:
172
+     * [
173
+     * 	['id' => 0, 'name' = 'First tag', 'owner' = 'User', 'type' => 'tagtype'],
174
+     * 	['id' => 1, 'name' = 'Shared tag', 'owner' = 'Other user', 'type' => 'tagtype'],
175
+     * ]
176
+     *
177
+     * @return array
178
+     */
179
+    public function getTags() {
180
+        if(!count($this->tags)) {
181
+            return [];
182
+        }
183
+
184
+        usort($this->tags, function ($a, $b) {
185
+            return strnatcasecmp($a->getName(), $b->getName());
186
+        });
187
+        $tagMap = [];
188
+
189
+        foreach($this->tags as $tag) {
190
+            if($tag->getName() !== ITags::TAG_FAVORITE) {
191
+                $tagMap[] = $this->tagMap($tag);
192
+            }
193
+        }
194
+        return $tagMap;
195
+
196
+    }
197
+
198
+    /**
199
+     * Return only the tags owned by the given user, omitting any tags shared
200
+     * by other users.
201
+     *
202
+     * @param string $user The user whose tags are to be checked.
203
+     * @return array An array of Tag objects.
204
+     */
205
+    public function getTagsForUser($user) {
206
+        return array_filter($this->tags,
207
+            function ($tag) use ($user) {
208
+                return $tag->getOwner() === $user;
209
+            }
210
+        );
211
+    }
212
+
213
+    /**
214
+     * Get the list of tags for the given ids.
215
+     *
216
+     * @param array $objIds array of object ids
217
+     * @return array|boolean of tags id as key to array of tag names
218
+     * or false if an error occurred
219
+     */
220
+    public function getTagsForObjects(array $objIds) {
221
+        $entries = [];
222
+
223
+        try {
224
+            $conn = \OC::$server->getDatabaseConnection();
225
+            $chunks = array_chunk($objIds, 900, false);
226
+            foreach ($chunks as $chunk) {
227
+                $result = $conn->executeQuery(
228
+                    'SELECT `category`, `categoryid`, `objid` ' .
229
+                    'FROM `' . self::RELATION_TABLE . '` r, `' . self::TAG_TABLE . '` ' .
230
+                    'WHERE `categoryid` = `id` AND `uid` = ? AND r.`type` = ? AND `objid` IN (?)',
231
+                    [$this->user, $this->type, $chunk],
232
+                    [null, null, IQueryBuilder::PARAM_INT_ARRAY]
233
+                );
234
+                while ($row = $result->fetch()) {
235
+                    $objId = (int)$row['objid'];
236
+                    if (!isset($entries[$objId])) {
237
+                        $entries[$objId] = [];
238
+                    }
239
+                    $entries[$objId][] = $row['category'];
240
+                }
241
+                if ($result === null) {
242
+                    \OCP\Util::writeLog('core', __METHOD__. 'DB error: ' . \OC::$server->getDatabaseConnection()->getError(), ILogger::ERROR);
243
+                    return false;
244
+                }
245
+            }
246
+        } catch(\Exception $e) {
247
+            \OC::$server->getLogger()->logException($e, [
248
+                'message' => __METHOD__,
249
+                'level' => ILogger::ERROR,
250
+                'app' => 'core',
251
+            ]);
252
+            return false;
253
+        }
254
+
255
+        return $entries;
256
+    }
257
+
258
+    /**
259
+     * Get the a list if items tagged with $tag.
260
+     *
261
+     * Throws an exception if the tag could not be found.
262
+     *
263
+     * @param string $tag Tag id or name.
264
+     * @return array|false An array of object ids or false on error.
265
+     * @throws \Exception
266
+     */
267
+    public function getIdsForTag($tag) {
268
+        $result = null;
269
+        $tagId = false;
270
+        if(is_numeric($tag)) {
271
+            $tagId = $tag;
272
+        } elseif(is_string($tag)) {
273
+            $tag = trim($tag);
274
+            if($tag === '') {
275
+                \OCP\Util::writeLog('core', __METHOD__.', Cannot use empty tag names', ILogger::DEBUG);
276
+                return false;
277
+            }
278
+            $tagId = $this->getTagId($tag);
279
+        }
280
+
281
+        if($tagId === false) {
282
+            $l10n = \OC::$server->getL10N('core');
283
+            throw new \Exception(
284
+                $l10n->t('Could not find category "%s"', [$tag])
285
+            );
286
+        }
287
+
288
+        $ids = [];
289
+        $sql = 'SELECT `objid` FROM `' . self::RELATION_TABLE
290
+            . '` WHERE `categoryid` = ?';
291
+
292
+        try {
293
+            $stmt = \OC_DB::prepare($sql);
294
+            $result = $stmt->execute([$tagId]);
295
+            if ($result === null) {
296
+                \OCP\Util::writeLog('core', __METHOD__. 'DB error: ' . \OC::$server->getDatabaseConnection()->getError(), ILogger::ERROR);
297
+                return false;
298
+            }
299
+        } catch(\Exception $e) {
300
+            \OC::$server->getLogger()->logException($e, [
301
+                'message' => __METHOD__,
302
+                'level' => ILogger::ERROR,
303
+                'app' => 'core',
304
+            ]);
305
+            return false;
306
+        }
307
+
308
+        if(!is_null($result)) {
309
+            while($row = $result->fetchRow()) {
310
+                $id = (int)$row['objid'];
311
+
312
+                if ($this->includeShared) {
313
+                    // We have to check if we are really allowed to access the
314
+                    // items that are tagged with $tag. To that end, we ask the
315
+                    // corresponding sharing backend if the item identified by $id
316
+                    // is owned by any of $this->owners.
317
+                    foreach ($this->owners as $owner) {
318
+                        if ($this->backend->isValidSource($id, $owner)) {
319
+                            $ids[] = $id;
320
+                            break;
321
+                        }
322
+                    }
323
+                } else {
324
+                    $ids[] = $id;
325
+                }
326
+            }
327
+        }
328
+
329
+        return $ids;
330
+    }
331
+
332
+    /**
333
+     * Checks whether a tag is saved for the given user,
334
+     * disregarding the ones shared with him or her.
335
+     *
336
+     * @param string $name The tag name to check for.
337
+     * @param string $user The user whose tags are to be checked.
338
+     * @return bool
339
+     */
340
+    public function userHasTag($name, $user) {
341
+        $key = $this->array_searchi($name, $this->getTagsForUser($user));
342
+        return ($key !== false) ? $this->tags[$key]->getId() : false;
343
+    }
344
+
345
+    /**
346
+     * Checks whether a tag is saved for or shared with the current user.
347
+     *
348
+     * @param string $name The tag name to check for.
349
+     * @return bool
350
+     */
351
+    public function hasTag($name) {
352
+        return $this->getTagId($name) !== false;
353
+    }
354
+
355
+    /**
356
+     * Add a new tag.
357
+     *
358
+     * @param string $name A string with a name of the tag
359
+     * @return false|int the id of the added tag or false on error.
360
+     */
361
+    public function add($name) {
362
+        $name = trim($name);
363
+
364
+        if($name === '') {
365
+            \OCP\Util::writeLog('core', __METHOD__.', Cannot add an empty tag', ILogger::DEBUG);
366
+            return false;
367
+        }
368
+        if($this->userHasTag($name, $this->user)) {
369
+            \OCP\Util::writeLog('core', __METHOD__.', name: ' . $name. ' exists already', ILogger::DEBUG);
370
+            return false;
371
+        }
372
+        try {
373
+            $tag = new Tag($this->user, $this->type, $name);
374
+            $tag = $this->mapper->insert($tag);
375
+            $this->tags[] = $tag;
376
+        } catch(\Exception $e) {
377
+            \OC::$server->getLogger()->logException($e, [
378
+                'message' => __METHOD__,
379
+                'level' => ILogger::ERROR,
380
+                'app' => 'core',
381
+            ]);
382
+            return false;
383
+        }
384
+        \OCP\Util::writeLog('core', __METHOD__.', id: ' . $tag->getId(), ILogger::DEBUG);
385
+        return $tag->getId();
386
+    }
387
+
388
+    /**
389
+     * Rename tag.
390
+     *
391
+     * @param string|integer $from The name or ID of the existing tag
392
+     * @param string $to The new name of the tag.
393
+     * @return bool
394
+     */
395
+    public function rename($from, $to) {
396
+        $from = trim($from);
397
+        $to = trim($to);
398
+
399
+        if($to === '' || $from === '') {
400
+            \OCP\Util::writeLog('core', __METHOD__.', Cannot use empty tag names', ILogger::DEBUG);
401
+            return false;
402
+        }
403
+
404
+        if (is_numeric($from)) {
405
+            $key = $this->getTagById($from);
406
+        } else {
407
+            $key = $this->getTagByName($from);
408
+        }
409
+        if($key === false) {
410
+            \OCP\Util::writeLog('core', __METHOD__.', tag: ' . $from. ' does not exist', ILogger::DEBUG);
411
+            return false;
412
+        }
413
+        $tag = $this->tags[$key];
414
+
415
+        if($this->userHasTag($to, $tag->getOwner())) {
416
+            \OCP\Util::writeLog('core', __METHOD__.', A tag named ' . $to. ' already exists for user ' . $tag->getOwner() . '.', ILogger::DEBUG);
417
+            return false;
418
+        }
419
+
420
+        try {
421
+            $tag->setName($to);
422
+            $this->tags[$key] = $this->mapper->update($tag);
423
+        } catch(\Exception $e) {
424
+            \OC::$server->getLogger()->logException($e, [
425
+                'message' => __METHOD__,
426
+                'level' => ILogger::ERROR,
427
+                'app' => 'core',
428
+            ]);
429
+            return false;
430
+        }
431
+        return true;
432
+    }
433
+
434
+    /**
435
+     * Add a list of new tags.
436
+     *
437
+     * @param string[] $names A string with a name or an array of strings containing
438
+     * the name(s) of the tag(s) to add.
439
+     * @param bool $sync When true, save the tags
440
+     * @param int|null $id int Optional object id to add to this|these tag(s)
441
+     * @return bool Returns false on error.
442
+     */
443
+    public function addMultiple($names, $sync=false, $id = null) {
444
+        if(!is_array($names)) {
445
+            $names = [$names];
446
+        }
447
+        $names = array_map('trim', $names);
448
+        array_filter($names);
449
+
450
+        $newones = [];
451
+        foreach($names as $name) {
452
+            if(!$this->hasTag($name) && $name !== '') {
453
+                $newones[] = new Tag($this->user, $this->type, $name);
454
+            }
455
+            if(!is_null($id)) {
456
+                // Insert $objectid, $categoryid  pairs if not exist.
457
+                self::$relations[] = ['objid' => $id, 'tag' => $name];
458
+            }
459
+        }
460
+        $this->tags = array_merge($this->tags, $newones);
461
+        if($sync === true) {
462
+            $this->save();
463
+        }
464
+
465
+        return true;
466
+    }
467
+
468
+    /**
469
+     * Save the list of tags and their object relations
470
+     */
471
+    protected function save() {
472
+        if(is_array($this->tags)) {
473
+            foreach($this->tags as $tag) {
474
+                try {
475
+                    if (!$this->mapper->tagExists($tag)) {
476
+                        $this->mapper->insert($tag);
477
+                    }
478
+                } catch(\Exception $e) {
479
+                    \OC::$server->getLogger()->logException($e, [
480
+                        'message' => __METHOD__,
481
+                        'level' => ILogger::ERROR,
482
+                        'app' => 'core',
483
+                    ]);
484
+                }
485
+            }
486
+
487
+            // reload tags to get the proper ids.
488
+            $this->tags = $this->mapper->loadTags($this->owners, $this->type);
489
+            \OCP\Util::writeLog('core', __METHOD__.', tags: ' . print_r($this->tags, true),
490
+                ILogger::DEBUG);
491
+            // Loop through temporarily cached objectid/tagname pairs
492
+            // and save relations.
493
+            $tags = $this->tags;
494
+            // For some reason this is needed or array_search(i) will return 0..?
495
+            ksort($tags);
496
+            $dbConnection = \OC::$server->getDatabaseConnection();
497
+            foreach(self::$relations as $relation) {
498
+                $tagId = $this->getTagId($relation['tag']);
499
+                \OCP\Util::writeLog('core', __METHOD__ . 'catid, ' . $relation['tag'] . ' ' . $tagId, ILogger::DEBUG);
500
+                if($tagId) {
501
+                    try {
502
+                        $dbConnection->insertIfNotExist(self::RELATION_TABLE,
503
+                            [
504
+                                'objid' => $relation['objid'],
505
+                                'categoryid' => $tagId,
506
+                                'type' => $this->type,
507
+                            ]);
508
+                    } catch(\Exception $e) {
509
+                        \OC::$server->getLogger()->logException($e, [
510
+                            'message' => __METHOD__,
511
+                            'level' => ILogger::ERROR,
512
+                            'app' => 'core',
513
+                        ]);
514
+                    }
515
+                }
516
+            }
517
+            self::$relations = []; // reset
518
+        } else {
519
+            \OCP\Util::writeLog('core', __METHOD__.', $this->tags is not an array! '
520
+                . print_r($this->tags, true), ILogger::ERROR);
521
+        }
522
+    }
523
+
524
+    /**
525
+     * Delete tags and tag/object relations for a user.
526
+     *
527
+     * For hooking up on post_deleteUser
528
+     *
529
+     * @param array $arguments
530
+     */
531
+    public static function post_deleteUser($arguments) {
532
+        // Find all objectid/tagId pairs.
533
+        $result = null;
534
+        try {
535
+            $stmt = \OC_DB::prepare('SELECT `id` FROM `' . self::TAG_TABLE . '` '
536
+                . 'WHERE `uid` = ?');
537
+            $result = $stmt->execute([$arguments['uid']]);
538
+            if ($result === null) {
539
+                \OCP\Util::writeLog('core', __METHOD__. 'DB error: ' . \OC::$server->getDatabaseConnection()->getError(), ILogger::ERROR);
540
+            }
541
+        } catch(\Exception $e) {
542
+            \OC::$server->getLogger()->logException($e, [
543
+                'message' => __METHOD__,
544
+                'level' => ILogger::ERROR,
545
+                'app' => 'core',
546
+            ]);
547
+        }
548
+
549
+        if(!is_null($result)) {
550
+            try {
551
+                $stmt = \OC_DB::prepare('DELETE FROM `' . self::RELATION_TABLE . '` '
552
+                    . 'WHERE `categoryid` = ?');
553
+                while($row = $result->fetchRow()) {
554
+                    try {
555
+                        $stmt->execute([$row['id']]);
556
+                    } catch(\Exception $e) {
557
+                        \OC::$server->getLogger()->logException($e, [
558
+                            'message' => __METHOD__,
559
+                            'level' => ILogger::ERROR,
560
+                            'app' => 'core',
561
+                        ]);
562
+                    }
563
+                }
564
+            } catch(\Exception $e) {
565
+                \OC::$server->getLogger()->logException($e, [
566
+                    'message' => __METHOD__,
567
+                    'level' => ILogger::ERROR,
568
+                    'app' => 'core',
569
+                ]);
570
+            }
571
+        }
572
+        try {
573
+            $stmt = \OC_DB::prepare('DELETE FROM `' . self::TAG_TABLE . '` '
574
+                . 'WHERE `uid` = ?');
575
+            $result = $stmt->execute([$arguments['uid']]);
576
+            if ($result === null) {
577
+                \OCP\Util::writeLog('core', __METHOD__. ', DB error: ' . \OC::$server->getDatabaseConnection()->getError(), ILogger::ERROR);
578
+            }
579
+        } catch(\Exception $e) {
580
+            \OC::$server->getLogger()->logException($e, [
581
+                'message' => __METHOD__,
582
+                'level' => ILogger::ERROR,
583
+                'app' => 'core',
584
+            ]);
585
+        }
586
+    }
587
+
588
+    /**
589
+     * Delete tag/object relations from the db
590
+     *
591
+     * @param array $ids The ids of the objects
592
+     * @return boolean Returns false on error.
593
+     */
594
+    public function purgeObjects(array $ids) {
595
+        if(count($ids) === 0) {
596
+            // job done ;)
597
+            return true;
598
+        }
599
+        $updates = $ids;
600
+        try {
601
+            $query = 'DELETE FROM `' . self::RELATION_TABLE . '` ';
602
+            $query .= 'WHERE `objid` IN (' . str_repeat('?,', count($ids)-1) . '?) ';
603
+            $query .= 'AND `type`= ?';
604
+            $updates[] = $this->type;
605
+            $stmt = \OC_DB::prepare($query);
606
+            $result = $stmt->execute($updates);
607
+            if ($result === null) {
608
+                \OCP\Util::writeLog('core', __METHOD__. 'DB error: ' . \OC::$server->getDatabaseConnection()->getError(), ILogger::ERROR);
609
+                return false;
610
+            }
611
+        } catch(\Exception $e) {
612
+            \OC::$server->getLogger()->logException($e, [
613
+                'message' => __METHOD__,
614
+                'level' => ILogger::ERROR,
615
+                'app' => 'core',
616
+            ]);
617
+            return false;
618
+        }
619
+        return true;
620
+    }
621
+
622
+    /**
623
+     * Get favorites for an object type
624
+     *
625
+     * @return array|false An array of object ids.
626
+     */
627
+    public function getFavorites() {
628
+        if(!$this->userHasTag(ITags::TAG_FAVORITE, $this->user)) {
629
+            return [];
630
+        }
631
+
632
+        try {
633
+            return $this->getIdsForTag(ITags::TAG_FAVORITE);
634
+        } catch(\Exception $e) {
635
+            \OC::$server->getLogger()->logException($e, [
636
+                'message' => __METHOD__,
637
+                'level' => ILogger::ERROR,
638
+                'app' => 'core',
639
+            ]);
640
+            return [];
641
+        }
642
+    }
643
+
644
+    /**
645
+     * Add an object to favorites
646
+     *
647
+     * @param int $objid The id of the object
648
+     * @return boolean
649
+     */
650
+    public function addToFavorites($objid) {
651
+        if(!$this->userHasTag(ITags::TAG_FAVORITE, $this->user)) {
652
+            $this->add(ITags::TAG_FAVORITE);
653
+        }
654
+        return $this->tagAs($objid, ITags::TAG_FAVORITE);
655
+    }
656
+
657
+    /**
658
+     * Remove an object from favorites
659
+     *
660
+     * @param int $objid The id of the object
661
+     * @return boolean
662
+     */
663
+    public function removeFromFavorites($objid) {
664
+        return $this->unTag($objid, ITags::TAG_FAVORITE);
665
+    }
666
+
667
+    /**
668
+     * Creates a tag/object relation.
669
+     *
670
+     * @param int $objid The id of the object
671
+     * @param string $tag The id or name of the tag
672
+     * @return boolean Returns false on error.
673
+     */
674
+    public function tagAs($objid, $tag) {
675
+        if(is_string($tag) && !is_numeric($tag)) {
676
+            $tag = trim($tag);
677
+            if($tag === '') {
678
+                \OCP\Util::writeLog('core', __METHOD__.', Cannot add an empty tag', ILogger::DEBUG);
679
+                return false;
680
+            }
681
+            if(!$this->hasTag($tag)) {
682
+                $this->add($tag);
683
+            }
684
+            $tagId =  $this->getTagId($tag);
685
+        } else {
686
+            $tagId = $tag;
687
+        }
688
+        try {
689
+            \OC::$server->getDatabaseConnection()->insertIfNotExist(self::RELATION_TABLE,
690
+                [
691
+                    'objid' => $objid,
692
+                    'categoryid' => $tagId,
693
+                    'type' => $this->type,
694
+                ]);
695
+        } catch(\Exception $e) {
696
+            \OC::$server->getLogger()->logException($e, [
697
+                'message' => __METHOD__,
698
+                'level' => ILogger::ERROR,
699
+                'app' => 'core',
700
+            ]);
701
+            return false;
702
+        }
703
+        return true;
704
+    }
705
+
706
+    /**
707
+     * Delete single tag/object relation from the db
708
+     *
709
+     * @param int $objid The id of the object
710
+     * @param string $tag The id or name of the tag
711
+     * @return boolean
712
+     */
713
+    public function unTag($objid, $tag) {
714
+        if(is_string($tag) && !is_numeric($tag)) {
715
+            $tag = trim($tag);
716
+            if($tag === '') {
717
+                \OCP\Util::writeLog('core', __METHOD__.', Tag name is empty', ILogger::DEBUG);
718
+                return false;
719
+            }
720
+            $tagId =  $this->getTagId($tag);
721
+        } else {
722
+            $tagId = $tag;
723
+        }
724
+
725
+        try {
726
+            $sql = 'DELETE FROM `' . self::RELATION_TABLE . '` '
727
+                    . 'WHERE `objid` = ? AND `categoryid` = ? AND `type` = ?';
728
+            $stmt = \OC_DB::prepare($sql);
729
+            $stmt->execute([$objid, $tagId, $this->type]);
730
+        } catch(\Exception $e) {
731
+            \OC::$server->getLogger()->logException($e, [
732
+                'message' => __METHOD__,
733
+                'level' => ILogger::ERROR,
734
+                'app' => 'core',
735
+            ]);
736
+            return false;
737
+        }
738
+        return true;
739
+    }
740
+
741
+    /**
742
+     * Delete tags from the database.
743
+     *
744
+     * @param string[]|integer[] $names An array of tags (names or IDs) to delete
745
+     * @return bool Returns false on error
746
+     */
747
+    public function delete($names) {
748
+        if(!is_array($names)) {
749
+            $names = [$names];
750
+        }
751
+
752
+        $names = array_map('trim', $names);
753
+        array_filter($names);
754
+
755
+        \OCP\Util::writeLog('core', __METHOD__ . ', before: '
756
+            . print_r($this->tags, true), ILogger::DEBUG);
757
+        foreach($names as $name) {
758
+            $id = null;
759
+
760
+            if (is_numeric($name)) {
761
+                $key = $this->getTagById($name);
762
+            } else {
763
+                $key = $this->getTagByName($name);
764
+            }
765
+            if ($key !== false) {
766
+                $tag = $this->tags[$key];
767
+                $id = $tag->getId();
768
+                unset($this->tags[$key]);
769
+                $this->mapper->delete($tag);
770
+            } else {
771
+                \OCP\Util::writeLog('core', __METHOD__ . 'Cannot delete tag ' . $name
772
+                    . ': not found.', ILogger::ERROR);
773
+            }
774
+            if(!is_null($id) && $id !== false) {
775
+                try {
776
+                    $sql = 'DELETE FROM `' . self::RELATION_TABLE . '` '
777
+                            . 'WHERE `categoryid` = ?';
778
+                    $stmt = \OC_DB::prepare($sql);
779
+                    $result = $stmt->execute([$id]);
780
+                    if ($result === null) {
781
+                        \OCP\Util::writeLog('core',
782
+                            __METHOD__. 'DB error: ' . \OC::$server->getDatabaseConnection()->getError(),
783
+                            ILogger::ERROR);
784
+                        return false;
785
+                    }
786
+                } catch(\Exception $e) {
787
+                    \OC::$server->getLogger()->logException($e, [
788
+                        'message' => __METHOD__,
789
+                        'level' => ILogger::ERROR,
790
+                        'app' => 'core',
791
+                    ]);
792
+                    return false;
793
+                }
794
+            }
795
+        }
796
+        return true;
797
+    }
798
+
799
+    // case-insensitive array_search
800
+    protected function array_searchi($needle, $haystack, $mem='getName') {
801
+        if(!is_array($haystack)) {
802
+            return false;
803
+        }
804
+        return array_search(strtolower($needle), array_map(
805
+            function ($tag) use ($mem) {
806
+                return strtolower(call_user_func([$tag, $mem]));
807
+            }, $haystack)
808
+        );
809
+    }
810
+
811
+    /**
812
+     * Get a tag's ID.
813
+     *
814
+     * @param string $name The tag name to look for.
815
+     * @return string|bool The tag's id or false if no matching tag is found.
816
+     */
817
+    private function getTagId($name) {
818
+        $key = $this->array_searchi($name, $this->tags);
819
+        if ($key !== false) {
820
+            return $this->tags[$key]->getId();
821
+        }
822
+        return false;
823
+    }
824
+
825
+    /**
826
+     * Get a tag by its name.
827
+     *
828
+     * @param string $name The tag name.
829
+     * @return integer|bool The tag object's offset within the $this->tags
830
+     *                      array or false if it doesn't exist.
831
+     */
832
+    private function getTagByName($name) {
833
+        return $this->array_searchi($name, $this->tags, 'getName');
834
+    }
835
+
836
+    /**
837
+     * Get a tag by its ID.
838
+     *
839
+     * @param string $id The tag ID to look for.
840
+     * @return integer|bool The tag object's offset within the $this->tags
841
+     *                      array or false if it doesn't exist.
842
+     */
843
+    private function getTagById($id) {
844
+        return $this->array_searchi($id, $this->tags, 'getId');
845
+    }
846
+
847
+    /**
848
+     * Returns an array mapping a given tag's properties to its values:
849
+     * ['id' => 0, 'name' = 'Tag', 'owner' = 'User', 'type' => 'tagtype']
850
+     *
851
+     * @param Tag $tag The tag that is going to be mapped
852
+     * @return array
853
+     */
854
+    private function tagMap(Tag $tag) {
855
+        return [
856
+            'id'    => $tag->getId(),
857
+            'name'  => $tag->getName(),
858
+            'owner' => $tag->getOwner(),
859
+            'type'  => $tag->getType()
860
+        ];
861
+    }
862 862
 }
Please login to merge, or discard this patch.
lib/private/Collaboration/Collaborators/RemotePlugin.php 1 patch
Indentation   +140 added lines, -140 removed lines patch added patch discarded remove patch
@@ -37,155 +37,155 @@
 block discarded – undo
37 37
 use OCP\Share;
38 38
 
39 39
 class RemotePlugin implements ISearchPlugin {
40
-	protected $shareeEnumeration;
40
+    protected $shareeEnumeration;
41 41
 
42
-	/** @var IManager */
43
-	private $contactsManager;
44
-	/** @var ICloudIdManager */
45
-	private $cloudIdManager;
46
-	/** @var IConfig */
47
-	private $config;
48
-	/** @var IUserManager */
49
-	private $userManager;
50
-	/** @var string */
51
-	private $userId = '';
42
+    /** @var IManager */
43
+    private $contactsManager;
44
+    /** @var ICloudIdManager */
45
+    private $cloudIdManager;
46
+    /** @var IConfig */
47
+    private $config;
48
+    /** @var IUserManager */
49
+    private $userManager;
50
+    /** @var string */
51
+    private $userId = '';
52 52
 
53
-	public function __construct(IManager $contactsManager, ICloudIdManager $cloudIdManager, IConfig $config, IUserManager $userManager, IUserSession $userSession) {
54
-		$this->contactsManager = $contactsManager;
55
-		$this->cloudIdManager = $cloudIdManager;
56
-		$this->config = $config;
57
-		$this->userManager = $userManager;
58
-		$user = $userSession->getUser();
59
-		if ($user !== null) {
60
-			$this->userId = $user->getUID();
61
-		}
62
-		$this->shareeEnumeration = $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') === 'yes';
63
-	}
53
+    public function __construct(IManager $contactsManager, ICloudIdManager $cloudIdManager, IConfig $config, IUserManager $userManager, IUserSession $userSession) {
54
+        $this->contactsManager = $contactsManager;
55
+        $this->cloudIdManager = $cloudIdManager;
56
+        $this->config = $config;
57
+        $this->userManager = $userManager;
58
+        $user = $userSession->getUser();
59
+        if ($user !== null) {
60
+            $this->userId = $user->getUID();
61
+        }
62
+        $this->shareeEnumeration = $this->config->getAppValue('core', 'shareapi_allow_share_dialog_user_enumeration', 'yes') === 'yes';
63
+    }
64 64
 
65
-	public function search($search, $limit, $offset, ISearchResult $searchResult) {
66
-		$result = ['wide' => [], 'exact' => []];
67
-		$resultType = new SearchResultType('remotes');
65
+    public function search($search, $limit, $offset, ISearchResult $searchResult) {
66
+        $result = ['wide' => [], 'exact' => []];
67
+        $resultType = new SearchResultType('remotes');
68 68
 
69
-		// Search in contacts
70
-		//@todo Pagination missing
71
-		$addressBookContacts = $this->contactsManager->search($search, ['CLOUD', 'FN']);
72
-		foreach ($addressBookContacts as $contact) {
73
-			if (isset($contact['isLocalSystemBook'])) {
74
-				continue;
75
-			}
76
-			if (isset($contact['CLOUD'])) {
77
-				$cloudIds = $contact['CLOUD'];
78
-				if (is_string($cloudIds)) {
79
-					$cloudIds = [$cloudIds];
80
-				}
81
-				$lowerSearch = strtolower($search);
82
-				foreach ($cloudIds as $cloudId) {
83
-					$cloudIdType = '';
84
-					if (\is_array($cloudId)) {
85
-						$cloudIdData = $cloudId;
86
-						$cloudId = $cloudIdData['value'];
87
-						$cloudIdType = $cloudIdData['type'];
88
-					}
89
-					try {
90
-						list($remoteUser, $serverUrl) = $this->splitUserRemote($cloudId);
91
-					} catch (\InvalidArgumentException $e) {
92
-						continue;
93
-					}
69
+        // Search in contacts
70
+        //@todo Pagination missing
71
+        $addressBookContacts = $this->contactsManager->search($search, ['CLOUD', 'FN']);
72
+        foreach ($addressBookContacts as $contact) {
73
+            if (isset($contact['isLocalSystemBook'])) {
74
+                continue;
75
+            }
76
+            if (isset($contact['CLOUD'])) {
77
+                $cloudIds = $contact['CLOUD'];
78
+                if (is_string($cloudIds)) {
79
+                    $cloudIds = [$cloudIds];
80
+                }
81
+                $lowerSearch = strtolower($search);
82
+                foreach ($cloudIds as $cloudId) {
83
+                    $cloudIdType = '';
84
+                    if (\is_array($cloudId)) {
85
+                        $cloudIdData = $cloudId;
86
+                        $cloudId = $cloudIdData['value'];
87
+                        $cloudIdType = $cloudIdData['type'];
88
+                    }
89
+                    try {
90
+                        list($remoteUser, $serverUrl) = $this->splitUserRemote($cloudId);
91
+                    } catch (\InvalidArgumentException $e) {
92
+                        continue;
93
+                    }
94 94
 
95
-					$localUser = $this->userManager->get($remoteUser);
96
-					/**
97
-					 * Add local share if remote cloud id matches a local user ones
98
-					 */
99
-					if ($localUser !== null && $remoteUser !== $this->userId && $cloudId === $localUser->getCloudId()) {
100
-						$result['wide'][] = [
101
-							'label' => $contact['FN'],
102
-							'uuid' => $contact['UID'],
103
-							'value' => [
104
-								'shareType' => Share::SHARE_TYPE_USER,
105
-								'shareWith' => $remoteUser
106
-							]
107
-						];
108
-					}
95
+                    $localUser = $this->userManager->get($remoteUser);
96
+                    /**
97
+                     * Add local share if remote cloud id matches a local user ones
98
+                     */
99
+                    if ($localUser !== null && $remoteUser !== $this->userId && $cloudId === $localUser->getCloudId()) {
100
+                        $result['wide'][] = [
101
+                            'label' => $contact['FN'],
102
+                            'uuid' => $contact['UID'],
103
+                            'value' => [
104
+                                'shareType' => Share::SHARE_TYPE_USER,
105
+                                'shareWith' => $remoteUser
106
+                            ]
107
+                        ];
108
+                    }
109 109
 
110
-					if (strtolower($contact['FN']) === $lowerSearch || strtolower($cloudId) === $lowerSearch) {
111
-						if (strtolower($cloudId) === $lowerSearch) {
112
-							$searchResult->markExactIdMatch($resultType);
113
-						}
114
-						$result['exact'][] = [
115
-							'label' => $contact['FN'] . " ($cloudId)",
116
-							'uuid' => $contact['UID'],
117
-							'name' => $contact['FN'],
118
-							'type' => $cloudIdType,
119
-							'value' => [
120
-								'shareType' => Share::SHARE_TYPE_REMOTE,
121
-								'shareWith' => $cloudId,
122
-								'server' => $serverUrl,
123
-							],
124
-						];
125
-					} else {
126
-						$result['wide'][] = [
127
-							'label' => $contact['FN'] . " ($cloudId)",
128
-							'uuid' => $contact['UID'],
129
-							'name' => $contact['FN'],
130
-							'type' => $cloudIdType,
131
-							'value' => [
132
-								'shareType' => Share::SHARE_TYPE_REMOTE,
133
-								'shareWith' => $cloudId,
134
-								'server' => $serverUrl,
135
-							],
136
-						];
137
-					}
138
-				}
139
-			}
140
-		}
110
+                    if (strtolower($contact['FN']) === $lowerSearch || strtolower($cloudId) === $lowerSearch) {
111
+                        if (strtolower($cloudId) === $lowerSearch) {
112
+                            $searchResult->markExactIdMatch($resultType);
113
+                        }
114
+                        $result['exact'][] = [
115
+                            'label' => $contact['FN'] . " ($cloudId)",
116
+                            'uuid' => $contact['UID'],
117
+                            'name' => $contact['FN'],
118
+                            'type' => $cloudIdType,
119
+                            'value' => [
120
+                                'shareType' => Share::SHARE_TYPE_REMOTE,
121
+                                'shareWith' => $cloudId,
122
+                                'server' => $serverUrl,
123
+                            ],
124
+                        ];
125
+                    } else {
126
+                        $result['wide'][] = [
127
+                            'label' => $contact['FN'] . " ($cloudId)",
128
+                            'uuid' => $contact['UID'],
129
+                            'name' => $contact['FN'],
130
+                            'type' => $cloudIdType,
131
+                            'value' => [
132
+                                'shareType' => Share::SHARE_TYPE_REMOTE,
133
+                                'shareWith' => $cloudId,
134
+                                'server' => $serverUrl,
135
+                            ],
136
+                        ];
137
+                    }
138
+                }
139
+            }
140
+        }
141 141
 
142
-		if (!$this->shareeEnumeration) {
143
-			$result['wide'] = [];
144
-		} else {
145
-			$result['wide'] = array_slice($result['wide'], $offset, $limit);
146
-		}
142
+        if (!$this->shareeEnumeration) {
143
+            $result['wide'] = [];
144
+        } else {
145
+            $result['wide'] = array_slice($result['wide'], $offset, $limit);
146
+        }
147 147
 
148
-		/**
149
-		 * Add generic share with remote item for valid cloud ids that are not users of the local instance
150
-		 */
151
-		if (!$searchResult->hasExactIdMatch($resultType) && $this->cloudIdManager->isValidCloudId($search) && $offset === 0) {
152
-			try {
153
-				list($remoteUser, $serverUrl) = $this->splitUserRemote($search);
154
-				$localUser = $this->userManager->get($remoteUser);
155
-				if ($localUser === null || $search !== $localUser->getCloudId()) {
156
-					$result['exact'][] = [
157
-						'label' => $remoteUser . " ($serverUrl)",
158
-						'uuid' => $remoteUser,
159
-						'name' => $remoteUser,
160
-						'value' => [
161
-							'shareType' => Share::SHARE_TYPE_REMOTE,
162
-							'shareWith' => $search,
163
-							'server' => $serverUrl,
164
-						],
165
-					];
166
-				}
167
-			} catch (\InvalidArgumentException $e) {
168
-			}
169
-		}
148
+        /**
149
+         * Add generic share with remote item for valid cloud ids that are not users of the local instance
150
+         */
151
+        if (!$searchResult->hasExactIdMatch($resultType) && $this->cloudIdManager->isValidCloudId($search) && $offset === 0) {
152
+            try {
153
+                list($remoteUser, $serverUrl) = $this->splitUserRemote($search);
154
+                $localUser = $this->userManager->get($remoteUser);
155
+                if ($localUser === null || $search !== $localUser->getCloudId()) {
156
+                    $result['exact'][] = [
157
+                        'label' => $remoteUser . " ($serverUrl)",
158
+                        'uuid' => $remoteUser,
159
+                        'name' => $remoteUser,
160
+                        'value' => [
161
+                            'shareType' => Share::SHARE_TYPE_REMOTE,
162
+                            'shareWith' => $search,
163
+                            'server' => $serverUrl,
164
+                        ],
165
+                    ];
166
+                }
167
+            } catch (\InvalidArgumentException $e) {
168
+            }
169
+        }
170 170
 
171
-		$searchResult->addResultSet($resultType, $result['wide'], $result['exact']);
171
+        $searchResult->addResultSet($resultType, $result['wide'], $result['exact']);
172 172
 
173
-		return true;
174
-	}
173
+        return true;
174
+    }
175 175
 
176
-	/**
177
-	 * split user and remote from federated cloud id
178
-	 *
179
-	 * @param string $address federated share address
180
-	 * @return array [user, remoteURL]
181
-	 * @throws \InvalidArgumentException
182
-	 */
183
-	public function splitUserRemote($address) {
184
-		try {
185
-			$cloudId = $this->cloudIdManager->resolveCloudId($address);
186
-			return [$cloudId->getUser(), $cloudId->getRemote()];
187
-		} catch (\InvalidArgumentException $e) {
188
-			throw new \InvalidArgumentException('Invalid Federated Cloud ID', 0, $e);
189
-		}
190
-	}
176
+    /**
177
+     * split user and remote from federated cloud id
178
+     *
179
+     * @param string $address federated share address
180
+     * @return array [user, remoteURL]
181
+     * @throws \InvalidArgumentException
182
+     */
183
+    public function splitUserRemote($address) {
184
+        try {
185
+            $cloudId = $this->cloudIdManager->resolveCloudId($address);
186
+            return [$cloudId->getUser(), $cloudId->getRemote()];
187
+        } catch (\InvalidArgumentException $e) {
188
+            throw new \InvalidArgumentException('Invalid Federated Cloud ID', 0, $e);
189
+        }
190
+    }
191 191
 }
Please login to merge, or discard this patch.
lib/private/ContactsManager.php 1 patch
Indentation   +177 added lines, -177 removed lines patch added patch discarded remove patch
@@ -30,181 +30,181 @@
 block discarded – undo
30 30
 
31 31
 namespace OC {
32 32
 
33
-	class ContactsManager implements \OCP\Contacts\IManager {
34
-
35
-		/**
36
-		 * This function is used to search and find contacts within the users address books.
37
-		 * In case $pattern is empty all contacts will be returned.
38
-		 *
39
-		 * @param string $pattern which should match within the $searchProperties
40
-		 * @param array $searchProperties defines the properties within the query pattern should match
41
-		 * @param array $options = array() to define the search behavior
42
-		 * 	- 'escape_like_param' - If set to false wildcards _ and % are not escaped
43
-		 * @return array an array of contacts which are arrays of key-value-pairs
44
-		 */
45
-		public function search($pattern, $searchProperties = [], $options = []) {
46
-			$this->loadAddressBooks();
47
-			$result = [];
48
-			foreach($this->addressBooks as $addressBook) {
49
-				$r = $addressBook->search($pattern, $searchProperties, $options);
50
-				$contacts = [];
51
-				foreach($r as $c){
52
-					$c['addressbook-key'] = $addressBook->getKey();
53
-					$contacts[] = $c;
54
-				}
55
-				$result = array_merge($result, $contacts);
56
-			}
57
-
58
-			return $result;
59
-		}
60
-
61
-		/**
62
-		 * This function can be used to delete the contact identified by the given id
63
-		 *
64
-		 * @param object $id the unique identifier to a contact
65
-		 * @param string $addressBookKey identifier of the address book in which the contact shall be deleted
66
-		 * @return bool successful or not
67
-		 */
68
-		public function delete($id, $addressBookKey) {
69
-			$addressBook = $this->getAddressBook($addressBookKey);
70
-			if (!$addressBook) {
71
-				return null;
72
-			}
73
-
74
-			if ($addressBook->getPermissions() & \OCP\Constants::PERMISSION_DELETE) {
75
-				return $addressBook->delete($id);
76
-			}
77
-
78
-			return null;
79
-		}
80
-
81
-		/**
82
-		 * This function is used to create a new contact if 'id' is not given or not present.
83
-		 * Otherwise the contact will be updated by replacing the entire data set.
84
-		 *
85
-		 * @param array $properties this array if key-value-pairs defines a contact
86
-		 * @param string $addressBookKey identifier of the address book in which the contact shall be created or updated
87
-		 * @return array representing the contact just created or updated
88
-		 */
89
-		public function createOrUpdate($properties, $addressBookKey) {
90
-			$addressBook = $this->getAddressBook($addressBookKey);
91
-			if (!$addressBook) {
92
-				return null;
93
-			}
94
-
95
-			if ($addressBook->getPermissions() & \OCP\Constants::PERMISSION_CREATE) {
96
-				return $addressBook->createOrUpdate($properties);
97
-			}
98
-
99
-			return null;
100
-		}
101
-
102
-		/**
103
-		 * Check if contacts are available (e.g. contacts app enabled)
104
-		 *
105
-		 * @return bool true if enabled, false if not
106
-		 */
107
-		public function isEnabled() {
108
-			return !empty($this->addressBooks) || !empty($this->addressBookLoaders);
109
-		}
110
-
111
-		/**
112
-		 * @param \OCP\IAddressBook $addressBook
113
-		 */
114
-		public function registerAddressBook(\OCP\IAddressBook $addressBook) {
115
-			$this->addressBooks[$addressBook->getKey()] = $addressBook;
116
-		}
117
-
118
-		/**
119
-		 * @param \OCP\IAddressBook $addressBook
120
-		 */
121
-		public function unregisterAddressBook(\OCP\IAddressBook $addressBook) {
122
-			unset($this->addressBooks[$addressBook->getKey()]);
123
-		}
124
-
125
-		/**
126
-		 * Return a list of the user's addressbooks display names
127
-		 * ! The addressBook displayName are not unique, please use getUserAddressBooks
128
-		 *
129
-		 * @return array
130
-		 * @since 6.0.0
131
-		 * @deprecated 16.0.0 - Use `$this->getUserAddressBooks()` instead
132
-		 */
133
-		public function getAddressBooks() {
134
-			$this->loadAddressBooks();
135
-			$result = [];
136
-			foreach($this->addressBooks as $addressBook) {
137
-				$result[$addressBook->getKey()] = $addressBook->getDisplayName();
138
-			}
139
-
140
-			return $result;
141
-		}
142
-
143
-		/**
144
-		 * Return a list of the user's addressbooks
145
-		 *
146
-		 * @return IAddressBook[]
147
-		 * @since 16.0.0
148
-		 */
149
-		public function getUserAddressBooks(): array {
150
-			$this->loadAddressBooks();
151
-			return $this->addressBooks;
152
-		}
153
-
154
-		/**
155
-		 * removes all registered address book instances
156
-		 */
157
-		public function clear() {
158
-			$this->addressBooks = [];
159
-			$this->addressBookLoaders = [];
160
-		}
161
-
162
-		/**
163
-		 * @var \OCP\IAddressBook[] which holds all registered address books
164
-		 */
165
-		private $addressBooks = [];
166
-
167
-		/**
168
-		 * @var \Closure[] to call to load/register address books
169
-		 */
170
-		private $addressBookLoaders = [];
171
-
172
-		/**
173
-		 * In order to improve lazy loading a closure can be registered which will be called in case
174
-		 * address books are actually requested
175
-		 *
176
-		 * @param \Closure $callable
177
-		 */
178
-		public function register(\Closure $callable)
179
-		{
180
-			$this->addressBookLoaders[] = $callable;
181
-		}
182
-
183
-		/**
184
-		 * Get (and load when needed) the address book for $key
185
-		 *
186
-		 * @param string $addressBookKey
187
-		 * @return \OCP\IAddressBook
188
-		 */
189
-		protected function getAddressBook($addressBookKey)
190
-		{
191
-			$this->loadAddressBooks();
192
-			if (!array_key_exists($addressBookKey, $this->addressBooks)) {
193
-				return null;
194
-			}
195
-
196
-			return $this->addressBooks[$addressBookKey];
197
-		}
198
-
199
-		/**
200
-		 * Load all address books registered with 'register'
201
-		 */
202
-		protected function loadAddressBooks()
203
-		{
204
-			foreach($this->addressBookLoaders as $callable) {
205
-				$callable($this);
206
-			}
207
-			$this->addressBookLoaders = [];
208
-		}
209
-	}
33
+    class ContactsManager implements \OCP\Contacts\IManager {
34
+
35
+        /**
36
+         * This function is used to search and find contacts within the users address books.
37
+         * In case $pattern is empty all contacts will be returned.
38
+         *
39
+         * @param string $pattern which should match within the $searchProperties
40
+         * @param array $searchProperties defines the properties within the query pattern should match
41
+         * @param array $options = array() to define the search behavior
42
+         * 	- 'escape_like_param' - If set to false wildcards _ and % are not escaped
43
+         * @return array an array of contacts which are arrays of key-value-pairs
44
+         */
45
+        public function search($pattern, $searchProperties = [], $options = []) {
46
+            $this->loadAddressBooks();
47
+            $result = [];
48
+            foreach($this->addressBooks as $addressBook) {
49
+                $r = $addressBook->search($pattern, $searchProperties, $options);
50
+                $contacts = [];
51
+                foreach($r as $c){
52
+                    $c['addressbook-key'] = $addressBook->getKey();
53
+                    $contacts[] = $c;
54
+                }
55
+                $result = array_merge($result, $contacts);
56
+            }
57
+
58
+            return $result;
59
+        }
60
+
61
+        /**
62
+         * This function can be used to delete the contact identified by the given id
63
+         *
64
+         * @param object $id the unique identifier to a contact
65
+         * @param string $addressBookKey identifier of the address book in which the contact shall be deleted
66
+         * @return bool successful or not
67
+         */
68
+        public function delete($id, $addressBookKey) {
69
+            $addressBook = $this->getAddressBook($addressBookKey);
70
+            if (!$addressBook) {
71
+                return null;
72
+            }
73
+
74
+            if ($addressBook->getPermissions() & \OCP\Constants::PERMISSION_DELETE) {
75
+                return $addressBook->delete($id);
76
+            }
77
+
78
+            return null;
79
+        }
80
+
81
+        /**
82
+         * This function is used to create a new contact if 'id' is not given or not present.
83
+         * Otherwise the contact will be updated by replacing the entire data set.
84
+         *
85
+         * @param array $properties this array if key-value-pairs defines a contact
86
+         * @param string $addressBookKey identifier of the address book in which the contact shall be created or updated
87
+         * @return array representing the contact just created or updated
88
+         */
89
+        public function createOrUpdate($properties, $addressBookKey) {
90
+            $addressBook = $this->getAddressBook($addressBookKey);
91
+            if (!$addressBook) {
92
+                return null;
93
+            }
94
+
95
+            if ($addressBook->getPermissions() & \OCP\Constants::PERMISSION_CREATE) {
96
+                return $addressBook->createOrUpdate($properties);
97
+            }
98
+
99
+            return null;
100
+        }
101
+
102
+        /**
103
+         * Check if contacts are available (e.g. contacts app enabled)
104
+         *
105
+         * @return bool true if enabled, false if not
106
+         */
107
+        public function isEnabled() {
108
+            return !empty($this->addressBooks) || !empty($this->addressBookLoaders);
109
+        }
110
+
111
+        /**
112
+         * @param \OCP\IAddressBook $addressBook
113
+         */
114
+        public function registerAddressBook(\OCP\IAddressBook $addressBook) {
115
+            $this->addressBooks[$addressBook->getKey()] = $addressBook;
116
+        }
117
+
118
+        /**
119
+         * @param \OCP\IAddressBook $addressBook
120
+         */
121
+        public function unregisterAddressBook(\OCP\IAddressBook $addressBook) {
122
+            unset($this->addressBooks[$addressBook->getKey()]);
123
+        }
124
+
125
+        /**
126
+         * Return a list of the user's addressbooks display names
127
+         * ! The addressBook displayName are not unique, please use getUserAddressBooks
128
+         *
129
+         * @return array
130
+         * @since 6.0.0
131
+         * @deprecated 16.0.0 - Use `$this->getUserAddressBooks()` instead
132
+         */
133
+        public function getAddressBooks() {
134
+            $this->loadAddressBooks();
135
+            $result = [];
136
+            foreach($this->addressBooks as $addressBook) {
137
+                $result[$addressBook->getKey()] = $addressBook->getDisplayName();
138
+            }
139
+
140
+            return $result;
141
+        }
142
+
143
+        /**
144
+         * Return a list of the user's addressbooks
145
+         *
146
+         * @return IAddressBook[]
147
+         * @since 16.0.0
148
+         */
149
+        public function getUserAddressBooks(): array {
150
+            $this->loadAddressBooks();
151
+            return $this->addressBooks;
152
+        }
153
+
154
+        /**
155
+         * removes all registered address book instances
156
+         */
157
+        public function clear() {
158
+            $this->addressBooks = [];
159
+            $this->addressBookLoaders = [];
160
+        }
161
+
162
+        /**
163
+         * @var \OCP\IAddressBook[] which holds all registered address books
164
+         */
165
+        private $addressBooks = [];
166
+
167
+        /**
168
+         * @var \Closure[] to call to load/register address books
169
+         */
170
+        private $addressBookLoaders = [];
171
+
172
+        /**
173
+         * In order to improve lazy loading a closure can be registered which will be called in case
174
+         * address books are actually requested
175
+         *
176
+         * @param \Closure $callable
177
+         */
178
+        public function register(\Closure $callable)
179
+        {
180
+            $this->addressBookLoaders[] = $callable;
181
+        }
182
+
183
+        /**
184
+         * Get (and load when needed) the address book for $key
185
+         *
186
+         * @param string $addressBookKey
187
+         * @return \OCP\IAddressBook
188
+         */
189
+        protected function getAddressBook($addressBookKey)
190
+        {
191
+            $this->loadAddressBooks();
192
+            if (!array_key_exists($addressBookKey, $this->addressBooks)) {
193
+                return null;
194
+            }
195
+
196
+            return $this->addressBooks[$addressBookKey];
197
+        }
198
+
199
+        /**
200
+         * Load all address books registered with 'register'
201
+         */
202
+        protected function loadAddressBooks()
203
+        {
204
+            foreach($this->addressBookLoaders as $callable) {
205
+                $callable($this);
206
+            }
207
+            $this->addressBookLoaders = [];
208
+        }
209
+    }
210 210
 }
Please login to merge, or discard this patch.
lib/private/Color.php 1 patch
Indentation   +8 added lines, -8 removed lines patch added patch discarded remove patch
@@ -24,12 +24,12 @@
 block discarded – undo
24 24
 namespace OC;
25 25
 
26 26
 class Color {
27
-	public $r;
28
-	public $g;
29
-	public $b;
30
-	public function __construct($r, $g, $b) {
31
-		$this->r = $r;
32
-		$this->g = $g;
33
-		$this->b = $b;
34
-	}
27
+    public $r;
28
+    public $g;
29
+    public $b;
30
+    public function __construct($r, $g, $b) {
31
+        $this->r = $r;
32
+        $this->g = $g;
33
+        $this->b = $b;
34
+    }
35 35
 }
Please login to merge, or discard this patch.
lib/private/TemplateLayout.php 1 patch
Indentation   +309 added lines, -309 removed lines patch added patch discarded remove patch
@@ -53,313 +53,313 @@
 block discarded – undo
53 53
 
54 54
 class TemplateLayout extends \OC_Template {
55 55
 
56
-	private static $versionHash = '';
57
-
58
-	/**
59
-	 * @var \OCP\IConfig
60
-	 */
61
-	private $config;
62
-
63
-	/**
64
-	 * @param string $renderAs
65
-	 * @param string $appId application id
66
-	 */
67
-	public function __construct($renderAs, $appId = '') {
68
-
69
-		// yes - should be injected ....
70
-		$this->config = \OC::$server->getConfig();
71
-
72
-		if(\OCP\Util::isIE()) {
73
-			\OC_Util::addStyle('ie');
74
-		}
75
-
76
-		// Decide which page we show
77
-		if($renderAs === 'user') {
78
-			parent::__construct('core', 'layout.user');
79
-			if(in_array(\OC_App::getCurrentApp(), ['settings','admin', 'help']) !== false) {
80
-				$this->assign('bodyid', 'body-settings');
81
-			}else{
82
-				$this->assign('bodyid', 'body-user');
83
-			}
84
-
85
-			// Add navigation entry
86
-			$this->assign('application', '');
87
-			$this->assign('appid', $appId);
88
-			$navigation = \OC::$server->getNavigationManager()->getAll();
89
-			$this->assign('navigation', $navigation);
90
-			$settingsNavigation = \OC::$server->getNavigationManager()->getAll('settings');
91
-			$this->assign('settingsnavigation', $settingsNavigation);
92
-			foreach($navigation as $entry) {
93
-				if ($entry['active']) {
94
-					$this->assign('application', $entry['name']);
95
-					break;
96
-				}
97
-			}
98
-
99
-			foreach($settingsNavigation as $entry) {
100
-				if ($entry['active']) {
101
-					$this->assign('application', $entry['name']);
102
-					break;
103
-				}
104
-			}
105
-			$userDisplayName = \OC_User::getDisplayName();
106
-			$this->assign('user_displayname', $userDisplayName);
107
-			$this->assign('user_uid', \OC_User::getUser());
108
-
109
-			if (\OC_User::getUser() === false) {
110
-				$this->assign('userAvatarSet', false);
111
-			} else {
112
-				$this->assign('userAvatarSet', \OC::$server->getAvatarManager()->getAvatar(\OC_User::getUser())->exists());
113
-				$this->assign('userAvatarVersion', $this->config->getUserValue(\OC_User::getUser(), 'avatar', 'version', 0));
114
-			}
115
-
116
-			// check if app menu icons should be inverted
117
-			try {
118
-				/** @var \OCA\Theming\Util $util */
119
-				$util = \OC::$server->query(\OCA\Theming\Util::class);
120
-				$this->assign('themingInvertMenu', $util->invertTextColor(\OC::$server->getThemingDefaults()->getColorPrimary()));
121
-			} catch (\OCP\AppFramework\QueryException $e) {
122
-				$this->assign('themingInvertMenu', false);
123
-			} catch (\OCP\AutoloadNotAllowedException $e) {
124
-				$this->assign('themingInvertMenu', false);
125
-			}
126
-
127
-		} else if ($renderAs === 'error') {
128
-			parent::__construct('core', 'layout.guest', '', false);
129
-			$this->assign('bodyid', 'body-login');
130
-			$this->assign('user_displayname', '');
131
-			$this->assign('user_uid', '');
132
-		} else if ($renderAs === 'guest') {
133
-			parent::__construct('core', 'layout.guest');
134
-			\OC_Util::addStyle('guest');
135
-			$this->assign('bodyid', 'body-login');
136
-
137
-			$userDisplayName = \OC_User::getDisplayName();
138
-			$this->assign('user_displayname', $userDisplayName);
139
-			$this->assign('user_uid', \OC_User::getUser());
140
-		} else if ($renderAs === 'public') {
141
-			parent::__construct('core', 'layout.public');
142
-			$this->assign('appid', $appId);
143
-			$this->assign('bodyid', 'body-public');
144
-
145
-			/** @var IRegistry $subscription */
146
-			$subscription = \OC::$server->query(IRegistry::class);
147
-			$showSimpleSignup = $this->config->getSystemValueBool('simpleSignUpLink.shown', true);
148
-			if ($showSimpleSignup && $subscription->delegateHasValidSubscription()) {
149
-				$showSimpleSignup = false;
150
-			}
151
-			$this->assign('showSimpleSignUpLink', $showSimpleSignup);
152
-		} else {
153
-			parent::__construct('core', 'layout.base');
154
-
155
-		}
156
-		// Send the language and the locale to our layouts
157
-		$lang = \OC::$server->getL10NFactory()->findLanguage();
158
-		$locale = \OC::$server->getL10NFactory()->findLocale($lang);
159
-
160
-		$lang = str_replace('_', '-', $lang);
161
-		$this->assign('language', $lang);
162
-		$this->assign('locale', $locale);
163
-
164
-		if(\OC::$server->getSystemConfig()->getValue('installed', false)) {
165
-			if (empty(self::$versionHash)) {
166
-				$v = \OC_App::getAppVersions();
167
-				$v['core'] = implode('.', \OCP\Util::getVersion());
168
-				self::$versionHash = substr(md5(implode(',', $v)), 0, 8);
169
-			}
170
-		} else {
171
-			self::$versionHash = md5('not installed');
172
-		}
173
-
174
-		// Add the js files
175
-		$jsFiles = self::findJavascriptFiles(\OC_Util::$scripts);
176
-		$this->assign('jsfiles', []);
177
-		if ($this->config->getSystemValue('installed', false) && $renderAs != 'error') {
178
-			if (\OC::$server->getContentSecurityPolicyNonceManager()->browserSupportsCspV3()) {
179
-				$jsConfigHelper = new JSConfigHelper(
180
-					\OC::$server->getL10N('lib'),
181
-					\OC::$server->query(Defaults::class),
182
-					\OC::$server->getAppManager(),
183
-					\OC::$server->getSession(),
184
-					\OC::$server->getUserSession()->getUser(),
185
-					$this->config,
186
-					\OC::$server->getGroupManager(),
187
-					\OC::$server->getIniWrapper(),
188
-					\OC::$server->getURLGenerator(),
189
-					\OC::$server->getCapabilitiesManager()
190
-				);
191
-				$this->assign('inline_ocjs', $jsConfigHelper->getConfig());
192
-			} else {
193
-				$this->append('jsfiles', \OC::$server->getURLGenerator()->linkToRoute('core.OCJS.getConfig', ['v' => self::$versionHash]));
194
-			}
195
-		}
196
-		foreach($jsFiles as $info) {
197
-			$web = $info[1];
198
-			$file = $info[2];
199
-			$this->append('jsfiles', $web.'/'.$file . $this->getVersionHashSuffix());
200
-		}
201
-
202
-		try {
203
-			$pathInfo = \OC::$server->getRequest()->getPathInfo();
204
-		} catch (\Exception $e) {
205
-			$pathInfo = '';
206
-		}
207
-
208
-		// Do not initialise scss appdata until we have a fully installed instance
209
-		// Do not load scss for update, errors, installation or login page
210
-		if(\OC::$server->getSystemConfig()->getValue('installed', false)
211
-			&& !\OCP\Util::needUpgrade()
212
-			&& $pathInfo !== ''
213
-			&& !preg_match('/^\/login/', $pathInfo)
214
-			&& $renderAs !== 'error'
215
-		) {
216
-			$cssFiles = self::findStylesheetFiles(\OC_Util::$styles);
217
-		} else {
218
-			// If we ignore the scss compiler,
219
-			// we need to load the guest css fallback
220
-			\OC_Util::addStyle('guest');
221
-			$cssFiles = self::findStylesheetFiles(\OC_Util::$styles, false);
222
-		}
223
-
224
-		$this->assign('cssfiles', []);
225
-		$this->assign('printcssfiles', []);
226
-		$this->assign('versionHash', self::$versionHash);
227
-		foreach($cssFiles as $info) {
228
-			$web = $info[1];
229
-			$file = $info[2];
230
-
231
-			if (substr($file, -strlen('print.css')) === 'print.css') {
232
-				$this->append('printcssfiles', $web.'/'.$file . $this->getVersionHashSuffix());
233
-			} else {
234
-				$suffix = $this->getVersionHashSuffix($web, $file);
235
-
236
-				if (strpos($file, '?v=') == false) {
237
-					$this->append('cssfiles', $web.'/'.$file . $suffix);
238
-				} else {
239
-					$this->append('cssfiles', $web.'/'.$file . '-' . substr($suffix, 3));
240
-				}
241
-
242
-			}
243
-		}
244
-
245
-		/** @var InitialStateService $initialState */
246
-		$initialState = \OC::$server->query(InitialStateService::class);
247
-		$this->assign('initialStates', $initialState->getInitialStates());
248
-	}
249
-
250
-	/**
251
-	 * @param string $path
252
-	 * @param string $file
253
-	 * @return string
254
-	 */
255
-	protected function getVersionHashSuffix($path = false, $file = false) {
256
-		if ($this->config->getSystemValue('debug', false)) {
257
-			// allows chrome workspace mapping in debug mode
258
-			return "";
259
-		}
260
-		$themingSuffix = '';
261
-		$v = [];
262
-
263
-		if ($this->config->getSystemValue('installed', false)) {
264
-			if (\OC::$server->getAppManager()->isInstalled('theming')) {
265
-				$themingSuffix = '-' . $this->config->getAppValue('theming', 'cachebuster', '0');
266
-			}
267
-			$v = \OC_App::getAppVersions();
268
-		}
269
-
270
-		// Try the webroot path for a match
271
-		if ($path !== false && $path !== '') {
272
-			$appName = $this->getAppNamefromPath($path);
273
-			if(array_key_exists($appName, $v)) {
274
-				$appVersion = $v[$appName];
275
-				return '?v=' . substr(md5($appVersion), 0, 8) . $themingSuffix;
276
-			}
277
-		}
278
-		// fallback to the file path instead
279
-		if ($file !== false && $file !== '') {
280
-			$appName = $this->getAppNamefromPath($file);
281
-			if(array_key_exists($appName, $v)) {
282
-				$appVersion = $v[$appName];
283
-				return '?v=' . substr(md5($appVersion), 0, 8) . $themingSuffix;
284
-			}
285
-		}
286
-
287
-		return '?v=' . self::$versionHash . $themingSuffix;
288
-	}
289
-
290
-	/**
291
-	 * @param array $styles
292
-	 * @return array
293
-	 */
294
-	static public function findStylesheetFiles($styles, $compileScss = true) {
295
-		// Read the selected theme from the config file
296
-		$theme = \OC_Util::getTheme();
297
-
298
-		if($compileScss) {
299
-			$SCSSCacher = \OC::$server->query(SCSSCacher::class);
300
-		} else {
301
-			$SCSSCacher = null;
302
-		}
303
-
304
-		$locator = new \OC\Template\CSSResourceLocator(
305
-			\OC::$server->getLogger(),
306
-			$theme,
307
-			[ \OC::$SERVERROOT => \OC::$WEBROOT ],
308
-			[ \OC::$SERVERROOT => \OC::$WEBROOT ],
309
-			$SCSSCacher
310
-		);
311
-		$locator->find($styles);
312
-		return $locator->getResources();
313
-	}
314
-
315
-	/**
316
-	 * @param string $path
317
-	 * @return string|boolean
318
-	 */
319
-	public function getAppNamefromPath($path) {
320
-		if ($path !== '' && is_string($path)) {
321
-			$pathParts = explode('/', $path);
322
-			if ($pathParts[0] === 'css') {
323
-				// This is a scss request
324
-				return $pathParts[1];
325
-			}
326
-			return end($pathParts);
327
-		}
328
-		return false;
329
-
330
-	}
331
-
332
-	/**
333
-	 * @param array $scripts
334
-	 * @return array
335
-	 */
336
-	static public function findJavascriptFiles($scripts) {
337
-		// Read the selected theme from the config file
338
-		$theme = \OC_Util::getTheme();
339
-
340
-		$locator = new \OC\Template\JSResourceLocator(
341
-			\OC::$server->getLogger(),
342
-			$theme,
343
-			[ \OC::$SERVERROOT => \OC::$WEBROOT ],
344
-			[ \OC::$SERVERROOT => \OC::$WEBROOT ],
345
-			\OC::$server->query(JSCombiner::class)
346
-			);
347
-		$locator->find($scripts);
348
-		return $locator->getResources();
349
-	}
350
-
351
-	/**
352
-	 * Converts the absolute file path to a relative path from \OC::$SERVERROOT
353
-	 * @param string $filePath Absolute path
354
-	 * @return string Relative path
355
-	 * @throws \Exception If $filePath is not under \OC::$SERVERROOT
356
-	 */
357
-	public static function convertToRelativePath($filePath) {
358
-		$relativePath = explode(\OC::$SERVERROOT, $filePath);
359
-		if(count($relativePath) !== 2) {
360
-			throw new \Exception('$filePath is not under the \OC::$SERVERROOT');
361
-		}
362
-
363
-		return $relativePath[1];
364
-	}
56
+    private static $versionHash = '';
57
+
58
+    /**
59
+     * @var \OCP\IConfig
60
+     */
61
+    private $config;
62
+
63
+    /**
64
+     * @param string $renderAs
65
+     * @param string $appId application id
66
+     */
67
+    public function __construct($renderAs, $appId = '') {
68
+
69
+        // yes - should be injected ....
70
+        $this->config = \OC::$server->getConfig();
71
+
72
+        if(\OCP\Util::isIE()) {
73
+            \OC_Util::addStyle('ie');
74
+        }
75
+
76
+        // Decide which page we show
77
+        if($renderAs === 'user') {
78
+            parent::__construct('core', 'layout.user');
79
+            if(in_array(\OC_App::getCurrentApp(), ['settings','admin', 'help']) !== false) {
80
+                $this->assign('bodyid', 'body-settings');
81
+            }else{
82
+                $this->assign('bodyid', 'body-user');
83
+            }
84
+
85
+            // Add navigation entry
86
+            $this->assign('application', '');
87
+            $this->assign('appid', $appId);
88
+            $navigation = \OC::$server->getNavigationManager()->getAll();
89
+            $this->assign('navigation', $navigation);
90
+            $settingsNavigation = \OC::$server->getNavigationManager()->getAll('settings');
91
+            $this->assign('settingsnavigation', $settingsNavigation);
92
+            foreach($navigation as $entry) {
93
+                if ($entry['active']) {
94
+                    $this->assign('application', $entry['name']);
95
+                    break;
96
+                }
97
+            }
98
+
99
+            foreach($settingsNavigation as $entry) {
100
+                if ($entry['active']) {
101
+                    $this->assign('application', $entry['name']);
102
+                    break;
103
+                }
104
+            }
105
+            $userDisplayName = \OC_User::getDisplayName();
106
+            $this->assign('user_displayname', $userDisplayName);
107
+            $this->assign('user_uid', \OC_User::getUser());
108
+
109
+            if (\OC_User::getUser() === false) {
110
+                $this->assign('userAvatarSet', false);
111
+            } else {
112
+                $this->assign('userAvatarSet', \OC::$server->getAvatarManager()->getAvatar(\OC_User::getUser())->exists());
113
+                $this->assign('userAvatarVersion', $this->config->getUserValue(\OC_User::getUser(), 'avatar', 'version', 0));
114
+            }
115
+
116
+            // check if app menu icons should be inverted
117
+            try {
118
+                /** @var \OCA\Theming\Util $util */
119
+                $util = \OC::$server->query(\OCA\Theming\Util::class);
120
+                $this->assign('themingInvertMenu', $util->invertTextColor(\OC::$server->getThemingDefaults()->getColorPrimary()));
121
+            } catch (\OCP\AppFramework\QueryException $e) {
122
+                $this->assign('themingInvertMenu', false);
123
+            } catch (\OCP\AutoloadNotAllowedException $e) {
124
+                $this->assign('themingInvertMenu', false);
125
+            }
126
+
127
+        } else if ($renderAs === 'error') {
128
+            parent::__construct('core', 'layout.guest', '', false);
129
+            $this->assign('bodyid', 'body-login');
130
+            $this->assign('user_displayname', '');
131
+            $this->assign('user_uid', '');
132
+        } else if ($renderAs === 'guest') {
133
+            parent::__construct('core', 'layout.guest');
134
+            \OC_Util::addStyle('guest');
135
+            $this->assign('bodyid', 'body-login');
136
+
137
+            $userDisplayName = \OC_User::getDisplayName();
138
+            $this->assign('user_displayname', $userDisplayName);
139
+            $this->assign('user_uid', \OC_User::getUser());
140
+        } else if ($renderAs === 'public') {
141
+            parent::__construct('core', 'layout.public');
142
+            $this->assign('appid', $appId);
143
+            $this->assign('bodyid', 'body-public');
144
+
145
+            /** @var IRegistry $subscription */
146
+            $subscription = \OC::$server->query(IRegistry::class);
147
+            $showSimpleSignup = $this->config->getSystemValueBool('simpleSignUpLink.shown', true);
148
+            if ($showSimpleSignup && $subscription->delegateHasValidSubscription()) {
149
+                $showSimpleSignup = false;
150
+            }
151
+            $this->assign('showSimpleSignUpLink', $showSimpleSignup);
152
+        } else {
153
+            parent::__construct('core', 'layout.base');
154
+
155
+        }
156
+        // Send the language and the locale to our layouts
157
+        $lang = \OC::$server->getL10NFactory()->findLanguage();
158
+        $locale = \OC::$server->getL10NFactory()->findLocale($lang);
159
+
160
+        $lang = str_replace('_', '-', $lang);
161
+        $this->assign('language', $lang);
162
+        $this->assign('locale', $locale);
163
+
164
+        if(\OC::$server->getSystemConfig()->getValue('installed', false)) {
165
+            if (empty(self::$versionHash)) {
166
+                $v = \OC_App::getAppVersions();
167
+                $v['core'] = implode('.', \OCP\Util::getVersion());
168
+                self::$versionHash = substr(md5(implode(',', $v)), 0, 8);
169
+            }
170
+        } else {
171
+            self::$versionHash = md5('not installed');
172
+        }
173
+
174
+        // Add the js files
175
+        $jsFiles = self::findJavascriptFiles(\OC_Util::$scripts);
176
+        $this->assign('jsfiles', []);
177
+        if ($this->config->getSystemValue('installed', false) && $renderAs != 'error') {
178
+            if (\OC::$server->getContentSecurityPolicyNonceManager()->browserSupportsCspV3()) {
179
+                $jsConfigHelper = new JSConfigHelper(
180
+                    \OC::$server->getL10N('lib'),
181
+                    \OC::$server->query(Defaults::class),
182
+                    \OC::$server->getAppManager(),
183
+                    \OC::$server->getSession(),
184
+                    \OC::$server->getUserSession()->getUser(),
185
+                    $this->config,
186
+                    \OC::$server->getGroupManager(),
187
+                    \OC::$server->getIniWrapper(),
188
+                    \OC::$server->getURLGenerator(),
189
+                    \OC::$server->getCapabilitiesManager()
190
+                );
191
+                $this->assign('inline_ocjs', $jsConfigHelper->getConfig());
192
+            } else {
193
+                $this->append('jsfiles', \OC::$server->getURLGenerator()->linkToRoute('core.OCJS.getConfig', ['v' => self::$versionHash]));
194
+            }
195
+        }
196
+        foreach($jsFiles as $info) {
197
+            $web = $info[1];
198
+            $file = $info[2];
199
+            $this->append('jsfiles', $web.'/'.$file . $this->getVersionHashSuffix());
200
+        }
201
+
202
+        try {
203
+            $pathInfo = \OC::$server->getRequest()->getPathInfo();
204
+        } catch (\Exception $e) {
205
+            $pathInfo = '';
206
+        }
207
+
208
+        // Do not initialise scss appdata until we have a fully installed instance
209
+        // Do not load scss for update, errors, installation or login page
210
+        if(\OC::$server->getSystemConfig()->getValue('installed', false)
211
+            && !\OCP\Util::needUpgrade()
212
+            && $pathInfo !== ''
213
+            && !preg_match('/^\/login/', $pathInfo)
214
+            && $renderAs !== 'error'
215
+        ) {
216
+            $cssFiles = self::findStylesheetFiles(\OC_Util::$styles);
217
+        } else {
218
+            // If we ignore the scss compiler,
219
+            // we need to load the guest css fallback
220
+            \OC_Util::addStyle('guest');
221
+            $cssFiles = self::findStylesheetFiles(\OC_Util::$styles, false);
222
+        }
223
+
224
+        $this->assign('cssfiles', []);
225
+        $this->assign('printcssfiles', []);
226
+        $this->assign('versionHash', self::$versionHash);
227
+        foreach($cssFiles as $info) {
228
+            $web = $info[1];
229
+            $file = $info[2];
230
+
231
+            if (substr($file, -strlen('print.css')) === 'print.css') {
232
+                $this->append('printcssfiles', $web.'/'.$file . $this->getVersionHashSuffix());
233
+            } else {
234
+                $suffix = $this->getVersionHashSuffix($web, $file);
235
+
236
+                if (strpos($file, '?v=') == false) {
237
+                    $this->append('cssfiles', $web.'/'.$file . $suffix);
238
+                } else {
239
+                    $this->append('cssfiles', $web.'/'.$file . '-' . substr($suffix, 3));
240
+                }
241
+
242
+            }
243
+        }
244
+
245
+        /** @var InitialStateService $initialState */
246
+        $initialState = \OC::$server->query(InitialStateService::class);
247
+        $this->assign('initialStates', $initialState->getInitialStates());
248
+    }
249
+
250
+    /**
251
+     * @param string $path
252
+     * @param string $file
253
+     * @return string
254
+     */
255
+    protected function getVersionHashSuffix($path = false, $file = false) {
256
+        if ($this->config->getSystemValue('debug', false)) {
257
+            // allows chrome workspace mapping in debug mode
258
+            return "";
259
+        }
260
+        $themingSuffix = '';
261
+        $v = [];
262
+
263
+        if ($this->config->getSystemValue('installed', false)) {
264
+            if (\OC::$server->getAppManager()->isInstalled('theming')) {
265
+                $themingSuffix = '-' . $this->config->getAppValue('theming', 'cachebuster', '0');
266
+            }
267
+            $v = \OC_App::getAppVersions();
268
+        }
269
+
270
+        // Try the webroot path for a match
271
+        if ($path !== false && $path !== '') {
272
+            $appName = $this->getAppNamefromPath($path);
273
+            if(array_key_exists($appName, $v)) {
274
+                $appVersion = $v[$appName];
275
+                return '?v=' . substr(md5($appVersion), 0, 8) . $themingSuffix;
276
+            }
277
+        }
278
+        // fallback to the file path instead
279
+        if ($file !== false && $file !== '') {
280
+            $appName = $this->getAppNamefromPath($file);
281
+            if(array_key_exists($appName, $v)) {
282
+                $appVersion = $v[$appName];
283
+                return '?v=' . substr(md5($appVersion), 0, 8) . $themingSuffix;
284
+            }
285
+        }
286
+
287
+        return '?v=' . self::$versionHash . $themingSuffix;
288
+    }
289
+
290
+    /**
291
+     * @param array $styles
292
+     * @return array
293
+     */
294
+    static public function findStylesheetFiles($styles, $compileScss = true) {
295
+        // Read the selected theme from the config file
296
+        $theme = \OC_Util::getTheme();
297
+
298
+        if($compileScss) {
299
+            $SCSSCacher = \OC::$server->query(SCSSCacher::class);
300
+        } else {
301
+            $SCSSCacher = null;
302
+        }
303
+
304
+        $locator = new \OC\Template\CSSResourceLocator(
305
+            \OC::$server->getLogger(),
306
+            $theme,
307
+            [ \OC::$SERVERROOT => \OC::$WEBROOT ],
308
+            [ \OC::$SERVERROOT => \OC::$WEBROOT ],
309
+            $SCSSCacher
310
+        );
311
+        $locator->find($styles);
312
+        return $locator->getResources();
313
+    }
314
+
315
+    /**
316
+     * @param string $path
317
+     * @return string|boolean
318
+     */
319
+    public function getAppNamefromPath($path) {
320
+        if ($path !== '' && is_string($path)) {
321
+            $pathParts = explode('/', $path);
322
+            if ($pathParts[0] === 'css') {
323
+                // This is a scss request
324
+                return $pathParts[1];
325
+            }
326
+            return end($pathParts);
327
+        }
328
+        return false;
329
+
330
+    }
331
+
332
+    /**
333
+     * @param array $scripts
334
+     * @return array
335
+     */
336
+    static public function findJavascriptFiles($scripts) {
337
+        // Read the selected theme from the config file
338
+        $theme = \OC_Util::getTheme();
339
+
340
+        $locator = new \OC\Template\JSResourceLocator(
341
+            \OC::$server->getLogger(),
342
+            $theme,
343
+            [ \OC::$SERVERROOT => \OC::$WEBROOT ],
344
+            [ \OC::$SERVERROOT => \OC::$WEBROOT ],
345
+            \OC::$server->query(JSCombiner::class)
346
+            );
347
+        $locator->find($scripts);
348
+        return $locator->getResources();
349
+    }
350
+
351
+    /**
352
+     * Converts the absolute file path to a relative path from \OC::$SERVERROOT
353
+     * @param string $filePath Absolute path
354
+     * @return string Relative path
355
+     * @throws \Exception If $filePath is not under \OC::$SERVERROOT
356
+     */
357
+    public static function convertToRelativePath($filePath) {
358
+        $relativePath = explode(\OC::$SERVERROOT, $filePath);
359
+        if(count($relativePath) !== 2) {
360
+            throw new \Exception('$filePath is not under the \OC::$SERVERROOT');
361
+        }
362
+
363
+        return $relativePath[1];
364
+    }
365 365
 }
Please login to merge, or discard this patch.
lib/private/DB/Connection.php 1 patch
Indentation   +406 added lines, -406 removed lines patch added patch discarded remove patch
@@ -47,410 +47,410 @@
 block discarded – undo
47 47
 use OCP\PreConditionNotMetException;
48 48
 
49 49
 class Connection extends ReconnectWrapper implements IDBConnection {
50
-	/**
51
-	 * @var string $tablePrefix
52
-	 */
53
-	protected $tablePrefix;
54
-
55
-	/**
56
-	 * @var \OC\DB\Adapter $adapter
57
-	 */
58
-	protected $adapter;
59
-
60
-	protected $lockedTable = null;
61
-
62
-	public function connect() {
63
-		try {
64
-			return parent::connect();
65
-		} catch (DBALException $e) {
66
-			// throw a new exception to prevent leaking info from the stacktrace
67
-			throw new DBALException('Failed to connect to the database: ' . $e->getMessage(), $e->getCode());
68
-		}
69
-	}
70
-
71
-	/**
72
-	 * Returns a QueryBuilder for the connection.
73
-	 *
74
-	 * @return \OCP\DB\QueryBuilder\IQueryBuilder
75
-	 */
76
-	public function getQueryBuilder() {
77
-		return new QueryBuilder(
78
-			$this,
79
-			\OC::$server->getSystemConfig(),
80
-			\OC::$server->getLogger()
81
-		);
82
-	}
83
-
84
-	/**
85
-	 * Gets the QueryBuilder for the connection.
86
-	 *
87
-	 * @return \Doctrine\DBAL\Query\QueryBuilder
88
-	 * @deprecated please use $this->getQueryBuilder() instead
89
-	 */
90
-	public function createQueryBuilder() {
91
-		$backtrace = $this->getCallerBacktrace();
92
-		\OC::$server->getLogger()->debug('Doctrine QueryBuilder retrieved in {backtrace}', ['app' => 'core', 'backtrace' => $backtrace]);
93
-		return parent::createQueryBuilder();
94
-	}
95
-
96
-	/**
97
-	 * Gets the ExpressionBuilder for the connection.
98
-	 *
99
-	 * @return \Doctrine\DBAL\Query\Expression\ExpressionBuilder
100
-	 * @deprecated please use $this->getQueryBuilder()->expr() instead
101
-	 */
102
-	public function getExpressionBuilder() {
103
-		$backtrace = $this->getCallerBacktrace();
104
-		\OC::$server->getLogger()->debug('Doctrine ExpressionBuilder retrieved in {backtrace}', ['app' => 'core', 'backtrace' => $backtrace]);
105
-		return parent::getExpressionBuilder();
106
-	}
107
-
108
-	/**
109
-	 * Get the file and line that called the method where `getCallerBacktrace()` was used
110
-	 *
111
-	 * @return string
112
-	 */
113
-	protected function getCallerBacktrace() {
114
-		$traces = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
115
-
116
-		// 0 is the method where we use `getCallerBacktrace`
117
-		// 1 is the target method which uses the method we want to log
118
-		if (isset($traces[1])) {
119
-			return $traces[1]['file'] . ':' . $traces[1]['line'];
120
-		}
121
-
122
-		return '';
123
-	}
124
-
125
-	/**
126
-	 * @return string
127
-	 */
128
-	public function getPrefix() {
129
-		return $this->tablePrefix;
130
-	}
131
-
132
-	/**
133
-	 * Initializes a new instance of the Connection class.
134
-	 *
135
-	 * @param array $params  The connection parameters.
136
-	 * @param \Doctrine\DBAL\Driver $driver
137
-	 * @param \Doctrine\DBAL\Configuration $config
138
-	 * @param \Doctrine\Common\EventManager $eventManager
139
-	 * @throws \Exception
140
-	 */
141
-	public function __construct(array $params, Driver $driver, Configuration $config = null,
142
-		EventManager $eventManager = null)
143
-	{
144
-		if (!isset($params['adapter'])) {
145
-			throw new \Exception('adapter not set');
146
-		}
147
-		if (!isset($params['tablePrefix'])) {
148
-			throw new \Exception('tablePrefix not set');
149
-		}
150
-		parent::__construct($params, $driver, $config, $eventManager);
151
-		$this->adapter = new $params['adapter']($this);
152
-		$this->tablePrefix = $params['tablePrefix'];
153
-	}
154
-
155
-	/**
156
-	 * Prepares an SQL statement.
157
-	 *
158
-	 * @param string $statement The SQL statement to prepare.
159
-	 * @param int $limit
160
-	 * @param int $offset
161
-	 * @return \Doctrine\DBAL\Driver\Statement The prepared statement.
162
-	 */
163
-	public function prepare($statement, $limit=null, $offset=null) {
164
-		if ($limit === -1) {
165
-			$limit = null;
166
-		}
167
-		if (!is_null($limit)) {
168
-			$platform = $this->getDatabasePlatform();
169
-			$statement = $platform->modifyLimitQuery($statement, $limit, $offset);
170
-		}
171
-		$statement = $this->replaceTablePrefix($statement);
172
-		$statement = $this->adapter->fixupStatement($statement);
173
-
174
-		return parent::prepare($statement);
175
-	}
176
-
177
-	/**
178
-	 * Executes an, optionally parametrized, SQL query.
179
-	 *
180
-	 * If the query is parametrized, a prepared statement is used.
181
-	 * If an SQLLogger is configured, the execution is logged.
182
-	 *
183
-	 * @param string                                      $query  The SQL query to execute.
184
-	 * @param array                                       $params The parameters to bind to the query, if any.
185
-	 * @param array                                       $types  The types the previous parameters are in.
186
-	 * @param \Doctrine\DBAL\Cache\QueryCacheProfile|null $qcp    The query cache profile, optional.
187
-	 *
188
-	 * @return \Doctrine\DBAL\Driver\Statement The executed statement.
189
-	 *
190
-	 * @throws \Doctrine\DBAL\DBALException
191
-	 */
192
-	public function executeQuery($query, array $params = [], $types = [], QueryCacheProfile $qcp = null)
193
-	{
194
-		$query = $this->replaceTablePrefix($query);
195
-		$query = $this->adapter->fixupStatement($query);
196
-		return parent::executeQuery($query, $params, $types, $qcp);
197
-	}
198
-
199
-	/**
200
-	 * Executes an SQL INSERT/UPDATE/DELETE query with the given parameters
201
-	 * and returns the number of affected rows.
202
-	 *
203
-	 * This method supports PDO binding types as well as DBAL mapping types.
204
-	 *
205
-	 * @param string $query  The SQL query.
206
-	 * @param array  $params The query parameters.
207
-	 * @param array  $types  The parameter types.
208
-	 *
209
-	 * @return integer The number of affected rows.
210
-	 *
211
-	 * @throws \Doctrine\DBAL\DBALException
212
-	 */
213
-	public function executeUpdate($query, array $params = [], array $types = [])
214
-	{
215
-		$query = $this->replaceTablePrefix($query);
216
-		$query = $this->adapter->fixupStatement($query);
217
-		return parent::executeUpdate($query, $params, $types);
218
-	}
219
-
220
-	/**
221
-	 * Returns the ID of the last inserted row, or the last value from a sequence object,
222
-	 * depending on the underlying driver.
223
-	 *
224
-	 * Note: This method may not return a meaningful or consistent result across different drivers,
225
-	 * because the underlying database may not even support the notion of AUTO_INCREMENT/IDENTITY
226
-	 * columns or sequences.
227
-	 *
228
-	 * @param string $seqName Name of the sequence object from which the ID should be returned.
229
-	 * @return string A string representation of the last inserted ID.
230
-	 */
231
-	public function lastInsertId($seqName = null) {
232
-		if ($seqName) {
233
-			$seqName = $this->replaceTablePrefix($seqName);
234
-		}
235
-		return $this->adapter->lastInsertId($seqName);
236
-	}
237
-
238
-	// internal use
239
-	public function realLastInsertId($seqName = null) {
240
-		return parent::lastInsertId($seqName);
241
-	}
242
-
243
-	/**
244
-	 * Insert a row if the matching row does not exists. To accomplish proper race condition avoidance
245
-	 * it is needed that there is also a unique constraint on the values. Then this method will
246
-	 * catch the exception and return 0.
247
-	 *
248
-	 * @param string $table The table name (will replace *PREFIX* with the actual prefix)
249
-	 * @param array $input data that should be inserted into the table  (column name => value)
250
-	 * @param array|null $compare List of values that should be checked for "if not exists"
251
-	 *				If this is null or an empty array, all keys of $input will be compared
252
-	 *				Please note: text fields (clob) must not be used in the compare array
253
-	 * @return int number of inserted rows
254
-	 * @throws \Doctrine\DBAL\DBALException
255
-	 * @deprecated 15.0.0 - use unique index and "try { $db->insert() } catch (UniqueConstraintViolationException $e) {}" instead, because it is more reliable and does not have the risk for deadlocks - see https://github.com/nextcloud/server/pull/12371
256
-	 */
257
-	public function insertIfNotExist($table, $input, array $compare = null) {
258
-		return $this->adapter->insertIfNotExist($table, $input, $compare);
259
-	}
260
-
261
-	public function insertIgnoreConflict(string $table, array $values) : int {
262
-		return $this->adapter->insertIgnoreConflict($table, $values);
263
-	}
264
-
265
-	private function getType($value) {
266
-		if (is_bool($value)) {
267
-			return IQueryBuilder::PARAM_BOOL;
268
-		} else if (is_int($value)) {
269
-			return IQueryBuilder::PARAM_INT;
270
-		} else {
271
-			return IQueryBuilder::PARAM_STR;
272
-		}
273
-	}
274
-
275
-	/**
276
-	 * Insert or update a row value
277
-	 *
278
-	 * @param string $table
279
-	 * @param array $keys (column name => value)
280
-	 * @param array $values (column name => value)
281
-	 * @param array $updatePreconditionValues ensure values match preconditions (column name => value)
282
-	 * @return int number of new rows
283
-	 * @throws \Doctrine\DBAL\DBALException
284
-	 * @throws PreConditionNotMetException
285
-	 * @suppress SqlInjectionChecker
286
-	 */
287
-	public function setValues($table, array $keys, array $values, array $updatePreconditionValues = []) {
288
-		try {
289
-			$insertQb = $this->getQueryBuilder();
290
-			$insertQb->insert($table)
291
-				->values(
292
-					array_map(function ($value) use ($insertQb) {
293
-						return $insertQb->createNamedParameter($value, $this->getType($value));
294
-					}, array_merge($keys, $values))
295
-				);
296
-			return $insertQb->execute();
297
-		} catch (ConstraintViolationException $e) {
298
-			// value already exists, try update
299
-			$updateQb = $this->getQueryBuilder();
300
-			$updateQb->update($table);
301
-			foreach ($values as $name => $value) {
302
-				$updateQb->set($name, $updateQb->createNamedParameter($value, $this->getType($value)));
303
-			}
304
-			$where = $updateQb->expr()->andX();
305
-			$whereValues = array_merge($keys, $updatePreconditionValues);
306
-			foreach ($whereValues as $name => $value) {
307
-				$where->add($updateQb->expr()->eq(
308
-					$name,
309
-					$updateQb->createNamedParameter($value, $this->getType($value)),
310
-					$this->getType($value)
311
-				));
312
-			}
313
-			$updateQb->where($where);
314
-			$affected = $updateQb->execute();
315
-
316
-			if ($affected === 0 && !empty($updatePreconditionValues)) {
317
-				throw new PreConditionNotMetException();
318
-			}
319
-
320
-			return 0;
321
-		}
322
-	}
323
-
324
-	/**
325
-	 * Create an exclusive read+write lock on a table
326
-	 *
327
-	 * @param string $tableName
328
-	 * @throws \BadMethodCallException When trying to acquire a second lock
329
-	 * @since 9.1.0
330
-	 */
331
-	public function lockTable($tableName) {
332
-		if ($this->lockedTable !== null) {
333
-			throw new \BadMethodCallException('Can not lock a new table until the previous lock is released.');
334
-		}
335
-
336
-		$tableName = $this->tablePrefix . $tableName;
337
-		$this->lockedTable = $tableName;
338
-		$this->adapter->lockTable($tableName);
339
-	}
340
-
341
-	/**
342
-	 * Release a previous acquired lock again
343
-	 *
344
-	 * @since 9.1.0
345
-	 */
346
-	public function unlockTable() {
347
-		$this->adapter->unlockTable();
348
-		$this->lockedTable = null;
349
-	}
350
-
351
-	/**
352
-	 * returns the error code and message as a string for logging
353
-	 * works with DoctrineException
354
-	 * @return string
355
-	 */
356
-	public function getError() {
357
-		$msg = $this->errorCode() . ': ';
358
-		$errorInfo = $this->errorInfo();
359
-		if (is_array($errorInfo)) {
360
-			$msg .= 'SQLSTATE = '.$errorInfo[0] . ', ';
361
-			$msg .= 'Driver Code = '.$errorInfo[1] . ', ';
362
-			$msg .= 'Driver Message = '.$errorInfo[2];
363
-		}
364
-		return $msg;
365
-	}
366
-
367
-	/**
368
-	 * Drop a table from the database if it exists
369
-	 *
370
-	 * @param string $table table name without the prefix
371
-	 */
372
-	public function dropTable($table) {
373
-		$table = $this->tablePrefix . trim($table);
374
-		$schema = $this->getSchemaManager();
375
-		if($schema->tablesExist([$table])) {
376
-			$schema->dropTable($table);
377
-		}
378
-	}
379
-
380
-	/**
381
-	 * Check if a table exists
382
-	 *
383
-	 * @param string $table table name without the prefix
384
-	 * @return bool
385
-	 */
386
-	public function tableExists($table) {
387
-		$table = $this->tablePrefix . trim($table);
388
-		$schema = $this->getSchemaManager();
389
-		return $schema->tablesExist([$table]);
390
-	}
391
-
392
-	// internal use
393
-	/**
394
-	 * @param string $statement
395
-	 * @return string
396
-	 */
397
-	protected function replaceTablePrefix($statement) {
398
-		return str_replace('*PREFIX*', $this->tablePrefix, $statement);
399
-	}
400
-
401
-	/**
402
-	 * Check if a transaction is active
403
-	 *
404
-	 * @return bool
405
-	 * @since 8.2.0
406
-	 */
407
-	public function inTransaction() {
408
-		return $this->getTransactionNestingLevel() > 0;
409
-	}
410
-
411
-	/**
412
-	 * Escape a parameter to be used in a LIKE query
413
-	 *
414
-	 * @param string $param
415
-	 * @return string
416
-	 */
417
-	public function escapeLikeParameter($param) {
418
-		return addcslashes($param, '\\_%');
419
-	}
420
-
421
-	/**
422
-	 * Check whether or not the current database support 4byte wide unicode
423
-	 *
424
-	 * @return bool
425
-	 * @since 11.0.0
426
-	 */
427
-	public function supports4ByteText() {
428
-		if (!$this->getDatabasePlatform() instanceof MySqlPlatform) {
429
-			return true;
430
-		}
431
-		return $this->getParams()['charset'] === 'utf8mb4';
432
-	}
433
-
434
-
435
-	/**
436
-	 * Create the schema of the connected database
437
-	 *
438
-	 * @return Schema
439
-	 */
440
-	public function createSchema() {
441
-		$schemaManager = new MDB2SchemaManager($this);
442
-		$migrator = $schemaManager->getMigrator();
443
-		return $migrator->createSchema();
444
-	}
445
-
446
-	/**
447
-	 * Migrate the database to the given schema
448
-	 *
449
-	 * @param Schema $toSchema
450
-	 */
451
-	public function migrateToSchema(Schema $toSchema) {
452
-		$schemaManager = new MDB2SchemaManager($this);
453
-		$migrator = $schemaManager->getMigrator();
454
-		$migrator->migrate($toSchema);
455
-	}
50
+    /**
51
+     * @var string $tablePrefix
52
+     */
53
+    protected $tablePrefix;
54
+
55
+    /**
56
+     * @var \OC\DB\Adapter $adapter
57
+     */
58
+    protected $adapter;
59
+
60
+    protected $lockedTable = null;
61
+
62
+    public function connect() {
63
+        try {
64
+            return parent::connect();
65
+        } catch (DBALException $e) {
66
+            // throw a new exception to prevent leaking info from the stacktrace
67
+            throw new DBALException('Failed to connect to the database: ' . $e->getMessage(), $e->getCode());
68
+        }
69
+    }
70
+
71
+    /**
72
+     * Returns a QueryBuilder for the connection.
73
+     *
74
+     * @return \OCP\DB\QueryBuilder\IQueryBuilder
75
+     */
76
+    public function getQueryBuilder() {
77
+        return new QueryBuilder(
78
+            $this,
79
+            \OC::$server->getSystemConfig(),
80
+            \OC::$server->getLogger()
81
+        );
82
+    }
83
+
84
+    /**
85
+     * Gets the QueryBuilder for the connection.
86
+     *
87
+     * @return \Doctrine\DBAL\Query\QueryBuilder
88
+     * @deprecated please use $this->getQueryBuilder() instead
89
+     */
90
+    public function createQueryBuilder() {
91
+        $backtrace = $this->getCallerBacktrace();
92
+        \OC::$server->getLogger()->debug('Doctrine QueryBuilder retrieved in {backtrace}', ['app' => 'core', 'backtrace' => $backtrace]);
93
+        return parent::createQueryBuilder();
94
+    }
95
+
96
+    /**
97
+     * Gets the ExpressionBuilder for the connection.
98
+     *
99
+     * @return \Doctrine\DBAL\Query\Expression\ExpressionBuilder
100
+     * @deprecated please use $this->getQueryBuilder()->expr() instead
101
+     */
102
+    public function getExpressionBuilder() {
103
+        $backtrace = $this->getCallerBacktrace();
104
+        \OC::$server->getLogger()->debug('Doctrine ExpressionBuilder retrieved in {backtrace}', ['app' => 'core', 'backtrace' => $backtrace]);
105
+        return parent::getExpressionBuilder();
106
+    }
107
+
108
+    /**
109
+     * Get the file and line that called the method where `getCallerBacktrace()` was used
110
+     *
111
+     * @return string
112
+     */
113
+    protected function getCallerBacktrace() {
114
+        $traces = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
115
+
116
+        // 0 is the method where we use `getCallerBacktrace`
117
+        // 1 is the target method which uses the method we want to log
118
+        if (isset($traces[1])) {
119
+            return $traces[1]['file'] . ':' . $traces[1]['line'];
120
+        }
121
+
122
+        return '';
123
+    }
124
+
125
+    /**
126
+     * @return string
127
+     */
128
+    public function getPrefix() {
129
+        return $this->tablePrefix;
130
+    }
131
+
132
+    /**
133
+     * Initializes a new instance of the Connection class.
134
+     *
135
+     * @param array $params  The connection parameters.
136
+     * @param \Doctrine\DBAL\Driver $driver
137
+     * @param \Doctrine\DBAL\Configuration $config
138
+     * @param \Doctrine\Common\EventManager $eventManager
139
+     * @throws \Exception
140
+     */
141
+    public function __construct(array $params, Driver $driver, Configuration $config = null,
142
+        EventManager $eventManager = null)
143
+    {
144
+        if (!isset($params['adapter'])) {
145
+            throw new \Exception('adapter not set');
146
+        }
147
+        if (!isset($params['tablePrefix'])) {
148
+            throw new \Exception('tablePrefix not set');
149
+        }
150
+        parent::__construct($params, $driver, $config, $eventManager);
151
+        $this->adapter = new $params['adapter']($this);
152
+        $this->tablePrefix = $params['tablePrefix'];
153
+    }
154
+
155
+    /**
156
+     * Prepares an SQL statement.
157
+     *
158
+     * @param string $statement The SQL statement to prepare.
159
+     * @param int $limit
160
+     * @param int $offset
161
+     * @return \Doctrine\DBAL\Driver\Statement The prepared statement.
162
+     */
163
+    public function prepare($statement, $limit=null, $offset=null) {
164
+        if ($limit === -1) {
165
+            $limit = null;
166
+        }
167
+        if (!is_null($limit)) {
168
+            $platform = $this->getDatabasePlatform();
169
+            $statement = $platform->modifyLimitQuery($statement, $limit, $offset);
170
+        }
171
+        $statement = $this->replaceTablePrefix($statement);
172
+        $statement = $this->adapter->fixupStatement($statement);
173
+
174
+        return parent::prepare($statement);
175
+    }
176
+
177
+    /**
178
+     * Executes an, optionally parametrized, SQL query.
179
+     *
180
+     * If the query is parametrized, a prepared statement is used.
181
+     * If an SQLLogger is configured, the execution is logged.
182
+     *
183
+     * @param string                                      $query  The SQL query to execute.
184
+     * @param array                                       $params The parameters to bind to the query, if any.
185
+     * @param array                                       $types  The types the previous parameters are in.
186
+     * @param \Doctrine\DBAL\Cache\QueryCacheProfile|null $qcp    The query cache profile, optional.
187
+     *
188
+     * @return \Doctrine\DBAL\Driver\Statement The executed statement.
189
+     *
190
+     * @throws \Doctrine\DBAL\DBALException
191
+     */
192
+    public function executeQuery($query, array $params = [], $types = [], QueryCacheProfile $qcp = null)
193
+    {
194
+        $query = $this->replaceTablePrefix($query);
195
+        $query = $this->adapter->fixupStatement($query);
196
+        return parent::executeQuery($query, $params, $types, $qcp);
197
+    }
198
+
199
+    /**
200
+     * Executes an SQL INSERT/UPDATE/DELETE query with the given parameters
201
+     * and returns the number of affected rows.
202
+     *
203
+     * This method supports PDO binding types as well as DBAL mapping types.
204
+     *
205
+     * @param string $query  The SQL query.
206
+     * @param array  $params The query parameters.
207
+     * @param array  $types  The parameter types.
208
+     *
209
+     * @return integer The number of affected rows.
210
+     *
211
+     * @throws \Doctrine\DBAL\DBALException
212
+     */
213
+    public function executeUpdate($query, array $params = [], array $types = [])
214
+    {
215
+        $query = $this->replaceTablePrefix($query);
216
+        $query = $this->adapter->fixupStatement($query);
217
+        return parent::executeUpdate($query, $params, $types);
218
+    }
219
+
220
+    /**
221
+     * Returns the ID of the last inserted row, or the last value from a sequence object,
222
+     * depending on the underlying driver.
223
+     *
224
+     * Note: This method may not return a meaningful or consistent result across different drivers,
225
+     * because the underlying database may not even support the notion of AUTO_INCREMENT/IDENTITY
226
+     * columns or sequences.
227
+     *
228
+     * @param string $seqName Name of the sequence object from which the ID should be returned.
229
+     * @return string A string representation of the last inserted ID.
230
+     */
231
+    public function lastInsertId($seqName = null) {
232
+        if ($seqName) {
233
+            $seqName = $this->replaceTablePrefix($seqName);
234
+        }
235
+        return $this->adapter->lastInsertId($seqName);
236
+    }
237
+
238
+    // internal use
239
+    public function realLastInsertId($seqName = null) {
240
+        return parent::lastInsertId($seqName);
241
+    }
242
+
243
+    /**
244
+     * Insert a row if the matching row does not exists. To accomplish proper race condition avoidance
245
+     * it is needed that there is also a unique constraint on the values. Then this method will
246
+     * catch the exception and return 0.
247
+     *
248
+     * @param string $table The table name (will replace *PREFIX* with the actual prefix)
249
+     * @param array $input data that should be inserted into the table  (column name => value)
250
+     * @param array|null $compare List of values that should be checked for "if not exists"
251
+     *				If this is null or an empty array, all keys of $input will be compared
252
+     *				Please note: text fields (clob) must not be used in the compare array
253
+     * @return int number of inserted rows
254
+     * @throws \Doctrine\DBAL\DBALException
255
+     * @deprecated 15.0.0 - use unique index and "try { $db->insert() } catch (UniqueConstraintViolationException $e) {}" instead, because it is more reliable and does not have the risk for deadlocks - see https://github.com/nextcloud/server/pull/12371
256
+     */
257
+    public function insertIfNotExist($table, $input, array $compare = null) {
258
+        return $this->adapter->insertIfNotExist($table, $input, $compare);
259
+    }
260
+
261
+    public function insertIgnoreConflict(string $table, array $values) : int {
262
+        return $this->adapter->insertIgnoreConflict($table, $values);
263
+    }
264
+
265
+    private function getType($value) {
266
+        if (is_bool($value)) {
267
+            return IQueryBuilder::PARAM_BOOL;
268
+        } else if (is_int($value)) {
269
+            return IQueryBuilder::PARAM_INT;
270
+        } else {
271
+            return IQueryBuilder::PARAM_STR;
272
+        }
273
+    }
274
+
275
+    /**
276
+     * Insert or update a row value
277
+     *
278
+     * @param string $table
279
+     * @param array $keys (column name => value)
280
+     * @param array $values (column name => value)
281
+     * @param array $updatePreconditionValues ensure values match preconditions (column name => value)
282
+     * @return int number of new rows
283
+     * @throws \Doctrine\DBAL\DBALException
284
+     * @throws PreConditionNotMetException
285
+     * @suppress SqlInjectionChecker
286
+     */
287
+    public function setValues($table, array $keys, array $values, array $updatePreconditionValues = []) {
288
+        try {
289
+            $insertQb = $this->getQueryBuilder();
290
+            $insertQb->insert($table)
291
+                ->values(
292
+                    array_map(function ($value) use ($insertQb) {
293
+                        return $insertQb->createNamedParameter($value, $this->getType($value));
294
+                    }, array_merge($keys, $values))
295
+                );
296
+            return $insertQb->execute();
297
+        } catch (ConstraintViolationException $e) {
298
+            // value already exists, try update
299
+            $updateQb = $this->getQueryBuilder();
300
+            $updateQb->update($table);
301
+            foreach ($values as $name => $value) {
302
+                $updateQb->set($name, $updateQb->createNamedParameter($value, $this->getType($value)));
303
+            }
304
+            $where = $updateQb->expr()->andX();
305
+            $whereValues = array_merge($keys, $updatePreconditionValues);
306
+            foreach ($whereValues as $name => $value) {
307
+                $where->add($updateQb->expr()->eq(
308
+                    $name,
309
+                    $updateQb->createNamedParameter($value, $this->getType($value)),
310
+                    $this->getType($value)
311
+                ));
312
+            }
313
+            $updateQb->where($where);
314
+            $affected = $updateQb->execute();
315
+
316
+            if ($affected === 0 && !empty($updatePreconditionValues)) {
317
+                throw new PreConditionNotMetException();
318
+            }
319
+
320
+            return 0;
321
+        }
322
+    }
323
+
324
+    /**
325
+     * Create an exclusive read+write lock on a table
326
+     *
327
+     * @param string $tableName
328
+     * @throws \BadMethodCallException When trying to acquire a second lock
329
+     * @since 9.1.0
330
+     */
331
+    public function lockTable($tableName) {
332
+        if ($this->lockedTable !== null) {
333
+            throw new \BadMethodCallException('Can not lock a new table until the previous lock is released.');
334
+        }
335
+
336
+        $tableName = $this->tablePrefix . $tableName;
337
+        $this->lockedTable = $tableName;
338
+        $this->adapter->lockTable($tableName);
339
+    }
340
+
341
+    /**
342
+     * Release a previous acquired lock again
343
+     *
344
+     * @since 9.1.0
345
+     */
346
+    public function unlockTable() {
347
+        $this->adapter->unlockTable();
348
+        $this->lockedTable = null;
349
+    }
350
+
351
+    /**
352
+     * returns the error code and message as a string for logging
353
+     * works with DoctrineException
354
+     * @return string
355
+     */
356
+    public function getError() {
357
+        $msg = $this->errorCode() . ': ';
358
+        $errorInfo = $this->errorInfo();
359
+        if (is_array($errorInfo)) {
360
+            $msg .= 'SQLSTATE = '.$errorInfo[0] . ', ';
361
+            $msg .= 'Driver Code = '.$errorInfo[1] . ', ';
362
+            $msg .= 'Driver Message = '.$errorInfo[2];
363
+        }
364
+        return $msg;
365
+    }
366
+
367
+    /**
368
+     * Drop a table from the database if it exists
369
+     *
370
+     * @param string $table table name without the prefix
371
+     */
372
+    public function dropTable($table) {
373
+        $table = $this->tablePrefix . trim($table);
374
+        $schema = $this->getSchemaManager();
375
+        if($schema->tablesExist([$table])) {
376
+            $schema->dropTable($table);
377
+        }
378
+    }
379
+
380
+    /**
381
+     * Check if a table exists
382
+     *
383
+     * @param string $table table name without the prefix
384
+     * @return bool
385
+     */
386
+    public function tableExists($table) {
387
+        $table = $this->tablePrefix . trim($table);
388
+        $schema = $this->getSchemaManager();
389
+        return $schema->tablesExist([$table]);
390
+    }
391
+
392
+    // internal use
393
+    /**
394
+     * @param string $statement
395
+     * @return string
396
+     */
397
+    protected function replaceTablePrefix($statement) {
398
+        return str_replace('*PREFIX*', $this->tablePrefix, $statement);
399
+    }
400
+
401
+    /**
402
+     * Check if a transaction is active
403
+     *
404
+     * @return bool
405
+     * @since 8.2.0
406
+     */
407
+    public function inTransaction() {
408
+        return $this->getTransactionNestingLevel() > 0;
409
+    }
410
+
411
+    /**
412
+     * Escape a parameter to be used in a LIKE query
413
+     *
414
+     * @param string $param
415
+     * @return string
416
+     */
417
+    public function escapeLikeParameter($param) {
418
+        return addcslashes($param, '\\_%');
419
+    }
420
+
421
+    /**
422
+     * Check whether or not the current database support 4byte wide unicode
423
+     *
424
+     * @return bool
425
+     * @since 11.0.0
426
+     */
427
+    public function supports4ByteText() {
428
+        if (!$this->getDatabasePlatform() instanceof MySqlPlatform) {
429
+            return true;
430
+        }
431
+        return $this->getParams()['charset'] === 'utf8mb4';
432
+    }
433
+
434
+
435
+    /**
436
+     * Create the schema of the connected database
437
+     *
438
+     * @return Schema
439
+     */
440
+    public function createSchema() {
441
+        $schemaManager = new MDB2SchemaManager($this);
442
+        $migrator = $schemaManager->getMigrator();
443
+        return $migrator->createSchema();
444
+    }
445
+
446
+    /**
447
+     * Migrate the database to the given schema
448
+     *
449
+     * @param Schema $toSchema
450
+     */
451
+    public function migrateToSchema(Schema $toSchema) {
452
+        $schemaManager = new MDB2SchemaManager($this);
453
+        $migrator = $schemaManager->getMigrator();
454
+        $migrator->migrate($toSchema);
455
+    }
456 456
 }
Please login to merge, or discard this patch.
lib/private/DB/AdapterPgSql.php 1 patch
Indentation   +35 added lines, -35 removed lines patch added patch discarded remove patch
@@ -27,46 +27,46 @@
 block discarded – undo
27 27
 namespace OC\DB;
28 28
 
29 29
 class AdapterPgSql extends Adapter {
30
-	protected $compatModePre9_5 = null;
30
+    protected $compatModePre9_5 = null;
31 31
 
32
-	public function lastInsertId($table) {
33
-		return $this->conn->fetchColumn('SELECT lastval()');
34
-	}
32
+    public function lastInsertId($table) {
33
+        return $this->conn->fetchColumn('SELECT lastval()');
34
+    }
35 35
 
36
-	const UNIX_TIMESTAMP_REPLACEMENT = 'cast(extract(epoch from current_timestamp) as integer)';
37
-	public function fixupStatement($statement) {
38
-		$statement = str_replace('`', '"', $statement);
39
-		$statement = str_ireplace('UNIX_TIMESTAMP()', self::UNIX_TIMESTAMP_REPLACEMENT, $statement);
40
-		return $statement;
41
-	}
36
+    const UNIX_TIMESTAMP_REPLACEMENT = 'cast(extract(epoch from current_timestamp) as integer)';
37
+    public function fixupStatement($statement) {
38
+        $statement = str_replace('`', '"', $statement);
39
+        $statement = str_ireplace('UNIX_TIMESTAMP()', self::UNIX_TIMESTAMP_REPLACEMENT, $statement);
40
+        return $statement;
41
+    }
42 42
 
43
-	/**
44
-	 * @suppress SqlInjectionChecker
45
-	 */
46
-	public function insertIgnoreConflict(string $table,array $values) : int {
47
-		if($this->isPre9_5CompatMode() === true) {
48
-			return parent::insertIgnoreConflict($table, $values);
49
-		}
43
+    /**
44
+     * @suppress SqlInjectionChecker
45
+     */
46
+    public function insertIgnoreConflict(string $table,array $values) : int {
47
+        if($this->isPre9_5CompatMode() === true) {
48
+            return parent::insertIgnoreConflict($table, $values);
49
+        }
50 50
 
51
-		// "upsert" is only available since PgSQL 9.5, but the generic way
52
-		// would leave error logs in the DB.
53
-		$builder = $this->conn->getQueryBuilder();
54
-		$builder->insert($table);
55
-		foreach ($values as $key => $value) {
56
-			$builder->setValue($key, $builder->createNamedParameter($value));
57
-		}
58
-		$queryString = $builder->getSQL() . ' ON CONFLICT DO NOTHING';
59
-		return $this->conn->executeUpdate($queryString, $builder->getParameters(), $builder->getParameterTypes());
60
-	}
51
+        // "upsert" is only available since PgSQL 9.5, but the generic way
52
+        // would leave error logs in the DB.
53
+        $builder = $this->conn->getQueryBuilder();
54
+        $builder->insert($table);
55
+        foreach ($values as $key => $value) {
56
+            $builder->setValue($key, $builder->createNamedParameter($value));
57
+        }
58
+        $queryString = $builder->getSQL() . ' ON CONFLICT DO NOTHING';
59
+        return $this->conn->executeUpdate($queryString, $builder->getParameters(), $builder->getParameterTypes());
60
+    }
61 61
 
62
-	protected function isPre9_5CompatMode(): bool {
63
-		if($this->compatModePre9_5 !== null) {
64
-			return $this->compatModePre9_5;
65
-		}
62
+    protected function isPre9_5CompatMode(): bool {
63
+        if($this->compatModePre9_5 !== null) {
64
+            return $this->compatModePre9_5;
65
+        }
66 66
 
67
-		$version = $this->conn->fetchColumn('SHOW SERVER_VERSION');
68
-		$this->compatModePre9_5 = version_compare($version, '9.5', '<');
67
+        $version = $this->conn->fetchColumn('SHOW SERVER_VERSION');
68
+        $this->compatModePre9_5 = version_compare($version, '9.5', '<');
69 69
 
70
-		return $this->compatModePre9_5;
71
-	}
70
+        return $this->compatModePre9_5;
71
+    }
72 72
 }
Please login to merge, or discard this patch.
lib/private/DB/AdapterSqlite.php 1 patch
Indentation   +61 added lines, -61 removed lines patch added patch discarded remove patch
@@ -30,70 +30,70 @@
 block discarded – undo
30 30
 
31 31
 class AdapterSqlite extends Adapter {
32 32
 
33
-	/**
34
-	 * @param string $tableName
35
-	 */
36
-	public function lockTable($tableName) {
37
-		$this->conn->executeUpdate('BEGIN EXCLUSIVE TRANSACTION');
38
-	}
33
+    /**
34
+     * @param string $tableName
35
+     */
36
+    public function lockTable($tableName) {
37
+        $this->conn->executeUpdate('BEGIN EXCLUSIVE TRANSACTION');
38
+    }
39 39
 
40
-	public function unlockTable() {
41
-		$this->conn->executeUpdate('COMMIT TRANSACTION');
42
-	}
40
+    public function unlockTable() {
41
+        $this->conn->executeUpdate('COMMIT TRANSACTION');
42
+    }
43 43
 
44
-	public function fixupStatement($statement) {
45
-		$statement = preg_replace('/`(\w+)` ILIKE \?/', 'LOWER($1) LIKE LOWER(?)', $statement);
46
-		$statement = str_replace('`', '"', $statement);
47
-		$statement = str_ireplace('NOW()', 'datetime(\'now\')', $statement);
48
-		$statement = str_ireplace('GREATEST(', 'MAX(', $statement);
49
-		$statement = str_ireplace('UNIX_TIMESTAMP()', 'strftime(\'%s\',\'now\')', $statement);
50
-		return $statement;
51
-	}
44
+    public function fixupStatement($statement) {
45
+        $statement = preg_replace('/`(\w+)` ILIKE \?/', 'LOWER($1) LIKE LOWER(?)', $statement);
46
+        $statement = str_replace('`', '"', $statement);
47
+        $statement = str_ireplace('NOW()', 'datetime(\'now\')', $statement);
48
+        $statement = str_ireplace('GREATEST(', 'MAX(', $statement);
49
+        $statement = str_ireplace('UNIX_TIMESTAMP()', 'strftime(\'%s\',\'now\')', $statement);
50
+        return $statement;
51
+    }
52 52
 
53
-	/**
54
-	 * Insert a row if the matching row does not exists. To accomplish proper race condition avoidance
55
-	 * it is needed that there is also a unique constraint on the values. Then this method will
56
-	 * catch the exception and return 0.
57
-	 *
58
-	 * @param string $table The table name (will replace *PREFIX* with the actual prefix)
59
-	 * @param array $input data that should be inserted into the table  (column name => value)
60
-	 * @param array|null $compare List of values that should be checked for "if not exists"
61
-	 *				If this is null or an empty array, all keys of $input will be compared
62
-	 *				Please note: text fields (clob) must not be used in the compare array
63
-	 * @return int number of inserted rows
64
-	 * @throws \Doctrine\DBAL\DBALException
65
-	 * @deprecated 15.0.0 - use unique index and "try { $db->insert() } catch (UniqueConstraintViolationException $e) {}" instead, because it is more reliable and does not have the risk for deadlocks - see https://github.com/nextcloud/server/pull/12371
66
-	 */
67
-	public function insertIfNotExist($table, $input, array $compare = null) {
68
-		if (empty($compare)) {
69
-			$compare = array_keys($input);
70
-		}
71
-		$fieldList = '`' . implode('`,`', array_keys($input)) . '`';
72
-		$query = "INSERT INTO `$table` ($fieldList) SELECT "
73
-			. str_repeat('?,', count($input)-1).'? '
74
-			. " WHERE NOT EXISTS (SELECT 1 FROM `$table` WHERE ";
53
+    /**
54
+     * Insert a row if the matching row does not exists. To accomplish proper race condition avoidance
55
+     * it is needed that there is also a unique constraint on the values. Then this method will
56
+     * catch the exception and return 0.
57
+     *
58
+     * @param string $table The table name (will replace *PREFIX* with the actual prefix)
59
+     * @param array $input data that should be inserted into the table  (column name => value)
60
+     * @param array|null $compare List of values that should be checked for "if not exists"
61
+     *				If this is null or an empty array, all keys of $input will be compared
62
+     *				Please note: text fields (clob) must not be used in the compare array
63
+     * @return int number of inserted rows
64
+     * @throws \Doctrine\DBAL\DBALException
65
+     * @deprecated 15.0.0 - use unique index and "try { $db->insert() } catch (UniqueConstraintViolationException $e) {}" instead, because it is more reliable and does not have the risk for deadlocks - see https://github.com/nextcloud/server/pull/12371
66
+     */
67
+    public function insertIfNotExist($table, $input, array $compare = null) {
68
+        if (empty($compare)) {
69
+            $compare = array_keys($input);
70
+        }
71
+        $fieldList = '`' . implode('`,`', array_keys($input)) . '`';
72
+        $query = "INSERT INTO `$table` ($fieldList) SELECT "
73
+            . str_repeat('?,', count($input)-1).'? '
74
+            . " WHERE NOT EXISTS (SELECT 1 FROM `$table` WHERE ";
75 75
 
76
-		$inserts = array_values($input);
77
-		foreach($compare as $key) {
78
-			$query .= '`' . $key . '`';
79
-			if (is_null($input[$key])) {
80
-				$query .= ' IS NULL AND ';
81
-			} else {
82
-				$inserts[] = $input[$key];
83
-				$query .= ' = ? AND ';
84
-			}
85
-		}
86
-		$query = substr($query, 0, -5);
87
-		$query .= ')';
76
+        $inserts = array_values($input);
77
+        foreach($compare as $key) {
78
+            $query .= '`' . $key . '`';
79
+            if (is_null($input[$key])) {
80
+                $query .= ' IS NULL AND ';
81
+            } else {
82
+                $inserts[] = $input[$key];
83
+                $query .= ' = ? AND ';
84
+            }
85
+        }
86
+        $query = substr($query, 0, -5);
87
+        $query .= ')';
88 88
 
89
-		try {
90
-			return $this->conn->executeUpdate($query, $inserts);
91
-		} catch (UniqueConstraintViolationException $e) {
92
-			// if this is thrown then a concurrent insert happened between the insert and the sub-select in the insert, that should have avoided it
93
-			// it's fine to ignore this then
94
-			//
95
-			// more discussions about this can be found at https://github.com/nextcloud/server/pull/12315
96
-			return 0;
97
-		}
98
-	}
89
+        try {
90
+            return $this->conn->executeUpdate($query, $inserts);
91
+        } catch (UniqueConstraintViolationException $e) {
92
+            // if this is thrown then a concurrent insert happened between the insert and the sub-select in the insert, that should have avoided it
93
+            // it's fine to ignore this then
94
+            //
95
+            // more discussions about this can be found at https://github.com/nextcloud/server/pull/12315
96
+            return 0;
97
+        }
98
+    }
99 99
 }
Please login to merge, or discard this patch.