Passed
Push — master ( 62403d...0c3e2f )
by Joas
14:50 queued 14s
created
lib/private/Share/Helper.php 1 patch
Indentation   +232 added lines, -232 removed lines patch added patch discarded remove patch
@@ -33,263 +33,263 @@
 block discarded – undo
33 33
 
34 34
 class Helper extends \OC\Share\Constants {
35 35
 
36
-	/**
37
-	 * Generate a unique target for the item
38
-	 * @param string $itemType
39
-	 * @param string $itemSource
40
-	 * @param int $shareType SHARE_TYPE_USER, SHARE_TYPE_GROUP, or SHARE_TYPE_LINK
41
-	 * @param string $shareWith User or group the item is being shared with
42
-	 * @param string $uidOwner User that is the owner of shared item
43
-	 * @param string $suggestedTarget The suggested target originating from a reshare (optional)
44
-	 * @param int $groupParent The id of the parent group share (optional)
45
-	 * @throws \Exception
46
-	 * @return string Item target
47
-	 */
48
-	public static function generateTarget($itemType, $itemSource, $shareType, $shareWith, $uidOwner, $suggestedTarget = null, $groupParent = null) {
49
-		// FIXME: $uidOwner and $groupParent seems to be unused
50
-		$backend = \OC\Share\Share::getBackend($itemType);
51
-		if ($shareType === self::SHARE_TYPE_LINK || $shareType === self::SHARE_TYPE_REMOTE) {
52
-			if (isset($suggestedTarget)) {
53
-				return $suggestedTarget;
54
-			}
55
-			return $backend->generateTarget($itemSource, false);
56
-		} else {
57
-			if ($shareType == self::SHARE_TYPE_USER) {
58
-				// Share with is a user, so set share type to user and groups
59
-				$shareType = self::$shareTypeUserAndGroups;
60
-			}
36
+    /**
37
+     * Generate a unique target for the item
38
+     * @param string $itemType
39
+     * @param string $itemSource
40
+     * @param int $shareType SHARE_TYPE_USER, SHARE_TYPE_GROUP, or SHARE_TYPE_LINK
41
+     * @param string $shareWith User or group the item is being shared with
42
+     * @param string $uidOwner User that is the owner of shared item
43
+     * @param string $suggestedTarget The suggested target originating from a reshare (optional)
44
+     * @param int $groupParent The id of the parent group share (optional)
45
+     * @throws \Exception
46
+     * @return string Item target
47
+     */
48
+    public static function generateTarget($itemType, $itemSource, $shareType, $shareWith, $uidOwner, $suggestedTarget = null, $groupParent = null) {
49
+        // FIXME: $uidOwner and $groupParent seems to be unused
50
+        $backend = \OC\Share\Share::getBackend($itemType);
51
+        if ($shareType === self::SHARE_TYPE_LINK || $shareType === self::SHARE_TYPE_REMOTE) {
52
+            if (isset($suggestedTarget)) {
53
+                return $suggestedTarget;
54
+            }
55
+            return $backend->generateTarget($itemSource, false);
56
+        } else {
57
+            if ($shareType == self::SHARE_TYPE_USER) {
58
+                // Share with is a user, so set share type to user and groups
59
+                $shareType = self::$shareTypeUserAndGroups;
60
+            }
61 61
 
62
-			// Check if suggested target exists first
63
-			if (!isset($suggestedTarget)) {
64
-				$suggestedTarget = $itemSource;
65
-			}
66
-			if ($shareType == self::SHARE_TYPE_GROUP) {
67
-				$target = $backend->generateTarget($suggestedTarget, false);
68
-			} else {
69
-				$target = $backend->generateTarget($suggestedTarget, $shareWith);
70
-			}
62
+            // Check if suggested target exists first
63
+            if (!isset($suggestedTarget)) {
64
+                $suggestedTarget = $itemSource;
65
+            }
66
+            if ($shareType == self::SHARE_TYPE_GROUP) {
67
+                $target = $backend->generateTarget($suggestedTarget, false);
68
+            } else {
69
+                $target = $backend->generateTarget($suggestedTarget, $shareWith);
70
+            }
71 71
 
72
-			return $target;
73
-		}
74
-	}
72
+            return $target;
73
+        }
74
+    }
75 75
 
76
-	/**
77
-	 * Delete all reshares and group share children of an item
78
-	 * @param int $parent Id of item to delete
79
-	 * @param bool $excludeParent If true, exclude the parent from the delete (optional)
80
-	 * @param string $uidOwner The user that the parent was shared with (optional)
81
-	 * @param int $newParent new parent for the childrens
82
-	 * @param bool $excludeGroupChildren exclude group children elements
83
-	 */
84
-	public static function delete($parent, $excludeParent = false, $uidOwner = null, $newParent = null, $excludeGroupChildren = false) {
85
-		$ids = [$parent];
86
-		$deletedItems = [];
87
-		$changeParent = [];
88
-		$parents = [$parent];
89
-		while (!empty($parents)) {
90
-			$parents = "'".implode("','", $parents)."'";
91
-			// Check the owner on the first search of reshares, useful for
92
-			// finding and deleting the reshares by a single user of a group share
93
-			$params = [];
94
-			if (count($ids) == 1 && isset($uidOwner)) {
95
-				// FIXME: don't concat $parents, use Docrine's PARAM_INT_ARRAY approach
96
-				$queryString = 'SELECT `id`, `share_with`, `item_type`, `share_type`, ' .
97
-					'`item_target`, `file_target`, `parent` ' .
98
-					'FROM `*PREFIX*share` ' .
99
-					'WHERE `parent` IN ('.$parents.') AND `uid_owner` = ? ';
100
-				$params[] = $uidOwner;
101
-			} else {
102
-				$queryString = 'SELECT `id`, `share_with`, `item_type`, `share_type`, ' .
103
-					'`item_target`, `file_target`, `parent`, `uid_owner` ' .
104
-					'FROM `*PREFIX*share` WHERE `parent` IN ('.$parents.') ';
105
-			}
106
-			if ($excludeGroupChildren) {
107
-				$queryString .= ' AND `share_type` != ?';
108
-				$params[] = self::$shareTypeGroupUserUnique;
109
-			}
110
-			$query = \OC_DB::prepare($queryString);
111
-			$result = $query->execute($params);
112
-			// Reset parents array, only go through loop again if items are found
113
-			$parents = [];
114
-			while ($item = $result->fetchRow()) {
115
-				$tmpItem = [
116
-					'id' => $item['id'],
117
-					'shareWith' => $item['share_with'],
118
-					'itemTarget' => $item['item_target'],
119
-					'itemType' => $item['item_type'],
120
-					'shareType' => (int)$item['share_type'],
121
-				];
122
-				if (isset($item['file_target'])) {
123
-					$tmpItem['fileTarget'] = $item['file_target'];
124
-				}
125
-				// if we have a new parent for the child we remember the child
126
-				// to update the parent, if not we add it to the list of items
127
-				// which should be deleted
128
-				if ($newParent !== null) {
129
-					$changeParent[] = $item['id'];
130
-				} else {
131
-					$deletedItems[] = $tmpItem;
132
-					$ids[] = $item['id'];
133
-					$parents[] = $item['id'];
134
-				}
135
-			}
136
-		}
137
-		if ($excludeParent) {
138
-			unset($ids[0]);
139
-		}
76
+    /**
77
+     * Delete all reshares and group share children of an item
78
+     * @param int $parent Id of item to delete
79
+     * @param bool $excludeParent If true, exclude the parent from the delete (optional)
80
+     * @param string $uidOwner The user that the parent was shared with (optional)
81
+     * @param int $newParent new parent for the childrens
82
+     * @param bool $excludeGroupChildren exclude group children elements
83
+     */
84
+    public static function delete($parent, $excludeParent = false, $uidOwner = null, $newParent = null, $excludeGroupChildren = false) {
85
+        $ids = [$parent];
86
+        $deletedItems = [];
87
+        $changeParent = [];
88
+        $parents = [$parent];
89
+        while (!empty($parents)) {
90
+            $parents = "'".implode("','", $parents)."'";
91
+            // Check the owner on the first search of reshares, useful for
92
+            // finding and deleting the reshares by a single user of a group share
93
+            $params = [];
94
+            if (count($ids) == 1 && isset($uidOwner)) {
95
+                // FIXME: don't concat $parents, use Docrine's PARAM_INT_ARRAY approach
96
+                $queryString = 'SELECT `id`, `share_with`, `item_type`, `share_type`, ' .
97
+                    '`item_target`, `file_target`, `parent` ' .
98
+                    'FROM `*PREFIX*share` ' .
99
+                    'WHERE `parent` IN ('.$parents.') AND `uid_owner` = ? ';
100
+                $params[] = $uidOwner;
101
+            } else {
102
+                $queryString = 'SELECT `id`, `share_with`, `item_type`, `share_type`, ' .
103
+                    '`item_target`, `file_target`, `parent`, `uid_owner` ' .
104
+                    'FROM `*PREFIX*share` WHERE `parent` IN ('.$parents.') ';
105
+            }
106
+            if ($excludeGroupChildren) {
107
+                $queryString .= ' AND `share_type` != ?';
108
+                $params[] = self::$shareTypeGroupUserUnique;
109
+            }
110
+            $query = \OC_DB::prepare($queryString);
111
+            $result = $query->execute($params);
112
+            // Reset parents array, only go through loop again if items are found
113
+            $parents = [];
114
+            while ($item = $result->fetchRow()) {
115
+                $tmpItem = [
116
+                    'id' => $item['id'],
117
+                    'shareWith' => $item['share_with'],
118
+                    'itemTarget' => $item['item_target'],
119
+                    'itemType' => $item['item_type'],
120
+                    'shareType' => (int)$item['share_type'],
121
+                ];
122
+                if (isset($item['file_target'])) {
123
+                    $tmpItem['fileTarget'] = $item['file_target'];
124
+                }
125
+                // if we have a new parent for the child we remember the child
126
+                // to update the parent, if not we add it to the list of items
127
+                // which should be deleted
128
+                if ($newParent !== null) {
129
+                    $changeParent[] = $item['id'];
130
+                } else {
131
+                    $deletedItems[] = $tmpItem;
132
+                    $ids[] = $item['id'];
133
+                    $parents[] = $item['id'];
134
+                }
135
+            }
136
+        }
137
+        if ($excludeParent) {
138
+            unset($ids[0]);
139
+        }
140 140
 
141
-		if (!empty($changeParent)) {
142
-			$idList = "'".implode("','", $changeParent)."'";
143
-			$query = \OC_DB::prepare('UPDATE `*PREFIX*share` SET `parent` = ? WHERE `id` IN ('.$idList.')');
144
-			$query->execute([$newParent]);
145
-		}
141
+        if (!empty($changeParent)) {
142
+            $idList = "'".implode("','", $changeParent)."'";
143
+            $query = \OC_DB::prepare('UPDATE `*PREFIX*share` SET `parent` = ? WHERE `id` IN ('.$idList.')');
144
+            $query->execute([$newParent]);
145
+        }
146 146
 
147
-		if (!empty($ids)) {
148
-			$idList = "'".implode("','", $ids)."'";
149
-			$query = \OC_DB::prepare('DELETE FROM `*PREFIX*share` WHERE `id` IN ('.$idList.')');
150
-			$query->execute();
151
-		}
147
+        if (!empty($ids)) {
148
+            $idList = "'".implode("','", $ids)."'";
149
+            $query = \OC_DB::prepare('DELETE FROM `*PREFIX*share` WHERE `id` IN ('.$idList.')');
150
+            $query->execute();
151
+        }
152 152
 
153
-		return $deletedItems;
154
-	}
153
+        return $deletedItems;
154
+    }
155 155
 
156
-	/**
157
-	 * get default expire settings defined by the admin
158
-	 * @return array contains 'defaultExpireDateSet', 'enforceExpireDate', 'expireAfterDays'
159
-	 */
160
-	public static function getDefaultExpireSetting() {
156
+    /**
157
+     * get default expire settings defined by the admin
158
+     * @return array contains 'defaultExpireDateSet', 'enforceExpireDate', 'expireAfterDays'
159
+     */
160
+    public static function getDefaultExpireSetting() {
161 161
 
162
-		$config = \OC::$server->getConfig();
162
+        $config = \OC::$server->getConfig();
163 163
 
164
-		$defaultExpireSettings = ['defaultExpireDateSet' => false];
164
+        $defaultExpireSettings = ['defaultExpireDateSet' => false];
165 165
 
166
-		// get default expire settings
167
-		$defaultExpireDate = $config->getAppValue('core', 'shareapi_default_expire_date', 'no');
168
-		if ($defaultExpireDate === 'yes') {
169
-			$enforceExpireDate = $config->getAppValue('core', 'shareapi_enforce_expire_date', 'no');
170
-			$defaultExpireSettings['defaultExpireDateSet'] = true;
171
-			$defaultExpireSettings['expireAfterDays'] = (int)$config->getAppValue('core', 'shareapi_expire_after_n_days', '7');
172
-			$defaultExpireSettings['enforceExpireDate'] = $enforceExpireDate === 'yes';
173
-		}
166
+        // get default expire settings
167
+        $defaultExpireDate = $config->getAppValue('core', 'shareapi_default_expire_date', 'no');
168
+        if ($defaultExpireDate === 'yes') {
169
+            $enforceExpireDate = $config->getAppValue('core', 'shareapi_enforce_expire_date', 'no');
170
+            $defaultExpireSettings['defaultExpireDateSet'] = true;
171
+            $defaultExpireSettings['expireAfterDays'] = (int)$config->getAppValue('core', 'shareapi_expire_after_n_days', '7');
172
+            $defaultExpireSettings['enforceExpireDate'] = $enforceExpireDate === 'yes';
173
+        }
174 174
 
175
-		return $defaultExpireSettings;
176
-	}
175
+        return $defaultExpireSettings;
176
+    }
177 177
 
178
-	public static function calcExpireDate() {
179
-		$expireAfter = \OC\Share\Share::getExpireInterval() * 24 * 60 * 60;
180
-		$expireAt = time() + $expireAfter;
181
-		$date = new \DateTime();
182
-		$date->setTimestamp($expireAt);
183
-		$date->setTime(0, 0, 0);
184
-		//$dateString = $date->format('Y-m-d') . ' 00:00:00';
178
+    public static function calcExpireDate() {
179
+        $expireAfter = \OC\Share\Share::getExpireInterval() * 24 * 60 * 60;
180
+        $expireAt = time() + $expireAfter;
181
+        $date = new \DateTime();
182
+        $date->setTimestamp($expireAt);
183
+        $date->setTime(0, 0, 0);
184
+        //$dateString = $date->format('Y-m-d') . ' 00:00:00';
185 185
 
186
-		return $date;
186
+        return $date;
187 187
 
188
-	}
188
+    }
189 189
 
190
-	/**
191
-	 * calculate expire date
192
-	 * @param array $defaultExpireSettings contains 'defaultExpireDateSet', 'enforceExpireDate', 'expireAfterDays'
193
-	 * @param int $creationTime timestamp when the share was created
194
-	 * @param int $userExpireDate expire timestamp set by the user
195
-	 * @return mixed integer timestamp or False
196
-	 */
197
-	public static function calculateExpireDate($defaultExpireSettings, $creationTime, $userExpireDate = null) {
190
+    /**
191
+     * calculate expire date
192
+     * @param array $defaultExpireSettings contains 'defaultExpireDateSet', 'enforceExpireDate', 'expireAfterDays'
193
+     * @param int $creationTime timestamp when the share was created
194
+     * @param int $userExpireDate expire timestamp set by the user
195
+     * @return mixed integer timestamp or False
196
+     */
197
+    public static function calculateExpireDate($defaultExpireSettings, $creationTime, $userExpireDate = null) {
198 198
 
199
-		$expires = false;
200
-		$defaultExpires = null;
199
+        $expires = false;
200
+        $defaultExpires = null;
201 201
 
202
-		if (!empty($defaultExpireSettings['defaultExpireDateSet'])) {
203
-			$defaultExpires = $creationTime + $defaultExpireSettings['expireAfterDays'] * 86400;
204
-		}
202
+        if (!empty($defaultExpireSettings['defaultExpireDateSet'])) {
203
+            $defaultExpires = $creationTime + $defaultExpireSettings['expireAfterDays'] * 86400;
204
+        }
205 205
 
206 206
 
207
-		if (isset($userExpireDate)) {
208
-			// if the admin decided to enforce the default expire date then we only take
209
-			// the user defined expire date of it is before the default expire date
210
-			if ($defaultExpires && !empty($defaultExpireSettings['enforceExpireDate'])) {
211
-				$expires = min($userExpireDate, $defaultExpires);
212
-			} else {
213
-				$expires = $userExpireDate;
214
-			}
215
-		} else if ($defaultExpires && !empty($defaultExpireSettings['enforceExpireDate'])) {
216
-			$expires = $defaultExpires;
217
-		}
207
+        if (isset($userExpireDate)) {
208
+            // if the admin decided to enforce the default expire date then we only take
209
+            // the user defined expire date of it is before the default expire date
210
+            if ($defaultExpires && !empty($defaultExpireSettings['enforceExpireDate'])) {
211
+                $expires = min($userExpireDate, $defaultExpires);
212
+            } else {
213
+                $expires = $userExpireDate;
214
+            }
215
+        } else if ($defaultExpires && !empty($defaultExpireSettings['enforceExpireDate'])) {
216
+            $expires = $defaultExpires;
217
+        }
218 218
 
219
-		return $expires;
220
-	}
219
+        return $expires;
220
+    }
221 221
 
222
-	/**
223
-	 * Strips away a potential file names and trailing slashes:
224
-	 * - http://localhost
225
-	 * - http://localhost/
226
-	 * - http://localhost/index.php
227
-	 * - http://localhost/index.php/s/{shareToken}
228
-	 *
229
-	 * all return: http://localhost
230
-	 *
231
-	 * @param string $remote
232
-	 * @return string
233
-	 */
234
-	protected static function fixRemoteURL($remote) {
235
-		$remote = str_replace('\\', '/', $remote);
236
-		if ($fileNamePosition = strpos($remote, '/index.php')) {
237
-			$remote = substr($remote, 0, $fileNamePosition);
238
-		}
239
-		$remote = rtrim($remote, '/');
222
+    /**
223
+     * Strips away a potential file names and trailing slashes:
224
+     * - http://localhost
225
+     * - http://localhost/
226
+     * - http://localhost/index.php
227
+     * - http://localhost/index.php/s/{shareToken}
228
+     *
229
+     * all return: http://localhost
230
+     *
231
+     * @param string $remote
232
+     * @return string
233
+     */
234
+    protected static function fixRemoteURL($remote) {
235
+        $remote = str_replace('\\', '/', $remote);
236
+        if ($fileNamePosition = strpos($remote, '/index.php')) {
237
+            $remote = substr($remote, 0, $fileNamePosition);
238
+        }
239
+        $remote = rtrim($remote, '/');
240 240
 
241
-		return $remote;
242
-	}
241
+        return $remote;
242
+    }
243 243
 
244
-	/**
245
-	 * split user and remote from federated cloud id
246
-	 *
247
-	 * @param string $id
248
-	 * @return string[]
249
-	 * @throws HintException
250
-	 */
251
-	public static function splitUserRemote($id) {
252
-		try {
253
-			$cloudId = \OC::$server->getCloudIdManager()->resolveCloudId($id);
254
-			return [$cloudId->getUser(), $cloudId->getRemote()];
255
-		} catch (\InvalidArgumentException $e) {
256
-			$l = \OC::$server->getL10N('core');
257
-			$hint = $l->t('Invalid Federated Cloud ID');
258
-			throw new HintException('Invalid Federated Cloud ID', $hint, 0, $e);
259
-		}
260
-	}
244
+    /**
245
+     * split user and remote from federated cloud id
246
+     *
247
+     * @param string $id
248
+     * @return string[]
249
+     * @throws HintException
250
+     */
251
+    public static function splitUserRemote($id) {
252
+        try {
253
+            $cloudId = \OC::$server->getCloudIdManager()->resolveCloudId($id);
254
+            return [$cloudId->getUser(), $cloudId->getRemote()];
255
+        } catch (\InvalidArgumentException $e) {
256
+            $l = \OC::$server->getL10N('core');
257
+            $hint = $l->t('Invalid Federated Cloud ID');
258
+            throw new HintException('Invalid Federated Cloud ID', $hint, 0, $e);
259
+        }
260
+    }
261 261
 
262
-	/**
263
-	 * check if two federated cloud IDs refer to the same user
264
-	 *
265
-	 * @param string $user1
266
-	 * @param string $server1
267
-	 * @param string $user2
268
-	 * @param string $server2
269
-	 * @return bool true if both users and servers are the same
270
-	 */
271
-	public static function isSameUserOnSameServer($user1, $server1, $user2, $server2) {
272
-		$normalizedServer1 = strtolower(\OC\Share\Share::removeProtocolFromUrl($server1));
273
-		$normalizedServer2 = strtolower(\OC\Share\Share::removeProtocolFromUrl($server2));
262
+    /**
263
+     * check if two federated cloud IDs refer to the same user
264
+     *
265
+     * @param string $user1
266
+     * @param string $server1
267
+     * @param string $user2
268
+     * @param string $server2
269
+     * @return bool true if both users and servers are the same
270
+     */
271
+    public static function isSameUserOnSameServer($user1, $server1, $user2, $server2) {
272
+        $normalizedServer1 = strtolower(\OC\Share\Share::removeProtocolFromUrl($server1));
273
+        $normalizedServer2 = strtolower(\OC\Share\Share::removeProtocolFromUrl($server2));
274 274
 
275
-		if (rtrim($normalizedServer1, '/') === rtrim($normalizedServer2, '/')) {
276
-			// FIXME this should be a method in the user management instead
277
-			\OCP\Util::emitHook(
278
-					'\OCA\Files_Sharing\API\Server2Server',
279
-					'preLoginNameUsedAsUserName',
280
-					['uid' => &$user1]
281
-			);
282
-			\OCP\Util::emitHook(
283
-					'\OCA\Files_Sharing\API\Server2Server',
284
-					'preLoginNameUsedAsUserName',
285
-					['uid' => &$user2]
286
-			);
275
+        if (rtrim($normalizedServer1, '/') === rtrim($normalizedServer2, '/')) {
276
+            // FIXME this should be a method in the user management instead
277
+            \OCP\Util::emitHook(
278
+                    '\OCA\Files_Sharing\API\Server2Server',
279
+                    'preLoginNameUsedAsUserName',
280
+                    ['uid' => &$user1]
281
+            );
282
+            \OCP\Util::emitHook(
283
+                    '\OCA\Files_Sharing\API\Server2Server',
284
+                    'preLoginNameUsedAsUserName',
285
+                    ['uid' => &$user2]
286
+            );
287 287
 
288
-			if ($user1 === $user2) {
289
-				return true;
290
-			}
291
-		}
288
+            if ($user1 === $user2) {
289
+                return true;
290
+            }
291
+        }
292 292
 
293
-		return false;
294
-	}
293
+        return false;
294
+    }
295 295
 }
Please login to merge, or discard this patch.
lib/private/Share/SearchResultSorter.php 1 patch
Indentation   +43 added lines, -43 removed lines patch added patch discarded remove patch
@@ -28,50 +28,50 @@
 block discarded – undo
28 28
 use OCP\ILogger;
29 29
 
30 30
 class SearchResultSorter {
31
-	private $search;
32
-	private $encoding;
33
-	private $key;
34
-	private $log;
31
+    private $search;
32
+    private $encoding;
33
+    private $key;
34
+    private $log;
35 35
 
36
-	/**
37
-	 * @param string $search the search term as was given by the user
38
-	 * @param string $key the array key containing the value that should be compared
39
-	 * against
40
-	 * @param string $encoding optional, encoding to use, defaults to UTF-8
41
-	 * @param ILogger $log optional
42
-	 */
43
-	public function __construct($search, $key, ILogger $log = null, $encoding = 'UTF-8') {
44
-		$this->encoding = $encoding;
45
-		$this->key = $key;
46
-		$this->log = $log;
47
-		$this->search = mb_strtolower($search, $this->encoding);
48
-	}
36
+    /**
37
+     * @param string $search the search term as was given by the user
38
+     * @param string $key the array key containing the value that should be compared
39
+     * against
40
+     * @param string $encoding optional, encoding to use, defaults to UTF-8
41
+     * @param ILogger $log optional
42
+     */
43
+    public function __construct($search, $key, ILogger $log = null, $encoding = 'UTF-8') {
44
+        $this->encoding = $encoding;
45
+        $this->key = $key;
46
+        $this->log = $log;
47
+        $this->search = mb_strtolower($search, $this->encoding);
48
+    }
49 49
 
50
-	/**
51
-	 * User and Group names matching the search term at the beginning shall appear
52
-	 * on top of the share dialog. Following entries in alphabetical order.
53
-	 * Callback function for usort. http://php.net/usort
54
-	 */
55
-	public function sort($a, $b) {
56
-		if(!isset($a[$this->key]) || !isset($b[$this->key])) {
57
-			if(!is_null($this->log)) {
58
-				$this->log->error('Sharing dialogue: cannot sort due to ' .
59
-								  'missing array key', ['app' => 'core']);
60
-			}
61
-			return 0;
62
-		}
63
-		$nameA = mb_strtolower($a[$this->key], $this->encoding);
64
-		$nameB = mb_strtolower($b[$this->key], $this->encoding);
65
-		$i = mb_strpos($nameA, $this->search, 0, $this->encoding);
66
-		$j = mb_strpos($nameB, $this->search, 0, $this->encoding);
50
+    /**
51
+     * User and Group names matching the search term at the beginning shall appear
52
+     * on top of the share dialog. Following entries in alphabetical order.
53
+     * Callback function for usort. http://php.net/usort
54
+     */
55
+    public function sort($a, $b) {
56
+        if(!isset($a[$this->key]) || !isset($b[$this->key])) {
57
+            if(!is_null($this->log)) {
58
+                $this->log->error('Sharing dialogue: cannot sort due to ' .
59
+                                    'missing array key', ['app' => 'core']);
60
+            }
61
+            return 0;
62
+        }
63
+        $nameA = mb_strtolower($a[$this->key], $this->encoding);
64
+        $nameB = mb_strtolower($b[$this->key], $this->encoding);
65
+        $i = mb_strpos($nameA, $this->search, 0, $this->encoding);
66
+        $j = mb_strpos($nameB, $this->search, 0, $this->encoding);
67 67
 
68
-		if($i === $j || $i > 0 && $j > 0) {
69
-			return strcmp(mb_strtolower($nameA, $this->encoding),
70
-						  mb_strtolower($nameB, $this->encoding));
71
-		} elseif ($i === 0) {
72
-			return -1;
73
-		} else {
74
-			return 1;
75
-		}
76
-	}
68
+        if($i === $j || $i > 0 && $j > 0) {
69
+            return strcmp(mb_strtolower($nameA, $this->encoding),
70
+                            mb_strtolower($nameB, $this->encoding));
71
+        } elseif ($i === 0) {
72
+            return -1;
73
+        } else {
74
+            return 1;
75
+        }
76
+    }
77 77
 }
Please login to merge, or discard this patch.
lib/private/Share/Constants.php 1 patch
Indentation   +49 added lines, -49 removed lines patch added patch discarded remove patch
@@ -33,57 +33,57 @@
 block discarded – undo
33 33
 
34 34
 class Constants {
35 35
 
36
-	/**
37
-	 * @deprecated 17.0.0 - use IShare::TYPE_USER instead
38
-	 */
39
-	const SHARE_TYPE_USER = 0;
40
-	/**
41
-	 * @deprecated 17.0.0 - use IShare::TYPE_GROUP instead
42
-	 */
43
-	const SHARE_TYPE_GROUP = 1;
44
-	// const SHARE_TYPE_USERGROUP = 2; // Internal type used by DefaultShareProvider
45
-	/**
46
-	 * @deprecated 17.0.0 - use IShare::TYPE_LINK instead
47
-	 */
48
-	const SHARE_TYPE_LINK = 3;
49
-	/**
50
-	 * @deprecated 17.0.0 - use IShare::TYPE_EMAIL instead
51
-	 */
52
-	const SHARE_TYPE_EMAIL = 4;
53
-	const SHARE_TYPE_CONTACT = 5; // ToDo Check if it is still in use otherwise remove it
54
-	/**
55
-	 * @deprecated 17.0.0 - use IShare::TYPE_REMOTE instead
56
-	 */
57
-	const SHARE_TYPE_REMOTE = 6;
58
-	/**
59
-	 * @deprecated 17.0.0 - use IShare::TYPE_CIRCLE instead
60
-	 */
61
-	const SHARE_TYPE_CIRCLE = 7;
62
-	/**
63
-	 * @deprecated 17.0.0 - use IShare::TYPE_GUEST instead
64
-	 */
65
-	const SHARE_TYPE_GUEST = 8;
66
-	/**
67
-	 * @deprecated 17.0.0 - use IShare::REMOTE_GROUP instead
68
-	 */
69
-	const SHARE_TYPE_REMOTE_GROUP = 9;
70
-	/**
71
-	 * @deprecated 17.0.0 - use IShare::TYPE_ROOM instead
72
-	 */
73
-	const SHARE_TYPE_ROOM = 10;
74
-	// const SHARE_TYPE_USERROOM = 11; // Internal type used by RoomShareProvider
36
+    /**
37
+     * @deprecated 17.0.0 - use IShare::TYPE_USER instead
38
+     */
39
+    const SHARE_TYPE_USER = 0;
40
+    /**
41
+     * @deprecated 17.0.0 - use IShare::TYPE_GROUP instead
42
+     */
43
+    const SHARE_TYPE_GROUP = 1;
44
+    // const SHARE_TYPE_USERGROUP = 2; // Internal type used by DefaultShareProvider
45
+    /**
46
+     * @deprecated 17.0.0 - use IShare::TYPE_LINK instead
47
+     */
48
+    const SHARE_TYPE_LINK = 3;
49
+    /**
50
+     * @deprecated 17.0.0 - use IShare::TYPE_EMAIL instead
51
+     */
52
+    const SHARE_TYPE_EMAIL = 4;
53
+    const SHARE_TYPE_CONTACT = 5; // ToDo Check if it is still in use otherwise remove it
54
+    /**
55
+     * @deprecated 17.0.0 - use IShare::TYPE_REMOTE instead
56
+     */
57
+    const SHARE_TYPE_REMOTE = 6;
58
+    /**
59
+     * @deprecated 17.0.0 - use IShare::TYPE_CIRCLE instead
60
+     */
61
+    const SHARE_TYPE_CIRCLE = 7;
62
+    /**
63
+     * @deprecated 17.0.0 - use IShare::TYPE_GUEST instead
64
+     */
65
+    const SHARE_TYPE_GUEST = 8;
66
+    /**
67
+     * @deprecated 17.0.0 - use IShare::REMOTE_GROUP instead
68
+     */
69
+    const SHARE_TYPE_REMOTE_GROUP = 9;
70
+    /**
71
+     * @deprecated 17.0.0 - use IShare::TYPE_ROOM instead
72
+     */
73
+    const SHARE_TYPE_ROOM = 10;
74
+    // const SHARE_TYPE_USERROOM = 11; // Internal type used by RoomShareProvider
75 75
 
76
-	const FORMAT_NONE = -1;
77
-	const FORMAT_STATUSES = -2;
78
-	const FORMAT_SOURCES = -3;  // ToDo Check if it is still in use otherwise remove it
76
+    const FORMAT_NONE = -1;
77
+    const FORMAT_STATUSES = -2;
78
+    const FORMAT_SOURCES = -3;  // ToDo Check if it is still in use otherwise remove it
79 79
 
80
-	const RESPONSE_FORMAT = 'json'; // default resonse format for ocs calls
80
+    const RESPONSE_FORMAT = 'json'; // default resonse format for ocs calls
81 81
 
82
-	const TOKEN_LENGTH = 15; // old (oc7) length is 32, keep token length in db at least that for compatibility
82
+    const TOKEN_LENGTH = 15; // old (oc7) length is 32, keep token length in db at least that for compatibility
83 83
 
84
-	protected static $shareTypeUserAndGroups = -1;
85
-	protected static $shareTypeGroupUserUnique = 2;
86
-	protected static $backends = [];
87
-	protected static $backendTypes = [];
88
-	protected static $isResharingAllowed;
84
+    protected static $shareTypeUserAndGroups = -1;
85
+    protected static $shareTypeGroupUserUnique = 2;
86
+    protected static $backends = [];
87
+    protected static $backendTypes = [];
88
+    protected static $isResharingAllowed;
89 89
 }
Please login to merge, or discard this patch.
lib/private/Share/Share.php 1 patch
Indentation   +1496 added lines, -1496 removed lines patch added patch discarded remove patch
@@ -50,1500 +50,1500 @@
 block discarded – undo
50 50
  */
51 51
 class Share extends Constants {
52 52
 
53
-	/** CRUDS permissions (Create, Read, Update, Delete, Share) using a bitmask
54
-	 * Construct permissions for share() and setPermissions with Or (|) e.g.
55
-	 * Give user read and update permissions: PERMISSION_READ | PERMISSION_UPDATE
56
-	 *
57
-	 * Check if permission is granted with And (&) e.g. Check if delete is
58
-	 * granted: if ($permissions & PERMISSION_DELETE)
59
-	 *
60
-	 * Remove permissions with And (&) and Not (~) e.g. Remove the update
61
-	 * permission: $permissions &= ~PERMISSION_UPDATE
62
-	 *
63
-	 * Apps are required to handle permissions on their own, this class only
64
-	 * stores and manages the permissions of shares
65
-	 * @see lib/public/constants.php
66
-	 */
67
-
68
-	/**
69
-	 * Register a sharing backend class that implements OCP\Share_Backend for an item type
70
-	 * @param string $itemType Item type
71
-	 * @param string $class Backend class
72
-	 * @param string $collectionOf (optional) Depends on item type
73
-	 * @param array $supportedFileExtensions (optional) List of supported file extensions if this item type depends on files
74
-	 * @return boolean true if backend is registered or false if error
75
-	 */
76
-	public static function registerBackend($itemType, $class, $collectionOf = null, $supportedFileExtensions = null) {
77
-		if (\OC::$server->getConfig()->getAppValue('core', 'shareapi_enabled', 'yes') == 'yes') {
78
-			if (!isset(self::$backendTypes[$itemType])) {
79
-				self::$backendTypes[$itemType] = [
80
-					'class' => $class,
81
-					'collectionOf' => $collectionOf,
82
-					'supportedFileExtensions' => $supportedFileExtensions
83
-				];
84
-				return true;
85
-			}
86
-			\OCP\Util::writeLog('OCP\Share',
87
-				'Sharing backend '.$class.' not registered, '.self::$backendTypes[$itemType]['class']
88
-				.' is already registered for '.$itemType,
89
-				ILogger::WARN);
90
-		}
91
-		return false;
92
-	}
93
-
94
-	/**
95
-	 * Get the items of item type shared with the current user
96
-	 * @param string $itemType
97
-	 * @param int $format (optional) Format type must be defined by the backend
98
-	 * @param mixed $parameters (optional)
99
-	 * @param int $limit Number of items to return (optional) Returns all by default
100
-	 * @param boolean $includeCollections (optional)
101
-	 * @return mixed Return depends on format
102
-	 * @deprecated TESTS ONLY - this methods is only used by tests
103
-	 * called like this:
104
-	 * \OC\Share\Share::getItemsSharedWith('folder'); (apps/files_sharing/tests/UpdaterTest.php)
105
-	 */
106
-	public static function getItemsSharedWith() {
107
-		return self::getItems('folder', null, self::$shareTypeUserAndGroups, \OC_User::getUser(), null, self::FORMAT_NONE,
108
-			null, -1, false);
109
-	}
110
-
111
-	/**
112
-	 * Get the items of item type shared with a user
113
-	 * @param string $itemType
114
-	 * @param string $user id for which user we want the shares
115
-	 * @param int $format (optional) Format type must be defined by the backend
116
-	 * @param mixed $parameters (optional)
117
-	 * @param int $limit Number of items to return (optional) Returns all by default
118
-	 * @param boolean $includeCollections (optional)
119
-	 * @return mixed Return depends on format
120
-	 */
121
-	public static function getItemsSharedWithUser($itemType, $user, $format = self::FORMAT_NONE,
122
-												  $parameters = null, $limit = -1, $includeCollections = false) {
123
-		return self::getItems($itemType, null, self::$shareTypeUserAndGroups, $user, null, $format,
124
-			$parameters, $limit, $includeCollections);
125
-	}
126
-
127
-	/**
128
-	 * Get the item of item type shared with a given user by source
129
-	 * @param string $itemType
130
-	 * @param string $itemSource
131
-	 * @param string $user User to whom the item was shared
132
-	 * @param string $owner Owner of the share
133
-	 * @param int $shareType only look for a specific share type
134
-	 * @return array Return list of items with file_target, permissions and expiration
135
-	 */
136
-	public static function getItemSharedWithUser($itemType, $itemSource, $user, $owner = null, $shareType = null) {
137
-		$shares = [];
138
-		$fileDependent = false;
139
-
140
-		$where = 'WHERE';
141
-		$fileDependentWhere = '';
142
-		if ($itemType === 'file' || $itemType === 'folder') {
143
-			$fileDependent = true;
144
-			$column = 'file_source';
145
-			$fileDependentWhere = 'INNER JOIN `*PREFIX*filecache` ON `file_source` = `*PREFIX*filecache`.`fileid` ';
146
-			$fileDependentWhere .= 'INNER JOIN `*PREFIX*storages` ON `numeric_id` = `*PREFIX*filecache`.`storage` ';
147
-		} else {
148
-			$column = 'item_source';
149
-		}
150
-
151
-		$select = self::createSelectStatement(self::FORMAT_NONE, $fileDependent);
152
-
153
-		$where .= ' `' . $column . '` = ? AND `item_type` = ? ';
154
-		$arguments = [$itemSource, $itemType];
155
-		// for link shares $user === null
156
-		if ($user !== null) {
157
-			$where .= ' AND `share_with` = ? ';
158
-			$arguments[] = $user;
159
-		}
160
-
161
-		if ($shareType !== null) {
162
-			$where .= ' AND `share_type` = ? ';
163
-			$arguments[] = $shareType;
164
-		}
165
-
166
-		if ($owner !== null) {
167
-			$where .= ' AND `uid_owner` = ? ';
168
-			$arguments[] = $owner;
169
-		}
170
-
171
-		$query = \OC_DB::prepare('SELECT ' . $select . ' FROM `*PREFIX*share` '. $fileDependentWhere . $where);
172
-
173
-		$result = \OC_DB::executeAudited($query, $arguments);
174
-
175
-		while ($row = $result->fetchRow()) {
176
-			if ($fileDependent && !self::isFileReachable($row['path'], $row['storage_id'])) {
177
-				continue;
178
-			}
179
-			if ($fileDependent && (int)$row['file_parent'] === -1) {
180
-				// if it is a mount point we need to get the path from the mount manager
181
-				$mountManager = \OC\Files\Filesystem::getMountManager();
182
-				$mountPoint = $mountManager->findByStorageId($row['storage_id']);
183
-				if (!empty($mountPoint)) {
184
-					$path = $mountPoint[0]->getMountPoint();
185
-					$path = trim($path, '/');
186
-					$path = substr($path, strlen($owner) + 1); //normalize path to 'files/foo.txt`
187
-					$row['path'] = $path;
188
-				} else {
189
-					\OC::$server->getLogger()->warning(
190
-						'Could not resolve mount point for ' . $row['storage_id'],
191
-						['app' => 'OCP\Share']
192
-					);
193
-				}
194
-			}
195
-			$shares[] = $row;
196
-		}
197
-
198
-		//if didn't found a result than let's look for a group share.
199
-		if(empty($shares) && $user !== null) {
200
-			$userObject = \OC::$server->getUserManager()->get($user);
201
-			$groups = [];
202
-			if ($userObject) {
203
-				$groups = \OC::$server->getGroupManager()->getUserGroupIds($userObject);
204
-			}
205
-
206
-			if (!empty($groups)) {
207
-				$where = $fileDependentWhere . ' WHERE `' . $column . '` = ? AND `item_type` = ? AND `share_with` in (?)';
208
-				$arguments = [$itemSource, $itemType, $groups];
209
-				$types = [null, null, IQueryBuilder::PARAM_STR_ARRAY];
210
-
211
-				if ($owner !== null) {
212
-					$where .= ' AND `uid_owner` = ?';
213
-					$arguments[] = $owner;
214
-					$types[] = null;
215
-				}
216
-
217
-				// TODO: inject connection, hopefully one day in the future when this
218
-				// class isn't static anymore...
219
-				$conn = \OC::$server->getDatabaseConnection();
220
-				$result = $conn->executeQuery(
221
-					'SELECT ' . $select . ' FROM `*PREFIX*share` ' . $where,
222
-					$arguments,
223
-					$types
224
-				);
225
-
226
-				while ($row = $result->fetch()) {
227
-					$shares[] = $row;
228
-				}
229
-			}
230
-		}
231
-
232
-		return $shares;
233
-
234
-	}
235
-
236
-	/**
237
-	 * Get the item of item type shared with the current user by source
238
-	 * @param string $itemType
239
-	 * @param string $itemSource
240
-	 * @param int $format (optional) Format type must be defined by the backend
241
-	 * @param mixed $parameters
242
-	 * @param boolean $includeCollections
243
-	 * @param string $shareWith (optional) define against which user should be checked, default: current user
244
-	 * @return array
245
-	 */
246
-	public static function getItemSharedWithBySource($itemType, $itemSource, $format = self::FORMAT_NONE,
247
-													 $parameters = null, $includeCollections = false, $shareWith = null) {
248
-		$shareWith = ($shareWith === null) ? \OC_User::getUser() : $shareWith;
249
-		return self::getItems($itemType, $itemSource, self::$shareTypeUserAndGroups, $shareWith, null, $format,
250
-			$parameters, 1, $includeCollections, true);
251
-	}
252
-
253
-	/**
254
-	 * Get the shared item of item type owned by the current user
255
-	 * @param string $itemType
256
-	 * @param string $itemSource
257
-	 * @param int $format (optional) Format type must be defined by the backend
258
-	 * @param mixed $parameters
259
-	 * @param boolean $includeCollections
260
-	 * @return mixed Return depends on format
261
-	 */
262
-	public static function getItemShared($itemType, $itemSource, $format = self::FORMAT_NONE,
263
-										 $parameters = null, $includeCollections = false) {
264
-		return self::getItems($itemType, $itemSource, null, null, \OC_User::getUser(), $format,
265
-			$parameters, -1, $includeCollections);
266
-	}
267
-
268
-	/**
269
-	 * Share an item with a user, group, or via private link
270
-	 * @param string $itemType
271
-	 * @param string $itemSource
272
-	 * @param int $shareType SHARE_TYPE_USER, SHARE_TYPE_GROUP, or SHARE_TYPE_LINK
273
-	 * @param string $shareWith User or group the item is being shared with
274
-	 * @param int $permissions CRUDS
275
-	 * @param string $itemSourceName
276
-	 * @param \DateTime|null $expirationDate
277
-	 * @return boolean|string Returns true on success or false on failure, Returns token on success for links
278
-	 * @throws \OC\HintException when the share type is remote and the shareWith is invalid
279
-	 * @throws \Exception
280
-	 * @since 5.0.0 - parameter $itemSourceName was added in 6.0.0, parameter $expirationDate was added in 7.0.0, parameter $passwordChanged added in 9.0.0
281
-	 * @deprecated 14.0.0 TESTS ONLY - this methods is as of 2018-06 only used by tests
282
-	 * called like this:
283
-	 * \OC\Share\Share::shareItem('test', 1, \OCP\Share::SHARE_TYPE_USER, $otherUserId, \OCP\Constants::PERMISSION_READ);
284
-	 */
285
-	public static function shareItem($itemType, $itemSource, $shareType, $shareWith, $permissions) {
286
-		$backend = self::getBackend($itemType);
287
-
288
-		if ($backend->isShareTypeAllowed($shareType) === false) {
289
-			$message = 'Sharing failed, because the backend does not allow shares from type %i';
290
-			throw new \Exception(sprintf($message, $shareType));
291
-		}
292
-
293
-		$uidOwner = \OC_User::getUser();
294
-
295
-		// Verify share type and sharing conditions are met
296
-		if ($shareType === self::SHARE_TYPE_USER) {
297
-			if ($shareWith == $uidOwner) {
298
-				$message = 'Sharing failed, because you can not share with yourself';
299
-				throw new \Exception($message);
300
-			}
301
-			if (!\OC::$server->getUserManager()->userExists($shareWith)) {
302
-				$message = 'Sharing failed, because the user %s does not exist';
303
-				throw new \Exception(sprintf($message, $shareWith));
304
-			}
305
-			// Check if the item source is already shared with the user, either from the same owner or a different user
306
-			if ($checkExists = self::getItems($itemType, $itemSource, self::$shareTypeUserAndGroups,
307
-				$shareWith, null, self::FORMAT_NONE, null, 1, true, true)) {
308
-				// Only allow the same share to occur again if it is the same
309
-				// owner and is not a user share, this use case is for increasing
310
-				// permissions for a specific user
311
-				if ($checkExists['uid_owner'] != $uidOwner || $checkExists['share_type'] == $shareType) {
312
-					$message = 'Sharing failed, because this item is already shared with %s';
313
-					throw new \Exception(sprintf($message, $shareWith));
314
-				}
315
-			}
316
-			if ($checkExists = self::getItems($itemType, $itemSource, self::SHARE_TYPE_USER,
317
-				$shareWith, null, self::FORMAT_NONE, null, 1, true, true)) {
318
-				// Only allow the same share to occur again if it is the same
319
-				// owner and is not a user share, this use case is for increasing
320
-				// permissions for a specific user
321
-				if ($checkExists['uid_owner'] != $uidOwner || $checkExists['share_type'] == $shareType) {
322
-					$message = 'Sharing failed, because this item is already shared with user %s';
323
-					throw new \Exception(sprintf($message, $shareWith));
324
-				}
325
-			}
326
-		}
327
-
328
-		// Put the item into the database
329
-		$result = self::put('test', $itemSource, self::SHARE_TYPE_USER, $shareWith, $uidOwner, $permissions);
330
-
331
-		return $result ? true : false;
332
-	}
333
-
334
-	/**
335
-	 * Unshare an item from a user, group, or delete a private link
336
-	 * @param string $itemType
337
-	 * @param string $itemSource
338
-	 * @param int $shareType SHARE_TYPE_USER, SHARE_TYPE_GROUP, or SHARE_TYPE_LINK
339
-	 * @param string $shareWith User or group the item is being shared with
340
-	 * @param string $owner owner of the share, if null the current user is used
341
-	 * @return boolean true on success or false on failure
342
-	 */
343
-	public static function unshare($itemType, $itemSource, $shareType, $shareWith, $owner = null) {
344
-
345
-		// check if it is a valid itemType
346
-		self::getBackend($itemType);
347
-
348
-		$items = self::getItemSharedWithUser($itemType, $itemSource, $shareWith, $owner, $shareType);
349
-
350
-		$toDelete = [];
351
-		$newParent = null;
352
-		$currentUser = $owner ? $owner : \OC_User::getUser();
353
-		foreach ($items as $item) {
354
-			// delete the item with the expected share_type and owner
355
-			if ((int)$item['share_type'] === (int)$shareType && $item['uid_owner'] === $currentUser) {
356
-				$toDelete = $item;
357
-				// if there is more then one result we don't have to delete the children
358
-				// but update their parent. For group shares the new parent should always be
359
-				// the original group share and not the db entry with the unique name
360
-			} else if ((int)$item['share_type'] === self::$shareTypeGroupUserUnique) {
361
-				$newParent = $item['parent'];
362
-			} else {
363
-				$newParent = $item['id'];
364
-			}
365
-		}
366
-
367
-		if (!empty($toDelete)) {
368
-			self::unshareItem($toDelete, $newParent);
369
-			return true;
370
-		}
371
-		return false;
372
-	}
373
-
374
-	/**
375
-	 * Checks whether a share has expired, calls unshareItem() if yes.
376
-	 * @param array $item Share data (usually database row)
377
-	 * @return boolean True if item was expired, false otherwise.
378
-	 */
379
-	protected static function expireItem(array $item) {
380
-
381
-		$result = false;
382
-
383
-		// only use default expiration date for link shares
384
-		if ((int) $item['share_type'] === self::SHARE_TYPE_LINK) {
385
-
386
-			// calculate expiration date
387
-			if (!empty($item['expiration'])) {
388
-				$userDefinedExpire = new \DateTime($item['expiration']);
389
-				$expires = $userDefinedExpire->getTimestamp();
390
-			} else {
391
-				$expires = null;
392
-			}
393
-
394
-
395
-			// get default expiration settings
396
-			$defaultSettings = Helper::getDefaultExpireSetting();
397
-			$expires = Helper::calculateExpireDate($defaultSettings, $item['stime'], $expires);
398
-
399
-
400
-			if (is_int($expires)) {
401
-				$now = time();
402
-				if ($now > $expires) {
403
-					self::unshareItem($item);
404
-					$result = true;
405
-				}
406
-			}
407
-		}
408
-		return $result;
409
-	}
410
-
411
-	/**
412
-	 * Unshares a share given a share data array
413
-	 * @param array $item Share data (usually database row)
414
-	 * @param int $newParent parent ID
415
-	 * @return null
416
-	 */
417
-	protected static function unshareItem(array $item, $newParent = null) {
418
-
419
-		$shareType = (int)$item['share_type'];
420
-		$shareWith = null;
421
-		if ($shareType !== \OCP\Share::SHARE_TYPE_LINK) {
422
-			$shareWith = $item['share_with'];
423
-		}
424
-
425
-		// Pass all the vars we have for now, they may be useful
426
-		$hookParams = [
427
-			'id'            => $item['id'],
428
-			'itemType'      => $item['item_type'],
429
-			'itemSource'    => $item['item_source'],
430
-			'shareType'     => $shareType,
431
-			'shareWith'     => $shareWith,
432
-			'itemParent'    => $item['parent'],
433
-			'uidOwner'      => $item['uid_owner'],
434
-		];
435
-		if($item['item_type'] === 'file' || $item['item_type'] === 'folder') {
436
-			$hookParams['fileSource'] = $item['file_source'];
437
-			$hookParams['fileTarget'] = $item['file_target'];
438
-		}
439
-
440
-		\OC_Hook::emit(\OCP\Share::class, 'pre_unshare', $hookParams);
441
-		$deletedShares = Helper::delete($item['id'], false, null, $newParent);
442
-		$deletedShares[] = $hookParams;
443
-		$hookParams['deletedShares'] = $deletedShares;
444
-		\OC_Hook::emit(\OCP\Share::class, 'post_unshare', $hookParams);
445
-		if ((int)$item['share_type'] === \OCP\Share::SHARE_TYPE_REMOTE && \OC::$server->getUserSession()->getUser()) {
446
-			list(, $remote) = Helper::splitUserRemote($item['share_with']);
447
-			self::sendRemoteUnshare($remote, $item['id'], $item['token']);
448
-		}
449
-	}
450
-
451
-	/**
452
-	 * Get the backend class for the specified item type
453
-	 * @param string $itemType
454
-	 * @throws \Exception
455
-	 * @return \OCP\Share_Backend
456
-	 */
457
-	public static function getBackend($itemType) {
458
-		$l = \OC::$server->getL10N('lib');
459
-		if (isset(self::$backends[$itemType])) {
460
-			return self::$backends[$itemType];
461
-		} else if (isset(self::$backendTypes[$itemType]['class'])) {
462
-			$class = self::$backendTypes[$itemType]['class'];
463
-			if (class_exists($class)) {
464
-				self::$backends[$itemType] = new $class;
465
-				if (!(self::$backends[$itemType] instanceof \OCP\Share_Backend)) {
466
-					$message = 'Sharing backend %s must implement the interface OCP\Share_Backend';
467
-					$message_t = $l->t('Sharing backend %s must implement the interface OCP\Share_Backend', [$class]);
468
-					\OCP\Util::writeLog('OCP\Share', sprintf($message, $class), ILogger::ERROR);
469
-					throw new \Exception($message_t);
470
-				}
471
-				return self::$backends[$itemType];
472
-			} else {
473
-				$message = 'Sharing backend %s not found';
474
-				$message_t = $l->t('Sharing backend %s not found', [$class]);
475
-				\OCP\Util::writeLog('OCP\Share', sprintf($message, $class), ILogger::ERROR);
476
-				throw new \Exception($message_t);
477
-			}
478
-		}
479
-		$message = 'Sharing backend for %s not found';
480
-		$message_t = $l->t('Sharing backend for %s not found', [$itemType]);
481
-		\OCP\Util::writeLog('OCP\Share', sprintf($message, $itemType), ILogger::ERROR);
482
-		throw new \Exception($message_t);
483
-	}
484
-
485
-	/**
486
-	 * Check if resharing is allowed
487
-	 * @return boolean true if allowed or false
488
-	 *
489
-	 * Resharing is allowed by default if not configured
490
-	 */
491
-	public static function isResharingAllowed() {
492
-		if (!isset(self::$isResharingAllowed)) {
493
-			if (\OC::$server->getConfig()->getAppValue('core', 'shareapi_allow_resharing', 'yes') == 'yes') {
494
-				self::$isResharingAllowed = true;
495
-			} else {
496
-				self::$isResharingAllowed = false;
497
-			}
498
-		}
499
-		return self::$isResharingAllowed;
500
-	}
501
-
502
-	/**
503
-	 * Get a list of collection item types for the specified item type
504
-	 * @param string $itemType
505
-	 * @return array
506
-	 */
507
-	private static function getCollectionItemTypes($itemType) {
508
-		$collectionTypes = [$itemType];
509
-		foreach (self::$backendTypes as $type => $backend) {
510
-			if (in_array($backend['collectionOf'], $collectionTypes)) {
511
-				$collectionTypes[] = $type;
512
-			}
513
-		}
514
-		// TODO Add option for collections to be collection of themselves, only 'folder' does it now...
515
-		if (isset(self::$backendTypes[$itemType]) && (!self::getBackend($itemType) instanceof \OCP\Share_Backend_Collection || $itemType != 'folder')) {
516
-			unset($collectionTypes[0]);
517
-		}
518
-		// Return array if collections were found or the item type is a
519
-		// collection itself - collections can be inside collections
520
-		if (count($collectionTypes) > 0) {
521
-			return $collectionTypes;
522
-		}
523
-		return false;
524
-	}
525
-
526
-	/**
527
-	 * Get the owners of items shared with a user.
528
-	 *
529
-	 * @param string $user The user the items are shared with.
530
-	 * @param string $type The type of the items shared with the user.
531
-	 * @param boolean $includeCollections Include collection item types (optional)
532
-	 * @param boolean $includeOwner include owner in the list of users the item is shared with (optional)
533
-	 * @return array
534
-	 * @deprecated TESTS ONLY - this methods is only used by tests
535
-	 * called like this:
536
-	 * \OC\Share\Share::getSharedItemsOwners($this->user, $this->type, true)
537
-	 */
538
-	public static function getSharedItemsOwners($user, $type, $includeCollections = false, $includeOwner = false) {
539
-		// First, we find out if $type is part of a collection (and if that collection is part of
540
-		// another one and so on).
541
-		$collectionTypes = [];
542
-		if (!$includeCollections || !$collectionTypes = self::getCollectionItemTypes($type)) {
543
-			$collectionTypes[] = $type;
544
-		}
545
-
546
-		// Of these collection types, along with our original $type, we make a
547
-		// list of the ones for which a sharing backend has been registered.
548
-		// FIXME: Ideally, we wouldn't need to nest getItemsSharedWith in this loop but just call it
549
-		// with its $includeCollections parameter set to true. Unfortunately, this fails currently.
550
-		$allMaybeSharedItems = [];
551
-		foreach ($collectionTypes as $collectionType) {
552
-			if (isset(self::$backends[$collectionType])) {
553
-				$allMaybeSharedItems[$collectionType] = self::getItemsSharedWithUser(
554
-					$collectionType,
555
-					$user,
556
-					self::FORMAT_NONE
557
-				);
558
-			}
559
-		}
560
-
561
-		$owners = [];
562
-		if ($includeOwner) {
563
-			$owners[] = $user;
564
-		}
565
-
566
-		// We take a look at all shared items of the given $type (or of the collections it is part of)
567
-		// and find out their owners. Then, we gather the tags for the original $type from all owners,
568
-		// and return them as elements of a list that look like "Tag (owner)".
569
-		foreach ($allMaybeSharedItems as $collectionType => $maybeSharedItems) {
570
-			foreach ($maybeSharedItems as $sharedItem) {
571
-				if (isset($sharedItem['id'])) { //workaround for https://github.com/owncloud/core/issues/2814
572
-					$owners[] = $sharedItem['uid_owner'];
573
-				}
574
-			}
575
-		}
576
-
577
-		return $owners;
578
-	}
579
-
580
-	/**
581
-	 * Get shared items from the database
582
-	 * @param string $itemType
583
-	 * @param string $item Item source or target (optional)
584
-	 * @param int $shareType SHARE_TYPE_USER, SHARE_TYPE_GROUP, SHARE_TYPE_LINK, $shareTypeUserAndGroups, or $shareTypeGroupUserUnique
585
-	 * @param string $shareWith User or group the item is being shared with
586
-	 * @param string $uidOwner User that is the owner of shared items (optional)
587
-	 * @param int $format Format to convert items to with formatItems() (optional)
588
-	 * @param mixed $parameters to pass to formatItems() (optional)
589
-	 * @param int $limit Number of items to return, -1 to return all matches (optional)
590
-	 * @param boolean $includeCollections Include collection item types (optional)
591
-	 * @param boolean $itemShareWithBySource (optional)
592
-	 * @param boolean $checkExpireDate
593
-	 * @return array
594
-	 *
595
-	 * See public functions getItem(s)... for parameter usage
596
-	 *
597
-	 */
598
-	public static function getItems($itemType, $item = null, $shareType = null, $shareWith = null,
599
-									$uidOwner = null, $format = self::FORMAT_NONE, $parameters = null, $limit = -1,
600
-									$includeCollections = false, $itemShareWithBySource = false, $checkExpireDate  = true) {
601
-		if (\OC::$server->getConfig()->getAppValue('core', 'shareapi_enabled', 'yes') != 'yes') {
602
-			return [];
603
-		}
604
-		$backend = self::getBackend($itemType);
605
-		$collectionTypes = false;
606
-		// Get filesystem root to add it to the file target and remove from the
607
-		// file source, match file_source with the file cache
608
-		if ($itemType == 'file' || $itemType == 'folder') {
609
-			if(!is_null($uidOwner)) {
610
-				$root = \OC\Files\Filesystem::getRoot();
611
-			} else {
612
-				$root = '';
613
-			}
614
-			$where = 'INNER JOIN `*PREFIX*filecache` ON `file_source` = `*PREFIX*filecache`.`fileid` ';
615
-			if (!isset($item)) {
616
-				$where .= ' AND `file_target` IS NOT NULL ';
617
-			}
618
-			$where .= 'INNER JOIN `*PREFIX*storages` ON `numeric_id` = `*PREFIX*filecache`.`storage` ';
619
-			$fileDependent = true;
620
-			$queryArgs = [];
621
-		} else {
622
-			$fileDependent = false;
623
-			$root = '';
624
-			$collectionTypes = self::getCollectionItemTypes($itemType);
625
-			if ($includeCollections && !isset($item) && $collectionTypes) {
626
-				// If includeCollections is true, find collections of this item type, e.g. a music album contains songs
627
-				if (!in_array($itemType, $collectionTypes)) {
628
-					$itemTypes = array_merge([$itemType], $collectionTypes);
629
-				} else {
630
-					$itemTypes = $collectionTypes;
631
-				}
632
-				$placeholders = implode(',', array_fill(0, count($itemTypes), '?'));
633
-				$where = ' WHERE `item_type` IN ('.$placeholders.'))';
634
-				$queryArgs = $itemTypes;
635
-			} else {
636
-				$where = ' WHERE `item_type` = ?';
637
-				$queryArgs = [$itemType];
638
-			}
639
-		}
640
-		if (\OC::$server->getConfig()->getAppValue('core', 'shareapi_allow_links', 'yes') !== 'yes') {
641
-			$where .= ' AND `share_type` != ?';
642
-			$queryArgs[] = self::SHARE_TYPE_LINK;
643
-		}
644
-		if (isset($shareType)) {
645
-			// Include all user and group items
646
-			if ($shareType == self::$shareTypeUserAndGroups && isset($shareWith)) {
647
-				$where .= ' AND ((`share_type` in (?, ?) AND `share_with` = ?) ';
648
-				$queryArgs[] = self::SHARE_TYPE_USER;
649
-				$queryArgs[] = self::$shareTypeGroupUserUnique;
650
-				$queryArgs[] = $shareWith;
651
-
652
-				$user = \OC::$server->getUserManager()->get($shareWith);
653
-				$groups = [];
654
-				if ($user) {
655
-					$groups = \OC::$server->getGroupManager()->getUserGroupIds($user);
656
-				}
657
-				if (!empty($groups)) {
658
-					$placeholders = implode(',', array_fill(0, count($groups), '?'));
659
-					$where .= ' OR (`share_type` = ? AND `share_with` IN ('.$placeholders.')) ';
660
-					$queryArgs[] = self::SHARE_TYPE_GROUP;
661
-					$queryArgs = array_merge($queryArgs, $groups);
662
-				}
663
-				$where .= ')';
664
-				// Don't include own group shares
665
-				$where .= ' AND `uid_owner` != ?';
666
-				$queryArgs[] = $shareWith;
667
-			} else {
668
-				$where .= ' AND `share_type` = ?';
669
-				$queryArgs[] = $shareType;
670
-				if (isset($shareWith)) {
671
-					$where .= ' AND `share_with` = ?';
672
-					$queryArgs[] = $shareWith;
673
-				}
674
-			}
675
-		}
676
-		if (isset($uidOwner)) {
677
-			$where .= ' AND `uid_owner` = ?';
678
-			$queryArgs[] = $uidOwner;
679
-			if (!isset($shareType)) {
680
-				// Prevent unique user targets for group shares from being selected
681
-				$where .= ' AND `share_type` != ?';
682
-				$queryArgs[] = self::$shareTypeGroupUserUnique;
683
-			}
684
-			if ($fileDependent) {
685
-				$column = 'file_source';
686
-			} else {
687
-				$column = 'item_source';
688
-			}
689
-		} else {
690
-			if ($fileDependent) {
691
-				$column = 'file_target';
692
-			} else {
693
-				$column = 'item_target';
694
-			}
695
-		}
696
-		if (isset($item)) {
697
-			$collectionTypes = self::getCollectionItemTypes($itemType);
698
-			if ($includeCollections && $collectionTypes && !in_array('folder', $collectionTypes)) {
699
-				$where .= ' AND (';
700
-			} else {
701
-				$where .= ' AND';
702
-			}
703
-			// If looking for own shared items, check item_source else check item_target
704
-			if (isset($uidOwner) || $itemShareWithBySource) {
705
-				// If item type is a file, file source needs to be checked in case the item was converted
706
-				if ($fileDependent) {
707
-					$where .= ' `file_source` = ?';
708
-					$column = 'file_source';
709
-				} else {
710
-					$where .= ' `item_source` = ?';
711
-					$column = 'item_source';
712
-				}
713
-			} else {
714
-				if ($fileDependent) {
715
-					$where .= ' `file_target` = ?';
716
-					$item = \OC\Files\Filesystem::normalizePath($item);
717
-				} else {
718
-					$where .= ' `item_target` = ?';
719
-				}
720
-			}
721
-			$queryArgs[] = $item;
722
-			if ($includeCollections && $collectionTypes && !in_array('folder', $collectionTypes)) {
723
-				$placeholders = implode(',', array_fill(0, count($collectionTypes), '?'));
724
-				$where .= ' OR `item_type` IN ('.$placeholders.'))';
725
-				$queryArgs = array_merge($queryArgs, $collectionTypes);
726
-			}
727
-		}
728
-
729
-		if ($shareType == self::$shareTypeUserAndGroups && $limit === 1) {
730
-			// Make sure the unique user target is returned if it exists,
731
-			// unique targets should follow the group share in the database
732
-			// If the limit is not 1, the filtering can be done later
733
-			$where .= ' ORDER BY `*PREFIX*share`.`id` DESC';
734
-		} else {
735
-			$where .= ' ORDER BY `*PREFIX*share`.`id` ASC';
736
-		}
737
-
738
-		if ($limit != -1 && !$includeCollections) {
739
-			// The limit must be at least 3, because filtering needs to be done
740
-			if ($limit < 3) {
741
-				$queryLimit = 3;
742
-			} else {
743
-				$queryLimit = $limit;
744
-			}
745
-		} else {
746
-			$queryLimit = null;
747
-		}
748
-		$select = self::createSelectStatement($format, $fileDependent, $uidOwner);
749
-		$root = strlen($root);
750
-		$query = \OC_DB::prepare('SELECT '.$select.' FROM `*PREFIX*share` '.$where, $queryLimit);
751
-		$result = $query->execute($queryArgs);
752
-		if ($result === false) {
753
-			\OCP\Util::writeLog('OCP\Share',
754
-				\OC_DB::getErrorMessage() . ', select=' . $select . ' where=',
755
-				ILogger::ERROR);
756
-		}
757
-		$items = [];
758
-		$targets = [];
759
-		$switchedItems = [];
760
-		$mounts = [];
761
-		while ($row = $result->fetchRow()) {
762
-			self::transformDBResults($row);
763
-			// Filter out duplicate group shares for users with unique targets
764
-			if ($fileDependent && !self::isFileReachable($row['path'], $row['storage_id'])) {
765
-				continue;
766
-			}
767
-			if ($row['share_type'] == self::$shareTypeGroupUserUnique && isset($items[$row['parent']])) {
768
-				$row['share_type'] = self::SHARE_TYPE_GROUP;
769
-				$row['unique_name'] = true; // remember that we use a unique name for this user
770
-				$row['share_with'] = $items[$row['parent']]['share_with'];
771
-				// if the group share was unshared from the user we keep the permission, otherwise
772
-				// we take the permission from the parent because this is always the up-to-date
773
-				// permission for the group share
774
-				if ($row['permissions'] > 0) {
775
-					$row['permissions'] = $items[$row['parent']]['permissions'];
776
-				}
777
-				// Remove the parent group share
778
-				unset($items[$row['parent']]);
779
-				if ($row['permissions'] == 0) {
780
-					continue;
781
-				}
782
-			} else if (!isset($uidOwner)) {
783
-				// Check if the same target already exists
784
-				if (isset($targets[$row['id']])) {
785
-					// Check if the same owner shared with the user twice
786
-					// through a group and user share - this is allowed
787
-					$id = $targets[$row['id']];
788
-					if (isset($items[$id]) && $items[$id]['uid_owner'] == $row['uid_owner']) {
789
-						// Switch to group share type to ensure resharing conditions aren't bypassed
790
-						if ($items[$id]['share_type'] != self::SHARE_TYPE_GROUP) {
791
-							$items[$id]['share_type'] = self::SHARE_TYPE_GROUP;
792
-							$items[$id]['share_with'] = $row['share_with'];
793
-						}
794
-						// Switch ids if sharing permission is granted on only
795
-						// one share to ensure correct parent is used if resharing
796
-						if (~(int)$items[$id]['permissions'] & \OCP\Constants::PERMISSION_SHARE
797
-							&& (int)$row['permissions'] & \OCP\Constants::PERMISSION_SHARE) {
798
-							$items[$row['id']] = $items[$id];
799
-							$switchedItems[$id] = $row['id'];
800
-							unset($items[$id]);
801
-							$id = $row['id'];
802
-						}
803
-						$items[$id]['permissions'] |= (int)$row['permissions'];
804
-
805
-					}
806
-					continue;
807
-				} elseif (!empty($row['parent'])) {
808
-					$targets[$row['parent']] = $row['id'];
809
-				}
810
-			}
811
-			// Remove root from file source paths if retrieving own shared items
812
-			if (isset($uidOwner) && isset($row['path'])) {
813
-				if (isset($row['parent'])) {
814
-					$query = \OC_DB::prepare('SELECT `file_target` FROM `*PREFIX*share` WHERE `id` = ?');
815
-					$parentResult = $query->execute([$row['parent']]);
816
-					if ($result === false) {
817
-						\OCP\Util::writeLog('OCP\Share', 'Can\'t select parent: ' .
818
-							\OC_DB::getErrorMessage() . ', select=' . $select . ' where=' . $where,
819
-							ILogger::ERROR);
820
-					} else {
821
-						$parentRow = $parentResult->fetchRow();
822
-						$tmpPath = $parentRow['file_target'];
823
-						// find the right position where the row path continues from the target path
824
-						$pos = strrpos($row['path'], $parentRow['file_target']);
825
-						$subPath = substr($row['path'], $pos);
826
-						$splitPath = explode('/', $subPath);
827
-						foreach (array_slice($splitPath, 2) as $pathPart) {
828
-							$tmpPath = $tmpPath . '/' . $pathPart;
829
-						}
830
-						$row['path'] = $tmpPath;
831
-					}
832
-				} else {
833
-					if (!isset($mounts[$row['storage']])) {
834
-						$mountPoints = \OC\Files\Filesystem::getMountByNumericId($row['storage']);
835
-						if (is_array($mountPoints) && !empty($mountPoints)) {
836
-							$mounts[$row['storage']] = current($mountPoints);
837
-						}
838
-					}
839
-					if (!empty($mounts[$row['storage']])) {
840
-						$path = $mounts[$row['storage']]->getMountPoint().$row['path'];
841
-						$relPath = substr($path, $root); // path relative to data/user
842
-						$row['path'] = rtrim($relPath, '/');
843
-					}
844
-				}
845
-			}
846
-
847
-			if($checkExpireDate) {
848
-				if (self::expireItem($row)) {
849
-					continue;
850
-				}
851
-			}
852
-			// Check if resharing is allowed, if not remove share permission
853
-			if (isset($row['permissions']) && (!self::isResharingAllowed() | \OCP\Util::isSharingDisabledForUser())) {
854
-				$row['permissions'] &= ~\OCP\Constants::PERMISSION_SHARE;
855
-			}
856
-			// Add display names to result
857
-			$row['share_with_displayname'] = $row['share_with'];
858
-			if ( isset($row['share_with']) && $row['share_with'] != '' &&
859
-				$row['share_type'] === self::SHARE_TYPE_USER) {
860
-				$shareWithUser = \OC::$server->getUserManager()->get($row['share_with']);
861
-				$row['share_with_displayname'] = $shareWithUser === null ? $row['share_with'] : $shareWithUser->getDisplayName();
862
-			} else if(isset($row['share_with']) && $row['share_with'] != '' &&
863
-				$row['share_type'] === self::SHARE_TYPE_REMOTE) {
864
-				$addressBookEntries = \OC::$server->getContactsManager()->search($row['share_with'], ['CLOUD']);
865
-				foreach ($addressBookEntries as $entry) {
866
-					foreach ($entry['CLOUD'] as $cloudID) {
867
-						if ($cloudID === $row['share_with']) {
868
-							$row['share_with_displayname'] = $entry['FN'];
869
-						}
870
-					}
871
-				}
872
-			}
873
-			if ( isset($row['uid_owner']) && $row['uid_owner'] != '') {
874
-				$ownerUser = \OC::$server->getUserManager()->get($row['uid_owner']);
875
-				$row['displayname_owner'] = $ownerUser === null ? $row['uid_owner'] : $ownerUser->getDisplayName();
876
-			}
877
-
878
-			if ($row['permissions'] > 0) {
879
-				$items[$row['id']] = $row;
880
-			}
881
-
882
-		}
883
-
884
-		// group items if we are looking for items shared with the current user
885
-		if (isset($shareWith) && $shareWith === \OCP\User::getUser()) {
886
-			$items = self::groupItems($items, $itemType);
887
-		}
888
-
889
-		if (!empty($items)) {
890
-			$collectionItems = [];
891
-			foreach ($items as &$row) {
892
-				// Return only the item instead of a 2-dimensional array
893
-				if ($limit == 1 && $row[$column] == $item && ($row['item_type'] == $itemType || $itemType == 'file')) {
894
-					if ($format == self::FORMAT_NONE) {
895
-						return $row;
896
-					} else {
897
-						break;
898
-					}
899
-				}
900
-				// Check if this is a collection of the requested item type
901
-				if ($includeCollections && $collectionTypes && $row['item_type'] !== 'folder' && in_array($row['item_type'], $collectionTypes)) {
902
-					if (($collectionBackend = self::getBackend($row['item_type']))
903
-						&& $collectionBackend instanceof \OCP\Share_Backend_Collection) {
904
-						// Collections can be inside collections, check if the item is a collection
905
-						if (isset($item) && $row['item_type'] == $itemType && $row[$column] == $item) {
906
-							$collectionItems[] = $row;
907
-						} else {
908
-							$collection = [];
909
-							$collection['item_type'] = $row['item_type'];
910
-							if ($row['item_type'] == 'file' || $row['item_type'] == 'folder') {
911
-								$collection['path'] = basename($row['path']);
912
-							}
913
-							$row['collection'] = $collection;
914
-							// Fetch all of the children sources
915
-							$children = $collectionBackend->getChildren($row[$column]);
916
-							foreach ($children as $child) {
917
-								$childItem = $row;
918
-								$childItem['item_type'] = $itemType;
919
-								if ($row['item_type'] != 'file' && $row['item_type'] != 'folder') {
920
-									$childItem['item_source'] = $child['source'];
921
-									$childItem['item_target'] = $child['target'];
922
-								}
923
-								if ($backend instanceof \OCP\Share_Backend_File_Dependent) {
924
-									if ($row['item_type'] == 'file' || $row['item_type'] == 'folder') {
925
-										$childItem['file_source'] = $child['source'];
926
-									} else { // TODO is this really needed if we already know that we use the file backend?
927
-										$meta = \OC\Files\Filesystem::getFileInfo($child['file_path']);
928
-										$childItem['file_source'] = $meta['fileid'];
929
-									}
930
-									$childItem['file_target'] =
931
-										\OC\Files\Filesystem::normalizePath($child['file_path']);
932
-								}
933
-								if (isset($item)) {
934
-									if ($childItem[$column] == $item) {
935
-										// Return only the item instead of a 2-dimensional array
936
-										if ($limit == 1) {
937
-											if ($format == self::FORMAT_NONE) {
938
-												return $childItem;
939
-											} else {
940
-												// Unset the items array and break out of both loops
941
-												$items = [];
942
-												$items[] = $childItem;
943
-												break 2;
944
-											}
945
-										} else {
946
-											$collectionItems[] = $childItem;
947
-										}
948
-									}
949
-								} else {
950
-									$collectionItems[] = $childItem;
951
-								}
952
-							}
953
-						}
954
-					}
955
-					// Remove collection item
956
-					$toRemove = $row['id'];
957
-					if (array_key_exists($toRemove, $switchedItems)) {
958
-						$toRemove = $switchedItems[$toRemove];
959
-					}
960
-					unset($items[$toRemove]);
961
-				} elseif ($includeCollections && $collectionTypes && in_array($row['item_type'], $collectionTypes)) {
962
-					// FIXME: Thats a dirty hack to improve file sharing performance,
963
-					// see github issue #10588 for more details
964
-					// Need to find a solution which works for all back-ends
965
-					$collectionBackend = self::getBackend($row['item_type']);
966
-					$sharedParents = $collectionBackend->getParents($row['item_source']);
967
-					foreach ($sharedParents as $parent) {
968
-						$collectionItems[] = $parent;
969
-					}
970
-				}
971
-			}
972
-			if (!empty($collectionItems)) {
973
-				$collectionItems = array_unique($collectionItems, SORT_REGULAR);
974
-				$items = array_merge($items, $collectionItems);
975
-			}
976
-
977
-			// filter out invalid items, these can appear when subshare entries exist
978
-			// for a group in which the requested user isn't a member any more
979
-			$items = array_filter($items, function($item) {
980
-				return $item['share_type'] !== self::$shareTypeGroupUserUnique;
981
-			});
982
-
983
-			return self::formatResult($items, $column, $backend, $format, $parameters);
984
-		} elseif ($includeCollections && $collectionTypes && in_array('folder', $collectionTypes)) {
985
-			// FIXME: Thats a dirty hack to improve file sharing performance,
986
-			// see github issue #10588 for more details
987
-			// Need to find a solution which works for all back-ends
988
-			$collectionItems = [];
989
-			$collectionBackend = self::getBackend('folder');
990
-			$sharedParents = $collectionBackend->getParents($item, $shareWith, $uidOwner);
991
-			foreach ($sharedParents as $parent) {
992
-				$collectionItems[] = $parent;
993
-			}
994
-			if ($limit === 1) {
995
-				return reset($collectionItems);
996
-			}
997
-			return self::formatResult($collectionItems, $column, $backend, $format, $parameters);
998
-		}
999
-
1000
-		return [];
1001
-	}
1002
-
1003
-	/**
1004
-	 * group items with link to the same source
1005
-	 *
1006
-	 * @param array $items
1007
-	 * @param string $itemType
1008
-	 * @return array of grouped items
1009
-	 */
1010
-	protected static function groupItems($items, $itemType) {
1011
-
1012
-		$fileSharing = $itemType === 'file' || $itemType === 'folder';
1013
-
1014
-		$result = [];
1015
-
1016
-		foreach ($items as $item) {
1017
-			$grouped = false;
1018
-			foreach ($result as $key => $r) {
1019
-				// for file/folder shares we need to compare file_source, otherwise we compare item_source
1020
-				// only group shares if they already point to the same target, otherwise the file where shared
1021
-				// before grouping of shares was added. In this case we don't group them toi avoid confusions
1022
-				if (( $fileSharing && $item['file_source'] === $r['file_source'] && $item['file_target'] === $r['file_target']) ||
1023
-					(!$fileSharing && $item['item_source'] === $r['item_source'] && $item['item_target'] === $r['item_target'])) {
1024
-					// add the first item to the list of grouped shares
1025
-					if (!isset($result[$key]['grouped'])) {
1026
-						$result[$key]['grouped'][] = $result[$key];
1027
-					}
1028
-					$result[$key]['permissions'] = (int) $item['permissions'] | (int) $r['permissions'];
1029
-					$result[$key]['grouped'][] = $item;
1030
-					$grouped = true;
1031
-					break;
1032
-				}
1033
-			}
1034
-
1035
-			if (!$grouped) {
1036
-				$result[] = $item;
1037
-			}
1038
-
1039
-		}
1040
-
1041
-		return $result;
1042
-	}
1043
-
1044
-	/**
1045
-	 * Put shared item into the database
1046
-	 * @param string $itemType Item type
1047
-	 * @param string $itemSource Item source
1048
-	 * @param int $shareType SHARE_TYPE_USER, SHARE_TYPE_GROUP, or SHARE_TYPE_LINK
1049
-	 * @param string $shareWith User or group the item is being shared with
1050
-	 * @param string $uidOwner User that is the owner of shared item
1051
-	 * @param int $permissions CRUDS permissions
1052
-	 * @throws \Exception
1053
-	 * @return mixed id of the new share or false
1054
-	 * @deprecated TESTS ONLY - this methods is only used by tests
1055
-	 * called like this:
1056
-	 * self::put('test', $itemSource, self::SHARE_TYPE_USER, $shareWith, $uidOwner, $permissions);
1057
-	 */
1058
-	private static function put($itemType, $itemSource, $shareType, $shareWith, $uidOwner,
1059
-								$permissions) {
1060
-
1061
-		$queriesToExecute = [];
1062
-		$suggestedItemTarget = null;
1063
-		$groupFileTarget = $fileTarget = $suggestedFileTarget = $filePath = '';
1064
-		$groupItemTarget = $itemTarget = $fileSource = $parent = 0;
1065
-
1066
-		$result = self::checkReshare('test', $itemSource, self::SHARE_TYPE_USER, $shareWith, $uidOwner, $permissions, null, null);
1067
-		if(!empty($result)) {
1068
-			$parent = $result['parent'];
1069
-			$itemSource = $result['itemSource'];
1070
-			$fileSource = $result['fileSource'];
1071
-			$suggestedItemTarget = $result['suggestedItemTarget'];
1072
-			$suggestedFileTarget = $result['suggestedFileTarget'];
1073
-			$filePath = $result['filePath'];
1074
-		}
1075
-
1076
-		$isGroupShare = false;
1077
-			$users = [$shareWith];
1078
-			$itemTarget = Helper::generateTarget($itemType, $itemSource, $shareType, $shareWith, $uidOwner,
1079
-				$suggestedItemTarget);
1080
-
1081
-		$run = true;
1082
-		$error = '';
1083
-		$preHookData = [
1084
-			'itemType' => $itemType,
1085
-			'itemSource' => $itemSource,
1086
-			'shareType' => $shareType,
1087
-			'uidOwner' => $uidOwner,
1088
-			'permissions' => $permissions,
1089
-			'fileSource' => $fileSource,
1090
-			'expiration' => null,
1091
-			'token' => null,
1092
-			'run' => &$run,
1093
-			'error' => &$error
1094
-		];
1095
-
1096
-		$preHookData['itemTarget'] = $itemTarget;
1097
-		$preHookData['shareWith'] = $shareWith;
1098
-
1099
-		\OC_Hook::emit(\OCP\Share::class, 'pre_shared', $preHookData);
1100
-
1101
-		if ($run === false) {
1102
-			throw new \Exception($error);
1103
-		}
1104
-
1105
-		foreach ($users as $user) {
1106
-			$sourceId = ($itemType === 'file' || $itemType === 'folder') ? $fileSource : $itemSource;
1107
-			$sourceExists = self::getItemSharedWithBySource($itemType, $sourceId, self::FORMAT_NONE, null, true, $user);
1108
-
1109
-			$userShareType = $shareType;
1110
-
1111
-			if ($sourceExists && $sourceExists['item_source'] === $itemSource) {
1112
-				$fileTarget = $sourceExists['file_target'];
1113
-				$itemTarget = $sourceExists['item_target'];
1114
-
1115
-			} elseif(!$sourceExists)  {
1116
-
1117
-				$itemTarget = Helper::generateTarget($itemType, $itemSource, $userShareType, $user,
1118
-					$uidOwner, $suggestedItemTarget, $parent);
1119
-				if (isset($fileSource)) {
1120
-						$fileTarget = Helper::generateTarget('file', $filePath, $userShareType,
1121
-							$user, $uidOwner, $suggestedFileTarget, $parent);
1122
-				} else {
1123
-					$fileTarget = null;
1124
-				}
1125
-
1126
-			} else {
1127
-
1128
-				// group share which doesn't exists until now, check if we need a unique target for this user
1129
-
1130
-				$itemTarget = Helper::generateTarget($itemType, $itemSource, self::SHARE_TYPE_USER, $user,
1131
-					$uidOwner, $suggestedItemTarget, $parent);
1132
-
1133
-				// do we also need a file target
1134
-				if (isset($fileSource)) {
1135
-					$fileTarget = Helper::generateTarget('file', $filePath, self::SHARE_TYPE_USER, $user,
1136
-						$uidOwner, $suggestedFileTarget, $parent);
1137
-				} else {
1138
-					$fileTarget = null;
1139
-				}
1140
-
1141
-				if (($itemTarget === $groupItemTarget) &&
1142
-					(!isset($fileSource) || $fileTarget === $groupFileTarget)) {
1143
-					continue;
1144
-				}
1145
-			}
1146
-
1147
-			$queriesToExecute[] = [
1148
-				'itemType'			=> $itemType,
1149
-				'itemSource'		=> $itemSource,
1150
-				'itemTarget'		=> $itemTarget,
1151
-				'shareType'			=> $userShareType,
1152
-				'shareWith'			=> $user,
1153
-				'uidOwner'			=> $uidOwner,
1154
-				'permissions'		=> $permissions,
1155
-				'shareTime'			=> time(),
1156
-				'fileSource'		=> $fileSource,
1157
-				'fileTarget'		=> $fileTarget,
1158
-				'token'				=> null,
1159
-				'parent'			=> $parent,
1160
-				'expiration'		=> null,
1161
-			];
1162
-
1163
-		}
1164
-
1165
-		$id = false;
1166
-
1167
-		foreach ($queriesToExecute as $shareQuery) {
1168
-			$shareQuery['parent'] = $parent;
1169
-			$id = self::insertShare($shareQuery);
1170
-		}
1171
-
1172
-		$postHookData = [
1173
-			'itemType' => $itemType,
1174
-			'itemSource' => $itemSource,
1175
-			'parent' => $parent,
1176
-			'shareType' => $shareType,
1177
-			'uidOwner' => $uidOwner,
1178
-			'permissions' => $permissions,
1179
-			'fileSource' => $fileSource,
1180
-			'id' => $parent,
1181
-			'token' => null,
1182
-			'expirationDate' => null,
1183
-		];
1184
-
1185
-		$postHookData['shareWith'] = $isGroupShare ? $shareWith['group'] : $shareWith;
1186
-		$postHookData['itemTarget'] = $isGroupShare ? $groupItemTarget : $itemTarget;
1187
-		$postHookData['fileTarget'] = $isGroupShare ? $groupFileTarget : $fileTarget;
1188
-
1189
-		\OC_Hook::emit(\OCP\Share::class, 'post_shared', $postHookData);
1190
-
1191
-
1192
-		return $id ? $id : false;
1193
-	}
1194
-
1195
-	/**
1196
-	 * @param string $itemType
1197
-	 * @param string $itemSource
1198
-	 * @param int $shareType
1199
-	 * @param string $shareWith
1200
-	 * @param string $uidOwner
1201
-	 * @param int $permissions
1202
-	 * @param string|null $itemSourceName
1203
-	 * @param null|\DateTime $expirationDate
1204
-	 * @deprecated TESTS ONLY - this methods is only used by tests
1205
-	 * called like this:
1206
-	 * self::checkReshare('test', $itemSource, self::SHARE_TYPE_USER, $shareWith, $uidOwner, $permissions, null, null);
1207
-	 */
1208
-	private static function checkReshare($itemType, $itemSource, $shareType, $shareWith, $uidOwner, $permissions, $itemSourceName, $expirationDate) {
1209
-		$backend = self::getBackend($itemType);
1210
-
1211
-		$result = [];
1212
-
1213
-		$column = ($itemType === 'file' || $itemType === 'folder') ? 'file_source' : 'item_source';
1214
-
1215
-		$checkReshare = self::getItemSharedWithBySource($itemType, $itemSource, self::FORMAT_NONE, null, true);
1216
-		if ($checkReshare) {
1217
-			// Check if attempting to share back to owner
1218
-			if ($checkReshare['uid_owner'] == $shareWith) {
1219
-				$message = 'Sharing %1$s failed, because the user %2$s is the original sharer';
1220
-				throw new \Exception(sprintf($message, $itemSourceName, $shareWith));
1221
-			}
1222
-		}
1223
-
1224
-		if ($checkReshare && $checkReshare['uid_owner'] !== \OC_User::getUser()) {
1225
-			// Check if share permissions is granted
1226
-			if (self::isResharingAllowed() && (int)$checkReshare['permissions'] & \OCP\Constants::PERMISSION_SHARE) {
1227
-				if (~(int)$checkReshare['permissions'] & $permissions) {
1228
-					$message = 'Sharing %1$s failed, because the permissions exceed permissions granted to %2$s';
1229
-					throw new \Exception(sprintf($message, $itemSourceName, $uidOwner));
1230
-				} else {
1231
-					// TODO Don't check if inside folder
1232
-					$result['parent'] = $checkReshare['id'];
1233
-
1234
-					$result['expirationDate'] = $expirationDate;
1235
-					// $checkReshare['expiration'] could be null and then is always less than any value
1236
-					if(isset($checkReshare['expiration']) && $checkReshare['expiration'] < $expirationDate) {
1237
-						$result['expirationDate'] = $checkReshare['expiration'];
1238
-					}
1239
-
1240
-					// only suggest the same name as new target if it is a reshare of the
1241
-					// same file/folder and not the reshare of a child
1242
-					if ($checkReshare[$column] === $itemSource) {
1243
-						$result['filePath'] = $checkReshare['file_target'];
1244
-						$result['itemSource'] = $checkReshare['item_source'];
1245
-						$result['fileSource'] = $checkReshare['file_source'];
1246
-						$result['suggestedItemTarget'] = $checkReshare['item_target'];
1247
-						$result['suggestedFileTarget'] = $checkReshare['file_target'];
1248
-					} else {
1249
-						$result['filePath'] = ($backend instanceof \OCP\Share_Backend_File_Dependent) ? $backend->getFilePath($itemSource, $uidOwner) : null;
1250
-						$result['suggestedItemTarget'] = null;
1251
-						$result['suggestedFileTarget'] = null;
1252
-						$result['itemSource'] = $itemSource;
1253
-						$result['fileSource'] = ($backend instanceof \OCP\Share_Backend_File_Dependent) ? $itemSource : null;
1254
-					}
1255
-				}
1256
-			} else {
1257
-				$message = 'Sharing %s failed, because resharing is not allowed';
1258
-				throw new \Exception(sprintf($message, $itemSourceName));
1259
-			}
1260
-		} else {
1261
-			$result['parent'] = null;
1262
-			$result['suggestedItemTarget'] = null;
1263
-			$result['suggestedFileTarget'] = null;
1264
-			$result['itemSource'] = $itemSource;
1265
-			$result['expirationDate'] = $expirationDate;
1266
-			if (!$backend->isValidSource($itemSource, $uidOwner)) {
1267
-				$message = 'Sharing %1$s failed, because the sharing backend for '
1268
-					.'%2$s could not find its source';
1269
-				throw new \Exception(sprintf($message, $itemSource, $itemType));
1270
-			}
1271
-			if ($backend instanceof \OCP\Share_Backend_File_Dependent) {
1272
-				$result['filePath'] = $backend->getFilePath($itemSource, $uidOwner);
1273
-					$meta = \OC\Files\Filesystem::getFileInfo($result['filePath']);
1274
-					$result['fileSource'] = $meta['fileid'];
1275
-				if ($result['fileSource'] == -1) {
1276
-					$message = 'Sharing %s failed, because the file could not be found in the file cache';
1277
-					throw new \Exception(sprintf($message, $itemSource));
1278
-				}
1279
-			} else {
1280
-				$result['filePath'] = null;
1281
-				$result['fileSource'] = null;
1282
-			}
1283
-		}
1284
-
1285
-		return $result;
1286
-	}
1287
-
1288
-	/**
1289
-	 *
1290
-	 * @param array $shareData
1291
-	 * @return mixed false in case of a failure or the id of the new share
1292
-	 */
1293
-	private static function insertShare(array $shareData) {
1294
-
1295
-		$query = \OC_DB::prepare('INSERT INTO `*PREFIX*share` ('
1296
-			.' `item_type`, `item_source`, `item_target`, `share_type`,'
1297
-			.' `share_with`, `uid_owner`, `permissions`, `stime`, `file_source`,'
1298
-			.' `file_target`, `token`, `parent`, `expiration`) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)');
1299
-		$query->bindValue(1, $shareData['itemType']);
1300
-		$query->bindValue(2, $shareData['itemSource']);
1301
-		$query->bindValue(3, $shareData['itemTarget']);
1302
-		$query->bindValue(4, $shareData['shareType']);
1303
-		$query->bindValue(5, $shareData['shareWith']);
1304
-		$query->bindValue(6, $shareData['uidOwner']);
1305
-		$query->bindValue(7, $shareData['permissions']);
1306
-		$query->bindValue(8, $shareData['shareTime']);
1307
-		$query->bindValue(9, $shareData['fileSource']);
1308
-		$query->bindValue(10, $shareData['fileTarget']);
1309
-		$query->bindValue(11, $shareData['token']);
1310
-		$query->bindValue(12, $shareData['parent']);
1311
-		$query->bindValue(13, $shareData['expiration'], 'datetime');
1312
-		$result = $query->execute();
1313
-
1314
-		$id = false;
1315
-		if ($result) {
1316
-			$id =  \OC::$server->getDatabaseConnection()->lastInsertId('*PREFIX*share');
1317
-		}
1318
-
1319
-		return $id;
1320
-
1321
-	}
1322
-
1323
-	/**
1324
-	 * construct select statement
1325
-	 * @param int $format
1326
-	 * @param boolean $fileDependent ist it a file/folder share or a generla share
1327
-	 * @param string $uidOwner
1328
-	 * @return string select statement
1329
-	 */
1330
-	private static function createSelectStatement($format, $fileDependent, $uidOwner = null) {
1331
-		$select = '*';
1332
-		if ($format == self::FORMAT_STATUSES) {
1333
-			if ($fileDependent) {
1334
-				$select = '`*PREFIX*share`.`id`, `*PREFIX*share`.`parent`, `share_type`, `path`, `storage`, '
1335
-					. '`share_with`, `uid_owner` , `file_source`, `stime`, `*PREFIX*share`.`permissions`, '
1336
-					. '`*PREFIX*storages`.`id` AS `storage_id`, `*PREFIX*filecache`.`parent` as `file_parent`, '
1337
-					. '`uid_initiator`';
1338
-			} else {
1339
-				$select = '`id`, `parent`, `share_type`, `share_with`, `uid_owner`, `item_source`, `stime`, `*PREFIX*share`.`permissions`';
1340
-			}
1341
-		} else {
1342
-			if (isset($uidOwner)) {
1343
-				if ($fileDependent) {
1344
-					$select = '`*PREFIX*share`.`id`, `item_type`, `item_source`, `*PREFIX*share`.`parent`,'
1345
-						. ' `share_type`, `share_with`, `file_source`, `file_target`, `path`, `*PREFIX*share`.`permissions`, `stime`,'
1346
-						. ' `expiration`, `token`, `storage`, `mail_send`, `uid_owner`, '
1347
-						. '`*PREFIX*storages`.`id` AS `storage_id`, `*PREFIX*filecache`.`parent` as `file_parent`';
1348
-				} else {
1349
-					$select = '`id`, `item_type`, `item_source`, `parent`, `share_type`, `share_with`, `*PREFIX*share`.`permissions`,'
1350
-						. ' `stime`, `file_source`, `expiration`, `token`, `mail_send`, `uid_owner`';
1351
-				}
1352
-			} else {
1353
-				if ($fileDependent) {
1354
-					if ($format == \OCA\Files_Sharing\ShareBackend\File::FORMAT_GET_FOLDER_CONTENTS || $format == \OCA\Files_Sharing\ShareBackend\File::FORMAT_FILE_APP_ROOT) {
1355
-						$select = '`*PREFIX*share`.`id`, `item_type`, `item_source`, `*PREFIX*share`.`parent`, `uid_owner`, '
1356
-							. '`share_type`, `share_with`, `file_source`, `path`, `file_target`, `stime`, '
1357
-							. '`*PREFIX*share`.`permissions`, `expiration`, `storage`, `*PREFIX*filecache`.`parent` as `file_parent`, '
1358
-							. '`name`, `mtime`, `mimetype`, `mimepart`, `size`, `encrypted`, `etag`, `mail_send`';
1359
-					} else {
1360
-						$select = '`*PREFIX*share`.`id`, `item_type`, `item_source`, `item_target`,'
1361
-							. '`*PREFIX*share`.`parent`, `share_type`, `share_with`, `uid_owner`,'
1362
-							. '`file_source`, `path`, `file_target`, `*PREFIX*share`.`permissions`,'
1363
-						    . '`stime`, `expiration`, `token`, `storage`, `mail_send`,'
1364
-							. '`*PREFIX*storages`.`id` AS `storage_id`, `*PREFIX*filecache`.`parent` as `file_parent`';
1365
-					}
1366
-				}
1367
-			}
1368
-		}
1369
-		return $select;
1370
-	}
1371
-
1372
-
1373
-	/**
1374
-	 * transform db results
1375
-	 * @param array $row result
1376
-	 */
1377
-	private static function transformDBResults(&$row) {
1378
-		if (isset($row['id'])) {
1379
-			$row['id'] = (int) $row['id'];
1380
-		}
1381
-		if (isset($row['share_type'])) {
1382
-			$row['share_type'] = (int) $row['share_type'];
1383
-		}
1384
-		if (isset($row['parent'])) {
1385
-			$row['parent'] = (int) $row['parent'];
1386
-		}
1387
-		if (isset($row['file_parent'])) {
1388
-			$row['file_parent'] = (int) $row['file_parent'];
1389
-		}
1390
-		if (isset($row['file_source'])) {
1391
-			$row['file_source'] = (int) $row['file_source'];
1392
-		}
1393
-		if (isset($row['permissions'])) {
1394
-			$row['permissions'] = (int) $row['permissions'];
1395
-		}
1396
-		if (isset($row['storage'])) {
1397
-			$row['storage'] = (int) $row['storage'];
1398
-		}
1399
-		if (isset($row['stime'])) {
1400
-			$row['stime'] = (int) $row['stime'];
1401
-		}
1402
-		if (isset($row['expiration']) && $row['share_type'] !== self::SHARE_TYPE_LINK) {
1403
-			// discard expiration date for non-link shares, which might have been
1404
-			// set by ancient bugs
1405
-			$row['expiration'] = null;
1406
-		}
1407
-	}
1408
-
1409
-	/**
1410
-	 * format result
1411
-	 * @param array $items result
1412
-	 * @param string $column is it a file share or a general share ('file_target' or 'item_target')
1413
-	 * @param \OCP\Share_Backend $backend sharing backend
1414
-	 * @param int $format
1415
-	 * @param array $parameters additional format parameters
1416
-	 * @return array format result
1417
-	 */
1418
-	private static function formatResult($items, $column, $backend, $format = self::FORMAT_NONE , $parameters = null) {
1419
-		if ($format === self::FORMAT_NONE) {
1420
-			return $items;
1421
-		} else if ($format === self::FORMAT_STATUSES) {
1422
-			$statuses = [];
1423
-			foreach ($items as $item) {
1424
-				if ($item['share_type'] === self::SHARE_TYPE_LINK) {
1425
-					if ($item['uid_initiator'] !== \OC::$server->getUserSession()->getUser()->getUID()) {
1426
-						continue;
1427
-					}
1428
-					$statuses[$item[$column]]['link'] = true;
1429
-				} else if (!isset($statuses[$item[$column]])) {
1430
-					$statuses[$item[$column]]['link'] = false;
1431
-				}
1432
-				if (!empty($item['file_target'])) {
1433
-					$statuses[$item[$column]]['path'] = $item['path'];
1434
-				}
1435
-			}
1436
-			return $statuses;
1437
-		} else {
1438
-			return $backend->formatItems($items, $format, $parameters);
1439
-		}
1440
-	}
1441
-
1442
-	/**
1443
-	 * remove protocol from URL
1444
-	 *
1445
-	 * @param string $url
1446
-	 * @return string
1447
-	 */
1448
-	public static function removeProtocolFromUrl($url) {
1449
-		if (strpos($url, 'https://') === 0) {
1450
-			return substr($url, strlen('https://'));
1451
-		} else if (strpos($url, 'http://') === 0) {
1452
-			return substr($url, strlen('http://'));
1453
-		}
1454
-
1455
-		return $url;
1456
-	}
1457
-
1458
-	/**
1459
-	 * try http post first with https and then with http as a fallback
1460
-	 *
1461
-	 * @param string $remoteDomain
1462
-	 * @param string $urlSuffix
1463
-	 * @param array $fields post parameters
1464
-	 * @return array
1465
-	 */
1466
-	private static function tryHttpPostToShareEndpoint($remoteDomain, $urlSuffix, array $fields) {
1467
-		$protocol = 'https://';
1468
-		$result = [
1469
-			'success' => false,
1470
-			'result' => '',
1471
-		];
1472
-		$try = 0;
1473
-		$discoveryService = \OC::$server->query(\OCP\OCS\IDiscoveryService::class);
1474
-		while ($result['success'] === false && $try < 2) {
1475
-			$federationEndpoints = $discoveryService->discover($protocol . $remoteDomain, 'FEDERATED_SHARING');
1476
-			$endpoint = isset($federationEndpoints['share']) ? $federationEndpoints['share'] : '/ocs/v2.php/cloud/shares';
1477
-			$client = \OC::$server->getHTTPClientService()->newClient();
1478
-
1479
-			try {
1480
-				$response = $client->post(
1481
-					$protocol . $remoteDomain . $endpoint . $urlSuffix . '?format=' . self::RESPONSE_FORMAT,
1482
-					[
1483
-						'body' => $fields,
1484
-						'connect_timeout' => 10,
1485
-					]
1486
-				);
1487
-
1488
-				$result = ['success' => true, 'result' => $response->getBody()];
1489
-			} catch (\Exception $e) {
1490
-				$result = ['success' => false, 'result' => $e->getMessage()];
1491
-			}
1492
-
1493
-			$try++;
1494
-			$protocol = 'http://';
1495
-		}
1496
-
1497
-		return $result;
1498
-	}
1499
-
1500
-	/**
1501
-	 * send server-to-server unshare to remote server
1502
-	 *
1503
-	 * @param string $remote url
1504
-	 * @param int $id share id
1505
-	 * @param string $token
1506
-	 * @return bool
1507
-	 */
1508
-	private static function sendRemoteUnshare($remote, $id, $token) {
1509
-		$url = rtrim($remote, '/');
1510
-		$fields = ['token' => $token, 'format' => 'json'];
1511
-		$url = self::removeProtocolFromUrl($url);
1512
-		$result = self::tryHttpPostToShareEndpoint($url, '/'.$id.'/unshare', $fields);
1513
-		$status = json_decode($result['result'], true);
1514
-
1515
-		return ($result['success'] && ($status['ocs']['meta']['statuscode'] === 100 || $status['ocs']['meta']['statuscode'] === 200));
1516
-	}
1517
-
1518
-	/**
1519
-	 * @return int
1520
-	 */
1521
-	public static function getExpireInterval() {
1522
-		return (int)\OC::$server->getConfig()->getAppValue('core', 'shareapi_expire_after_n_days', '7');
1523
-	}
1524
-
1525
-	/**
1526
-	 * Checks whether the given path is reachable for the given owner
1527
-	 *
1528
-	 * @param string $path path relative to files
1529
-	 * @param string $ownerStorageId storage id of the owner
1530
-	 *
1531
-	 * @return boolean true if file is reachable, false otherwise
1532
-	 */
1533
-	private static function isFileReachable($path, $ownerStorageId) {
1534
-		// if outside the home storage, file is always considered reachable
1535
-		if (!(substr($ownerStorageId, 0, 6) === 'home::' ||
1536
-			substr($ownerStorageId, 0, 13) === 'object::user:'
1537
-		)) {
1538
-			return true;
1539
-		}
1540
-
1541
-		// if inside the home storage, the file has to be under "/files/"
1542
-		$path = ltrim($path, '/');
1543
-		if (substr($path, 0, 6) === 'files/') {
1544
-			return true;
1545
-		}
1546
-
1547
-		return false;
1548
-	}
53
+    /** CRUDS permissions (Create, Read, Update, Delete, Share) using a bitmask
54
+     * Construct permissions for share() and setPermissions with Or (|) e.g.
55
+     * Give user read and update permissions: PERMISSION_READ | PERMISSION_UPDATE
56
+     *
57
+     * Check if permission is granted with And (&) e.g. Check if delete is
58
+     * granted: if ($permissions & PERMISSION_DELETE)
59
+     *
60
+     * Remove permissions with And (&) and Not (~) e.g. Remove the update
61
+     * permission: $permissions &= ~PERMISSION_UPDATE
62
+     *
63
+     * Apps are required to handle permissions on their own, this class only
64
+     * stores and manages the permissions of shares
65
+     * @see lib/public/constants.php
66
+     */
67
+
68
+    /**
69
+     * Register a sharing backend class that implements OCP\Share_Backend for an item type
70
+     * @param string $itemType Item type
71
+     * @param string $class Backend class
72
+     * @param string $collectionOf (optional) Depends on item type
73
+     * @param array $supportedFileExtensions (optional) List of supported file extensions if this item type depends on files
74
+     * @return boolean true if backend is registered or false if error
75
+     */
76
+    public static function registerBackend($itemType, $class, $collectionOf = null, $supportedFileExtensions = null) {
77
+        if (\OC::$server->getConfig()->getAppValue('core', 'shareapi_enabled', 'yes') == 'yes') {
78
+            if (!isset(self::$backendTypes[$itemType])) {
79
+                self::$backendTypes[$itemType] = [
80
+                    'class' => $class,
81
+                    'collectionOf' => $collectionOf,
82
+                    'supportedFileExtensions' => $supportedFileExtensions
83
+                ];
84
+                return true;
85
+            }
86
+            \OCP\Util::writeLog('OCP\Share',
87
+                'Sharing backend '.$class.' not registered, '.self::$backendTypes[$itemType]['class']
88
+                .' is already registered for '.$itemType,
89
+                ILogger::WARN);
90
+        }
91
+        return false;
92
+    }
93
+
94
+    /**
95
+     * Get the items of item type shared with the current user
96
+     * @param string $itemType
97
+     * @param int $format (optional) Format type must be defined by the backend
98
+     * @param mixed $parameters (optional)
99
+     * @param int $limit Number of items to return (optional) Returns all by default
100
+     * @param boolean $includeCollections (optional)
101
+     * @return mixed Return depends on format
102
+     * @deprecated TESTS ONLY - this methods is only used by tests
103
+     * called like this:
104
+     * \OC\Share\Share::getItemsSharedWith('folder'); (apps/files_sharing/tests/UpdaterTest.php)
105
+     */
106
+    public static function getItemsSharedWith() {
107
+        return self::getItems('folder', null, self::$shareTypeUserAndGroups, \OC_User::getUser(), null, self::FORMAT_NONE,
108
+            null, -1, false);
109
+    }
110
+
111
+    /**
112
+     * Get the items of item type shared with a user
113
+     * @param string $itemType
114
+     * @param string $user id for which user we want the shares
115
+     * @param int $format (optional) Format type must be defined by the backend
116
+     * @param mixed $parameters (optional)
117
+     * @param int $limit Number of items to return (optional) Returns all by default
118
+     * @param boolean $includeCollections (optional)
119
+     * @return mixed Return depends on format
120
+     */
121
+    public static function getItemsSharedWithUser($itemType, $user, $format = self::FORMAT_NONE,
122
+                                                    $parameters = null, $limit = -1, $includeCollections = false) {
123
+        return self::getItems($itemType, null, self::$shareTypeUserAndGroups, $user, null, $format,
124
+            $parameters, $limit, $includeCollections);
125
+    }
126
+
127
+    /**
128
+     * Get the item of item type shared with a given user by source
129
+     * @param string $itemType
130
+     * @param string $itemSource
131
+     * @param string $user User to whom the item was shared
132
+     * @param string $owner Owner of the share
133
+     * @param int $shareType only look for a specific share type
134
+     * @return array Return list of items with file_target, permissions and expiration
135
+     */
136
+    public static function getItemSharedWithUser($itemType, $itemSource, $user, $owner = null, $shareType = null) {
137
+        $shares = [];
138
+        $fileDependent = false;
139
+
140
+        $where = 'WHERE';
141
+        $fileDependentWhere = '';
142
+        if ($itemType === 'file' || $itemType === 'folder') {
143
+            $fileDependent = true;
144
+            $column = 'file_source';
145
+            $fileDependentWhere = 'INNER JOIN `*PREFIX*filecache` ON `file_source` = `*PREFIX*filecache`.`fileid` ';
146
+            $fileDependentWhere .= 'INNER JOIN `*PREFIX*storages` ON `numeric_id` = `*PREFIX*filecache`.`storage` ';
147
+        } else {
148
+            $column = 'item_source';
149
+        }
150
+
151
+        $select = self::createSelectStatement(self::FORMAT_NONE, $fileDependent);
152
+
153
+        $where .= ' `' . $column . '` = ? AND `item_type` = ? ';
154
+        $arguments = [$itemSource, $itemType];
155
+        // for link shares $user === null
156
+        if ($user !== null) {
157
+            $where .= ' AND `share_with` = ? ';
158
+            $arguments[] = $user;
159
+        }
160
+
161
+        if ($shareType !== null) {
162
+            $where .= ' AND `share_type` = ? ';
163
+            $arguments[] = $shareType;
164
+        }
165
+
166
+        if ($owner !== null) {
167
+            $where .= ' AND `uid_owner` = ? ';
168
+            $arguments[] = $owner;
169
+        }
170
+
171
+        $query = \OC_DB::prepare('SELECT ' . $select . ' FROM `*PREFIX*share` '. $fileDependentWhere . $where);
172
+
173
+        $result = \OC_DB::executeAudited($query, $arguments);
174
+
175
+        while ($row = $result->fetchRow()) {
176
+            if ($fileDependent && !self::isFileReachable($row['path'], $row['storage_id'])) {
177
+                continue;
178
+            }
179
+            if ($fileDependent && (int)$row['file_parent'] === -1) {
180
+                // if it is a mount point we need to get the path from the mount manager
181
+                $mountManager = \OC\Files\Filesystem::getMountManager();
182
+                $mountPoint = $mountManager->findByStorageId($row['storage_id']);
183
+                if (!empty($mountPoint)) {
184
+                    $path = $mountPoint[0]->getMountPoint();
185
+                    $path = trim($path, '/');
186
+                    $path = substr($path, strlen($owner) + 1); //normalize path to 'files/foo.txt`
187
+                    $row['path'] = $path;
188
+                } else {
189
+                    \OC::$server->getLogger()->warning(
190
+                        'Could not resolve mount point for ' . $row['storage_id'],
191
+                        ['app' => 'OCP\Share']
192
+                    );
193
+                }
194
+            }
195
+            $shares[] = $row;
196
+        }
197
+
198
+        //if didn't found a result than let's look for a group share.
199
+        if(empty($shares) && $user !== null) {
200
+            $userObject = \OC::$server->getUserManager()->get($user);
201
+            $groups = [];
202
+            if ($userObject) {
203
+                $groups = \OC::$server->getGroupManager()->getUserGroupIds($userObject);
204
+            }
205
+
206
+            if (!empty($groups)) {
207
+                $where = $fileDependentWhere . ' WHERE `' . $column . '` = ? AND `item_type` = ? AND `share_with` in (?)';
208
+                $arguments = [$itemSource, $itemType, $groups];
209
+                $types = [null, null, IQueryBuilder::PARAM_STR_ARRAY];
210
+
211
+                if ($owner !== null) {
212
+                    $where .= ' AND `uid_owner` = ?';
213
+                    $arguments[] = $owner;
214
+                    $types[] = null;
215
+                }
216
+
217
+                // TODO: inject connection, hopefully one day in the future when this
218
+                // class isn't static anymore...
219
+                $conn = \OC::$server->getDatabaseConnection();
220
+                $result = $conn->executeQuery(
221
+                    'SELECT ' . $select . ' FROM `*PREFIX*share` ' . $where,
222
+                    $arguments,
223
+                    $types
224
+                );
225
+
226
+                while ($row = $result->fetch()) {
227
+                    $shares[] = $row;
228
+                }
229
+            }
230
+        }
231
+
232
+        return $shares;
233
+
234
+    }
235
+
236
+    /**
237
+     * Get the item of item type shared with the current user by source
238
+     * @param string $itemType
239
+     * @param string $itemSource
240
+     * @param int $format (optional) Format type must be defined by the backend
241
+     * @param mixed $parameters
242
+     * @param boolean $includeCollections
243
+     * @param string $shareWith (optional) define against which user should be checked, default: current user
244
+     * @return array
245
+     */
246
+    public static function getItemSharedWithBySource($itemType, $itemSource, $format = self::FORMAT_NONE,
247
+                                                        $parameters = null, $includeCollections = false, $shareWith = null) {
248
+        $shareWith = ($shareWith === null) ? \OC_User::getUser() : $shareWith;
249
+        return self::getItems($itemType, $itemSource, self::$shareTypeUserAndGroups, $shareWith, null, $format,
250
+            $parameters, 1, $includeCollections, true);
251
+    }
252
+
253
+    /**
254
+     * Get the shared item of item type owned by the current user
255
+     * @param string $itemType
256
+     * @param string $itemSource
257
+     * @param int $format (optional) Format type must be defined by the backend
258
+     * @param mixed $parameters
259
+     * @param boolean $includeCollections
260
+     * @return mixed Return depends on format
261
+     */
262
+    public static function getItemShared($itemType, $itemSource, $format = self::FORMAT_NONE,
263
+                                            $parameters = null, $includeCollections = false) {
264
+        return self::getItems($itemType, $itemSource, null, null, \OC_User::getUser(), $format,
265
+            $parameters, -1, $includeCollections);
266
+    }
267
+
268
+    /**
269
+     * Share an item with a user, group, or via private link
270
+     * @param string $itemType
271
+     * @param string $itemSource
272
+     * @param int $shareType SHARE_TYPE_USER, SHARE_TYPE_GROUP, or SHARE_TYPE_LINK
273
+     * @param string $shareWith User or group the item is being shared with
274
+     * @param int $permissions CRUDS
275
+     * @param string $itemSourceName
276
+     * @param \DateTime|null $expirationDate
277
+     * @return boolean|string Returns true on success or false on failure, Returns token on success for links
278
+     * @throws \OC\HintException when the share type is remote and the shareWith is invalid
279
+     * @throws \Exception
280
+     * @since 5.0.0 - parameter $itemSourceName was added in 6.0.0, parameter $expirationDate was added in 7.0.0, parameter $passwordChanged added in 9.0.0
281
+     * @deprecated 14.0.0 TESTS ONLY - this methods is as of 2018-06 only used by tests
282
+     * called like this:
283
+     * \OC\Share\Share::shareItem('test', 1, \OCP\Share::SHARE_TYPE_USER, $otherUserId, \OCP\Constants::PERMISSION_READ);
284
+     */
285
+    public static function shareItem($itemType, $itemSource, $shareType, $shareWith, $permissions) {
286
+        $backend = self::getBackend($itemType);
287
+
288
+        if ($backend->isShareTypeAllowed($shareType) === false) {
289
+            $message = 'Sharing failed, because the backend does not allow shares from type %i';
290
+            throw new \Exception(sprintf($message, $shareType));
291
+        }
292
+
293
+        $uidOwner = \OC_User::getUser();
294
+
295
+        // Verify share type and sharing conditions are met
296
+        if ($shareType === self::SHARE_TYPE_USER) {
297
+            if ($shareWith == $uidOwner) {
298
+                $message = 'Sharing failed, because you can not share with yourself';
299
+                throw new \Exception($message);
300
+            }
301
+            if (!\OC::$server->getUserManager()->userExists($shareWith)) {
302
+                $message = 'Sharing failed, because the user %s does not exist';
303
+                throw new \Exception(sprintf($message, $shareWith));
304
+            }
305
+            // Check if the item source is already shared with the user, either from the same owner or a different user
306
+            if ($checkExists = self::getItems($itemType, $itemSource, self::$shareTypeUserAndGroups,
307
+                $shareWith, null, self::FORMAT_NONE, null, 1, true, true)) {
308
+                // Only allow the same share to occur again if it is the same
309
+                // owner and is not a user share, this use case is for increasing
310
+                // permissions for a specific user
311
+                if ($checkExists['uid_owner'] != $uidOwner || $checkExists['share_type'] == $shareType) {
312
+                    $message = 'Sharing failed, because this item is already shared with %s';
313
+                    throw new \Exception(sprintf($message, $shareWith));
314
+                }
315
+            }
316
+            if ($checkExists = self::getItems($itemType, $itemSource, self::SHARE_TYPE_USER,
317
+                $shareWith, null, self::FORMAT_NONE, null, 1, true, true)) {
318
+                // Only allow the same share to occur again if it is the same
319
+                // owner and is not a user share, this use case is for increasing
320
+                // permissions for a specific user
321
+                if ($checkExists['uid_owner'] != $uidOwner || $checkExists['share_type'] == $shareType) {
322
+                    $message = 'Sharing failed, because this item is already shared with user %s';
323
+                    throw new \Exception(sprintf($message, $shareWith));
324
+                }
325
+            }
326
+        }
327
+
328
+        // Put the item into the database
329
+        $result = self::put('test', $itemSource, self::SHARE_TYPE_USER, $shareWith, $uidOwner, $permissions);
330
+
331
+        return $result ? true : false;
332
+    }
333
+
334
+    /**
335
+     * Unshare an item from a user, group, or delete a private link
336
+     * @param string $itemType
337
+     * @param string $itemSource
338
+     * @param int $shareType SHARE_TYPE_USER, SHARE_TYPE_GROUP, or SHARE_TYPE_LINK
339
+     * @param string $shareWith User or group the item is being shared with
340
+     * @param string $owner owner of the share, if null the current user is used
341
+     * @return boolean true on success or false on failure
342
+     */
343
+    public static function unshare($itemType, $itemSource, $shareType, $shareWith, $owner = null) {
344
+
345
+        // check if it is a valid itemType
346
+        self::getBackend($itemType);
347
+
348
+        $items = self::getItemSharedWithUser($itemType, $itemSource, $shareWith, $owner, $shareType);
349
+
350
+        $toDelete = [];
351
+        $newParent = null;
352
+        $currentUser = $owner ? $owner : \OC_User::getUser();
353
+        foreach ($items as $item) {
354
+            // delete the item with the expected share_type and owner
355
+            if ((int)$item['share_type'] === (int)$shareType && $item['uid_owner'] === $currentUser) {
356
+                $toDelete = $item;
357
+                // if there is more then one result we don't have to delete the children
358
+                // but update their parent. For group shares the new parent should always be
359
+                // the original group share and not the db entry with the unique name
360
+            } else if ((int)$item['share_type'] === self::$shareTypeGroupUserUnique) {
361
+                $newParent = $item['parent'];
362
+            } else {
363
+                $newParent = $item['id'];
364
+            }
365
+        }
366
+
367
+        if (!empty($toDelete)) {
368
+            self::unshareItem($toDelete, $newParent);
369
+            return true;
370
+        }
371
+        return false;
372
+    }
373
+
374
+    /**
375
+     * Checks whether a share has expired, calls unshareItem() if yes.
376
+     * @param array $item Share data (usually database row)
377
+     * @return boolean True if item was expired, false otherwise.
378
+     */
379
+    protected static function expireItem(array $item) {
380
+
381
+        $result = false;
382
+
383
+        // only use default expiration date for link shares
384
+        if ((int) $item['share_type'] === self::SHARE_TYPE_LINK) {
385
+
386
+            // calculate expiration date
387
+            if (!empty($item['expiration'])) {
388
+                $userDefinedExpire = new \DateTime($item['expiration']);
389
+                $expires = $userDefinedExpire->getTimestamp();
390
+            } else {
391
+                $expires = null;
392
+            }
393
+
394
+
395
+            // get default expiration settings
396
+            $defaultSettings = Helper::getDefaultExpireSetting();
397
+            $expires = Helper::calculateExpireDate($defaultSettings, $item['stime'], $expires);
398
+
399
+
400
+            if (is_int($expires)) {
401
+                $now = time();
402
+                if ($now > $expires) {
403
+                    self::unshareItem($item);
404
+                    $result = true;
405
+                }
406
+            }
407
+        }
408
+        return $result;
409
+    }
410
+
411
+    /**
412
+     * Unshares a share given a share data array
413
+     * @param array $item Share data (usually database row)
414
+     * @param int $newParent parent ID
415
+     * @return null
416
+     */
417
+    protected static function unshareItem(array $item, $newParent = null) {
418
+
419
+        $shareType = (int)$item['share_type'];
420
+        $shareWith = null;
421
+        if ($shareType !== \OCP\Share::SHARE_TYPE_LINK) {
422
+            $shareWith = $item['share_with'];
423
+        }
424
+
425
+        // Pass all the vars we have for now, they may be useful
426
+        $hookParams = [
427
+            'id'            => $item['id'],
428
+            'itemType'      => $item['item_type'],
429
+            'itemSource'    => $item['item_source'],
430
+            'shareType'     => $shareType,
431
+            'shareWith'     => $shareWith,
432
+            'itemParent'    => $item['parent'],
433
+            'uidOwner'      => $item['uid_owner'],
434
+        ];
435
+        if($item['item_type'] === 'file' || $item['item_type'] === 'folder') {
436
+            $hookParams['fileSource'] = $item['file_source'];
437
+            $hookParams['fileTarget'] = $item['file_target'];
438
+        }
439
+
440
+        \OC_Hook::emit(\OCP\Share::class, 'pre_unshare', $hookParams);
441
+        $deletedShares = Helper::delete($item['id'], false, null, $newParent);
442
+        $deletedShares[] = $hookParams;
443
+        $hookParams['deletedShares'] = $deletedShares;
444
+        \OC_Hook::emit(\OCP\Share::class, 'post_unshare', $hookParams);
445
+        if ((int)$item['share_type'] === \OCP\Share::SHARE_TYPE_REMOTE && \OC::$server->getUserSession()->getUser()) {
446
+            list(, $remote) = Helper::splitUserRemote($item['share_with']);
447
+            self::sendRemoteUnshare($remote, $item['id'], $item['token']);
448
+        }
449
+    }
450
+
451
+    /**
452
+     * Get the backend class for the specified item type
453
+     * @param string $itemType
454
+     * @throws \Exception
455
+     * @return \OCP\Share_Backend
456
+     */
457
+    public static function getBackend($itemType) {
458
+        $l = \OC::$server->getL10N('lib');
459
+        if (isset(self::$backends[$itemType])) {
460
+            return self::$backends[$itemType];
461
+        } else if (isset(self::$backendTypes[$itemType]['class'])) {
462
+            $class = self::$backendTypes[$itemType]['class'];
463
+            if (class_exists($class)) {
464
+                self::$backends[$itemType] = new $class;
465
+                if (!(self::$backends[$itemType] instanceof \OCP\Share_Backend)) {
466
+                    $message = 'Sharing backend %s must implement the interface OCP\Share_Backend';
467
+                    $message_t = $l->t('Sharing backend %s must implement the interface OCP\Share_Backend', [$class]);
468
+                    \OCP\Util::writeLog('OCP\Share', sprintf($message, $class), ILogger::ERROR);
469
+                    throw new \Exception($message_t);
470
+                }
471
+                return self::$backends[$itemType];
472
+            } else {
473
+                $message = 'Sharing backend %s not found';
474
+                $message_t = $l->t('Sharing backend %s not found', [$class]);
475
+                \OCP\Util::writeLog('OCP\Share', sprintf($message, $class), ILogger::ERROR);
476
+                throw new \Exception($message_t);
477
+            }
478
+        }
479
+        $message = 'Sharing backend for %s not found';
480
+        $message_t = $l->t('Sharing backend for %s not found', [$itemType]);
481
+        \OCP\Util::writeLog('OCP\Share', sprintf($message, $itemType), ILogger::ERROR);
482
+        throw new \Exception($message_t);
483
+    }
484
+
485
+    /**
486
+     * Check if resharing is allowed
487
+     * @return boolean true if allowed or false
488
+     *
489
+     * Resharing is allowed by default if not configured
490
+     */
491
+    public static function isResharingAllowed() {
492
+        if (!isset(self::$isResharingAllowed)) {
493
+            if (\OC::$server->getConfig()->getAppValue('core', 'shareapi_allow_resharing', 'yes') == 'yes') {
494
+                self::$isResharingAllowed = true;
495
+            } else {
496
+                self::$isResharingAllowed = false;
497
+            }
498
+        }
499
+        return self::$isResharingAllowed;
500
+    }
501
+
502
+    /**
503
+     * Get a list of collection item types for the specified item type
504
+     * @param string $itemType
505
+     * @return array
506
+     */
507
+    private static function getCollectionItemTypes($itemType) {
508
+        $collectionTypes = [$itemType];
509
+        foreach (self::$backendTypes as $type => $backend) {
510
+            if (in_array($backend['collectionOf'], $collectionTypes)) {
511
+                $collectionTypes[] = $type;
512
+            }
513
+        }
514
+        // TODO Add option for collections to be collection of themselves, only 'folder' does it now...
515
+        if (isset(self::$backendTypes[$itemType]) && (!self::getBackend($itemType) instanceof \OCP\Share_Backend_Collection || $itemType != 'folder')) {
516
+            unset($collectionTypes[0]);
517
+        }
518
+        // Return array if collections were found or the item type is a
519
+        // collection itself - collections can be inside collections
520
+        if (count($collectionTypes) > 0) {
521
+            return $collectionTypes;
522
+        }
523
+        return false;
524
+    }
525
+
526
+    /**
527
+     * Get the owners of items shared with a user.
528
+     *
529
+     * @param string $user The user the items are shared with.
530
+     * @param string $type The type of the items shared with the user.
531
+     * @param boolean $includeCollections Include collection item types (optional)
532
+     * @param boolean $includeOwner include owner in the list of users the item is shared with (optional)
533
+     * @return array
534
+     * @deprecated TESTS ONLY - this methods is only used by tests
535
+     * called like this:
536
+     * \OC\Share\Share::getSharedItemsOwners($this->user, $this->type, true)
537
+     */
538
+    public static function getSharedItemsOwners($user, $type, $includeCollections = false, $includeOwner = false) {
539
+        // First, we find out if $type is part of a collection (and if that collection is part of
540
+        // another one and so on).
541
+        $collectionTypes = [];
542
+        if (!$includeCollections || !$collectionTypes = self::getCollectionItemTypes($type)) {
543
+            $collectionTypes[] = $type;
544
+        }
545
+
546
+        // Of these collection types, along with our original $type, we make a
547
+        // list of the ones for which a sharing backend has been registered.
548
+        // FIXME: Ideally, we wouldn't need to nest getItemsSharedWith in this loop but just call it
549
+        // with its $includeCollections parameter set to true. Unfortunately, this fails currently.
550
+        $allMaybeSharedItems = [];
551
+        foreach ($collectionTypes as $collectionType) {
552
+            if (isset(self::$backends[$collectionType])) {
553
+                $allMaybeSharedItems[$collectionType] = self::getItemsSharedWithUser(
554
+                    $collectionType,
555
+                    $user,
556
+                    self::FORMAT_NONE
557
+                );
558
+            }
559
+        }
560
+
561
+        $owners = [];
562
+        if ($includeOwner) {
563
+            $owners[] = $user;
564
+        }
565
+
566
+        // We take a look at all shared items of the given $type (or of the collections it is part of)
567
+        // and find out their owners. Then, we gather the tags for the original $type from all owners,
568
+        // and return them as elements of a list that look like "Tag (owner)".
569
+        foreach ($allMaybeSharedItems as $collectionType => $maybeSharedItems) {
570
+            foreach ($maybeSharedItems as $sharedItem) {
571
+                if (isset($sharedItem['id'])) { //workaround for https://github.com/owncloud/core/issues/2814
572
+                    $owners[] = $sharedItem['uid_owner'];
573
+                }
574
+            }
575
+        }
576
+
577
+        return $owners;
578
+    }
579
+
580
+    /**
581
+     * Get shared items from the database
582
+     * @param string $itemType
583
+     * @param string $item Item source or target (optional)
584
+     * @param int $shareType SHARE_TYPE_USER, SHARE_TYPE_GROUP, SHARE_TYPE_LINK, $shareTypeUserAndGroups, or $shareTypeGroupUserUnique
585
+     * @param string $shareWith User or group the item is being shared with
586
+     * @param string $uidOwner User that is the owner of shared items (optional)
587
+     * @param int $format Format to convert items to with formatItems() (optional)
588
+     * @param mixed $parameters to pass to formatItems() (optional)
589
+     * @param int $limit Number of items to return, -1 to return all matches (optional)
590
+     * @param boolean $includeCollections Include collection item types (optional)
591
+     * @param boolean $itemShareWithBySource (optional)
592
+     * @param boolean $checkExpireDate
593
+     * @return array
594
+     *
595
+     * See public functions getItem(s)... for parameter usage
596
+     *
597
+     */
598
+    public static function getItems($itemType, $item = null, $shareType = null, $shareWith = null,
599
+                                    $uidOwner = null, $format = self::FORMAT_NONE, $parameters = null, $limit = -1,
600
+                                    $includeCollections = false, $itemShareWithBySource = false, $checkExpireDate  = true) {
601
+        if (\OC::$server->getConfig()->getAppValue('core', 'shareapi_enabled', 'yes') != 'yes') {
602
+            return [];
603
+        }
604
+        $backend = self::getBackend($itemType);
605
+        $collectionTypes = false;
606
+        // Get filesystem root to add it to the file target and remove from the
607
+        // file source, match file_source with the file cache
608
+        if ($itemType == 'file' || $itemType == 'folder') {
609
+            if(!is_null($uidOwner)) {
610
+                $root = \OC\Files\Filesystem::getRoot();
611
+            } else {
612
+                $root = '';
613
+            }
614
+            $where = 'INNER JOIN `*PREFIX*filecache` ON `file_source` = `*PREFIX*filecache`.`fileid` ';
615
+            if (!isset($item)) {
616
+                $where .= ' AND `file_target` IS NOT NULL ';
617
+            }
618
+            $where .= 'INNER JOIN `*PREFIX*storages` ON `numeric_id` = `*PREFIX*filecache`.`storage` ';
619
+            $fileDependent = true;
620
+            $queryArgs = [];
621
+        } else {
622
+            $fileDependent = false;
623
+            $root = '';
624
+            $collectionTypes = self::getCollectionItemTypes($itemType);
625
+            if ($includeCollections && !isset($item) && $collectionTypes) {
626
+                // If includeCollections is true, find collections of this item type, e.g. a music album contains songs
627
+                if (!in_array($itemType, $collectionTypes)) {
628
+                    $itemTypes = array_merge([$itemType], $collectionTypes);
629
+                } else {
630
+                    $itemTypes = $collectionTypes;
631
+                }
632
+                $placeholders = implode(',', array_fill(0, count($itemTypes), '?'));
633
+                $where = ' WHERE `item_type` IN ('.$placeholders.'))';
634
+                $queryArgs = $itemTypes;
635
+            } else {
636
+                $where = ' WHERE `item_type` = ?';
637
+                $queryArgs = [$itemType];
638
+            }
639
+        }
640
+        if (\OC::$server->getConfig()->getAppValue('core', 'shareapi_allow_links', 'yes') !== 'yes') {
641
+            $where .= ' AND `share_type` != ?';
642
+            $queryArgs[] = self::SHARE_TYPE_LINK;
643
+        }
644
+        if (isset($shareType)) {
645
+            // Include all user and group items
646
+            if ($shareType == self::$shareTypeUserAndGroups && isset($shareWith)) {
647
+                $where .= ' AND ((`share_type` in (?, ?) AND `share_with` = ?) ';
648
+                $queryArgs[] = self::SHARE_TYPE_USER;
649
+                $queryArgs[] = self::$shareTypeGroupUserUnique;
650
+                $queryArgs[] = $shareWith;
651
+
652
+                $user = \OC::$server->getUserManager()->get($shareWith);
653
+                $groups = [];
654
+                if ($user) {
655
+                    $groups = \OC::$server->getGroupManager()->getUserGroupIds($user);
656
+                }
657
+                if (!empty($groups)) {
658
+                    $placeholders = implode(',', array_fill(0, count($groups), '?'));
659
+                    $where .= ' OR (`share_type` = ? AND `share_with` IN ('.$placeholders.')) ';
660
+                    $queryArgs[] = self::SHARE_TYPE_GROUP;
661
+                    $queryArgs = array_merge($queryArgs, $groups);
662
+                }
663
+                $where .= ')';
664
+                // Don't include own group shares
665
+                $where .= ' AND `uid_owner` != ?';
666
+                $queryArgs[] = $shareWith;
667
+            } else {
668
+                $where .= ' AND `share_type` = ?';
669
+                $queryArgs[] = $shareType;
670
+                if (isset($shareWith)) {
671
+                    $where .= ' AND `share_with` = ?';
672
+                    $queryArgs[] = $shareWith;
673
+                }
674
+            }
675
+        }
676
+        if (isset($uidOwner)) {
677
+            $where .= ' AND `uid_owner` = ?';
678
+            $queryArgs[] = $uidOwner;
679
+            if (!isset($shareType)) {
680
+                // Prevent unique user targets for group shares from being selected
681
+                $where .= ' AND `share_type` != ?';
682
+                $queryArgs[] = self::$shareTypeGroupUserUnique;
683
+            }
684
+            if ($fileDependent) {
685
+                $column = 'file_source';
686
+            } else {
687
+                $column = 'item_source';
688
+            }
689
+        } else {
690
+            if ($fileDependent) {
691
+                $column = 'file_target';
692
+            } else {
693
+                $column = 'item_target';
694
+            }
695
+        }
696
+        if (isset($item)) {
697
+            $collectionTypes = self::getCollectionItemTypes($itemType);
698
+            if ($includeCollections && $collectionTypes && !in_array('folder', $collectionTypes)) {
699
+                $where .= ' AND (';
700
+            } else {
701
+                $where .= ' AND';
702
+            }
703
+            // If looking for own shared items, check item_source else check item_target
704
+            if (isset($uidOwner) || $itemShareWithBySource) {
705
+                // If item type is a file, file source needs to be checked in case the item was converted
706
+                if ($fileDependent) {
707
+                    $where .= ' `file_source` = ?';
708
+                    $column = 'file_source';
709
+                } else {
710
+                    $where .= ' `item_source` = ?';
711
+                    $column = 'item_source';
712
+                }
713
+            } else {
714
+                if ($fileDependent) {
715
+                    $where .= ' `file_target` = ?';
716
+                    $item = \OC\Files\Filesystem::normalizePath($item);
717
+                } else {
718
+                    $where .= ' `item_target` = ?';
719
+                }
720
+            }
721
+            $queryArgs[] = $item;
722
+            if ($includeCollections && $collectionTypes && !in_array('folder', $collectionTypes)) {
723
+                $placeholders = implode(',', array_fill(0, count($collectionTypes), '?'));
724
+                $where .= ' OR `item_type` IN ('.$placeholders.'))';
725
+                $queryArgs = array_merge($queryArgs, $collectionTypes);
726
+            }
727
+        }
728
+
729
+        if ($shareType == self::$shareTypeUserAndGroups && $limit === 1) {
730
+            // Make sure the unique user target is returned if it exists,
731
+            // unique targets should follow the group share in the database
732
+            // If the limit is not 1, the filtering can be done later
733
+            $where .= ' ORDER BY `*PREFIX*share`.`id` DESC';
734
+        } else {
735
+            $where .= ' ORDER BY `*PREFIX*share`.`id` ASC';
736
+        }
737
+
738
+        if ($limit != -1 && !$includeCollections) {
739
+            // The limit must be at least 3, because filtering needs to be done
740
+            if ($limit < 3) {
741
+                $queryLimit = 3;
742
+            } else {
743
+                $queryLimit = $limit;
744
+            }
745
+        } else {
746
+            $queryLimit = null;
747
+        }
748
+        $select = self::createSelectStatement($format, $fileDependent, $uidOwner);
749
+        $root = strlen($root);
750
+        $query = \OC_DB::prepare('SELECT '.$select.' FROM `*PREFIX*share` '.$where, $queryLimit);
751
+        $result = $query->execute($queryArgs);
752
+        if ($result === false) {
753
+            \OCP\Util::writeLog('OCP\Share',
754
+                \OC_DB::getErrorMessage() . ', select=' . $select . ' where=',
755
+                ILogger::ERROR);
756
+        }
757
+        $items = [];
758
+        $targets = [];
759
+        $switchedItems = [];
760
+        $mounts = [];
761
+        while ($row = $result->fetchRow()) {
762
+            self::transformDBResults($row);
763
+            // Filter out duplicate group shares for users with unique targets
764
+            if ($fileDependent && !self::isFileReachable($row['path'], $row['storage_id'])) {
765
+                continue;
766
+            }
767
+            if ($row['share_type'] == self::$shareTypeGroupUserUnique && isset($items[$row['parent']])) {
768
+                $row['share_type'] = self::SHARE_TYPE_GROUP;
769
+                $row['unique_name'] = true; // remember that we use a unique name for this user
770
+                $row['share_with'] = $items[$row['parent']]['share_with'];
771
+                // if the group share was unshared from the user we keep the permission, otherwise
772
+                // we take the permission from the parent because this is always the up-to-date
773
+                // permission for the group share
774
+                if ($row['permissions'] > 0) {
775
+                    $row['permissions'] = $items[$row['parent']]['permissions'];
776
+                }
777
+                // Remove the parent group share
778
+                unset($items[$row['parent']]);
779
+                if ($row['permissions'] == 0) {
780
+                    continue;
781
+                }
782
+            } else if (!isset($uidOwner)) {
783
+                // Check if the same target already exists
784
+                if (isset($targets[$row['id']])) {
785
+                    // Check if the same owner shared with the user twice
786
+                    // through a group and user share - this is allowed
787
+                    $id = $targets[$row['id']];
788
+                    if (isset($items[$id]) && $items[$id]['uid_owner'] == $row['uid_owner']) {
789
+                        // Switch to group share type to ensure resharing conditions aren't bypassed
790
+                        if ($items[$id]['share_type'] != self::SHARE_TYPE_GROUP) {
791
+                            $items[$id]['share_type'] = self::SHARE_TYPE_GROUP;
792
+                            $items[$id]['share_with'] = $row['share_with'];
793
+                        }
794
+                        // Switch ids if sharing permission is granted on only
795
+                        // one share to ensure correct parent is used if resharing
796
+                        if (~(int)$items[$id]['permissions'] & \OCP\Constants::PERMISSION_SHARE
797
+                            && (int)$row['permissions'] & \OCP\Constants::PERMISSION_SHARE) {
798
+                            $items[$row['id']] = $items[$id];
799
+                            $switchedItems[$id] = $row['id'];
800
+                            unset($items[$id]);
801
+                            $id = $row['id'];
802
+                        }
803
+                        $items[$id]['permissions'] |= (int)$row['permissions'];
804
+
805
+                    }
806
+                    continue;
807
+                } elseif (!empty($row['parent'])) {
808
+                    $targets[$row['parent']] = $row['id'];
809
+                }
810
+            }
811
+            // Remove root from file source paths if retrieving own shared items
812
+            if (isset($uidOwner) && isset($row['path'])) {
813
+                if (isset($row['parent'])) {
814
+                    $query = \OC_DB::prepare('SELECT `file_target` FROM `*PREFIX*share` WHERE `id` = ?');
815
+                    $parentResult = $query->execute([$row['parent']]);
816
+                    if ($result === false) {
817
+                        \OCP\Util::writeLog('OCP\Share', 'Can\'t select parent: ' .
818
+                            \OC_DB::getErrorMessage() . ', select=' . $select . ' where=' . $where,
819
+                            ILogger::ERROR);
820
+                    } else {
821
+                        $parentRow = $parentResult->fetchRow();
822
+                        $tmpPath = $parentRow['file_target'];
823
+                        // find the right position where the row path continues from the target path
824
+                        $pos = strrpos($row['path'], $parentRow['file_target']);
825
+                        $subPath = substr($row['path'], $pos);
826
+                        $splitPath = explode('/', $subPath);
827
+                        foreach (array_slice($splitPath, 2) as $pathPart) {
828
+                            $tmpPath = $tmpPath . '/' . $pathPart;
829
+                        }
830
+                        $row['path'] = $tmpPath;
831
+                    }
832
+                } else {
833
+                    if (!isset($mounts[$row['storage']])) {
834
+                        $mountPoints = \OC\Files\Filesystem::getMountByNumericId($row['storage']);
835
+                        if (is_array($mountPoints) && !empty($mountPoints)) {
836
+                            $mounts[$row['storage']] = current($mountPoints);
837
+                        }
838
+                    }
839
+                    if (!empty($mounts[$row['storage']])) {
840
+                        $path = $mounts[$row['storage']]->getMountPoint().$row['path'];
841
+                        $relPath = substr($path, $root); // path relative to data/user
842
+                        $row['path'] = rtrim($relPath, '/');
843
+                    }
844
+                }
845
+            }
846
+
847
+            if($checkExpireDate) {
848
+                if (self::expireItem($row)) {
849
+                    continue;
850
+                }
851
+            }
852
+            // Check if resharing is allowed, if not remove share permission
853
+            if (isset($row['permissions']) && (!self::isResharingAllowed() | \OCP\Util::isSharingDisabledForUser())) {
854
+                $row['permissions'] &= ~\OCP\Constants::PERMISSION_SHARE;
855
+            }
856
+            // Add display names to result
857
+            $row['share_with_displayname'] = $row['share_with'];
858
+            if ( isset($row['share_with']) && $row['share_with'] != '' &&
859
+                $row['share_type'] === self::SHARE_TYPE_USER) {
860
+                $shareWithUser = \OC::$server->getUserManager()->get($row['share_with']);
861
+                $row['share_with_displayname'] = $shareWithUser === null ? $row['share_with'] : $shareWithUser->getDisplayName();
862
+            } else if(isset($row['share_with']) && $row['share_with'] != '' &&
863
+                $row['share_type'] === self::SHARE_TYPE_REMOTE) {
864
+                $addressBookEntries = \OC::$server->getContactsManager()->search($row['share_with'], ['CLOUD']);
865
+                foreach ($addressBookEntries as $entry) {
866
+                    foreach ($entry['CLOUD'] as $cloudID) {
867
+                        if ($cloudID === $row['share_with']) {
868
+                            $row['share_with_displayname'] = $entry['FN'];
869
+                        }
870
+                    }
871
+                }
872
+            }
873
+            if ( isset($row['uid_owner']) && $row['uid_owner'] != '') {
874
+                $ownerUser = \OC::$server->getUserManager()->get($row['uid_owner']);
875
+                $row['displayname_owner'] = $ownerUser === null ? $row['uid_owner'] : $ownerUser->getDisplayName();
876
+            }
877
+
878
+            if ($row['permissions'] > 0) {
879
+                $items[$row['id']] = $row;
880
+            }
881
+
882
+        }
883
+
884
+        // group items if we are looking for items shared with the current user
885
+        if (isset($shareWith) && $shareWith === \OCP\User::getUser()) {
886
+            $items = self::groupItems($items, $itemType);
887
+        }
888
+
889
+        if (!empty($items)) {
890
+            $collectionItems = [];
891
+            foreach ($items as &$row) {
892
+                // Return only the item instead of a 2-dimensional array
893
+                if ($limit == 1 && $row[$column] == $item && ($row['item_type'] == $itemType || $itemType == 'file')) {
894
+                    if ($format == self::FORMAT_NONE) {
895
+                        return $row;
896
+                    } else {
897
+                        break;
898
+                    }
899
+                }
900
+                // Check if this is a collection of the requested item type
901
+                if ($includeCollections && $collectionTypes && $row['item_type'] !== 'folder' && in_array($row['item_type'], $collectionTypes)) {
902
+                    if (($collectionBackend = self::getBackend($row['item_type']))
903
+                        && $collectionBackend instanceof \OCP\Share_Backend_Collection) {
904
+                        // Collections can be inside collections, check if the item is a collection
905
+                        if (isset($item) && $row['item_type'] == $itemType && $row[$column] == $item) {
906
+                            $collectionItems[] = $row;
907
+                        } else {
908
+                            $collection = [];
909
+                            $collection['item_type'] = $row['item_type'];
910
+                            if ($row['item_type'] == 'file' || $row['item_type'] == 'folder') {
911
+                                $collection['path'] = basename($row['path']);
912
+                            }
913
+                            $row['collection'] = $collection;
914
+                            // Fetch all of the children sources
915
+                            $children = $collectionBackend->getChildren($row[$column]);
916
+                            foreach ($children as $child) {
917
+                                $childItem = $row;
918
+                                $childItem['item_type'] = $itemType;
919
+                                if ($row['item_type'] != 'file' && $row['item_type'] != 'folder') {
920
+                                    $childItem['item_source'] = $child['source'];
921
+                                    $childItem['item_target'] = $child['target'];
922
+                                }
923
+                                if ($backend instanceof \OCP\Share_Backend_File_Dependent) {
924
+                                    if ($row['item_type'] == 'file' || $row['item_type'] == 'folder') {
925
+                                        $childItem['file_source'] = $child['source'];
926
+                                    } else { // TODO is this really needed if we already know that we use the file backend?
927
+                                        $meta = \OC\Files\Filesystem::getFileInfo($child['file_path']);
928
+                                        $childItem['file_source'] = $meta['fileid'];
929
+                                    }
930
+                                    $childItem['file_target'] =
931
+                                        \OC\Files\Filesystem::normalizePath($child['file_path']);
932
+                                }
933
+                                if (isset($item)) {
934
+                                    if ($childItem[$column] == $item) {
935
+                                        // Return only the item instead of a 2-dimensional array
936
+                                        if ($limit == 1) {
937
+                                            if ($format == self::FORMAT_NONE) {
938
+                                                return $childItem;
939
+                                            } else {
940
+                                                // Unset the items array and break out of both loops
941
+                                                $items = [];
942
+                                                $items[] = $childItem;
943
+                                                break 2;
944
+                                            }
945
+                                        } else {
946
+                                            $collectionItems[] = $childItem;
947
+                                        }
948
+                                    }
949
+                                } else {
950
+                                    $collectionItems[] = $childItem;
951
+                                }
952
+                            }
953
+                        }
954
+                    }
955
+                    // Remove collection item
956
+                    $toRemove = $row['id'];
957
+                    if (array_key_exists($toRemove, $switchedItems)) {
958
+                        $toRemove = $switchedItems[$toRemove];
959
+                    }
960
+                    unset($items[$toRemove]);
961
+                } elseif ($includeCollections && $collectionTypes && in_array($row['item_type'], $collectionTypes)) {
962
+                    // FIXME: Thats a dirty hack to improve file sharing performance,
963
+                    // see github issue #10588 for more details
964
+                    // Need to find a solution which works for all back-ends
965
+                    $collectionBackend = self::getBackend($row['item_type']);
966
+                    $sharedParents = $collectionBackend->getParents($row['item_source']);
967
+                    foreach ($sharedParents as $parent) {
968
+                        $collectionItems[] = $parent;
969
+                    }
970
+                }
971
+            }
972
+            if (!empty($collectionItems)) {
973
+                $collectionItems = array_unique($collectionItems, SORT_REGULAR);
974
+                $items = array_merge($items, $collectionItems);
975
+            }
976
+
977
+            // filter out invalid items, these can appear when subshare entries exist
978
+            // for a group in which the requested user isn't a member any more
979
+            $items = array_filter($items, function($item) {
980
+                return $item['share_type'] !== self::$shareTypeGroupUserUnique;
981
+            });
982
+
983
+            return self::formatResult($items, $column, $backend, $format, $parameters);
984
+        } elseif ($includeCollections && $collectionTypes && in_array('folder', $collectionTypes)) {
985
+            // FIXME: Thats a dirty hack to improve file sharing performance,
986
+            // see github issue #10588 for more details
987
+            // Need to find a solution which works for all back-ends
988
+            $collectionItems = [];
989
+            $collectionBackend = self::getBackend('folder');
990
+            $sharedParents = $collectionBackend->getParents($item, $shareWith, $uidOwner);
991
+            foreach ($sharedParents as $parent) {
992
+                $collectionItems[] = $parent;
993
+            }
994
+            if ($limit === 1) {
995
+                return reset($collectionItems);
996
+            }
997
+            return self::formatResult($collectionItems, $column, $backend, $format, $parameters);
998
+        }
999
+
1000
+        return [];
1001
+    }
1002
+
1003
+    /**
1004
+     * group items with link to the same source
1005
+     *
1006
+     * @param array $items
1007
+     * @param string $itemType
1008
+     * @return array of grouped items
1009
+     */
1010
+    protected static function groupItems($items, $itemType) {
1011
+
1012
+        $fileSharing = $itemType === 'file' || $itemType === 'folder';
1013
+
1014
+        $result = [];
1015
+
1016
+        foreach ($items as $item) {
1017
+            $grouped = false;
1018
+            foreach ($result as $key => $r) {
1019
+                // for file/folder shares we need to compare file_source, otherwise we compare item_source
1020
+                // only group shares if they already point to the same target, otherwise the file where shared
1021
+                // before grouping of shares was added. In this case we don't group them toi avoid confusions
1022
+                if (( $fileSharing && $item['file_source'] === $r['file_source'] && $item['file_target'] === $r['file_target']) ||
1023
+                    (!$fileSharing && $item['item_source'] === $r['item_source'] && $item['item_target'] === $r['item_target'])) {
1024
+                    // add the first item to the list of grouped shares
1025
+                    if (!isset($result[$key]['grouped'])) {
1026
+                        $result[$key]['grouped'][] = $result[$key];
1027
+                    }
1028
+                    $result[$key]['permissions'] = (int) $item['permissions'] | (int) $r['permissions'];
1029
+                    $result[$key]['grouped'][] = $item;
1030
+                    $grouped = true;
1031
+                    break;
1032
+                }
1033
+            }
1034
+
1035
+            if (!$grouped) {
1036
+                $result[] = $item;
1037
+            }
1038
+
1039
+        }
1040
+
1041
+        return $result;
1042
+    }
1043
+
1044
+    /**
1045
+     * Put shared item into the database
1046
+     * @param string $itemType Item type
1047
+     * @param string $itemSource Item source
1048
+     * @param int $shareType SHARE_TYPE_USER, SHARE_TYPE_GROUP, or SHARE_TYPE_LINK
1049
+     * @param string $shareWith User or group the item is being shared with
1050
+     * @param string $uidOwner User that is the owner of shared item
1051
+     * @param int $permissions CRUDS permissions
1052
+     * @throws \Exception
1053
+     * @return mixed id of the new share or false
1054
+     * @deprecated TESTS ONLY - this methods is only used by tests
1055
+     * called like this:
1056
+     * self::put('test', $itemSource, self::SHARE_TYPE_USER, $shareWith, $uidOwner, $permissions);
1057
+     */
1058
+    private static function put($itemType, $itemSource, $shareType, $shareWith, $uidOwner,
1059
+                                $permissions) {
1060
+
1061
+        $queriesToExecute = [];
1062
+        $suggestedItemTarget = null;
1063
+        $groupFileTarget = $fileTarget = $suggestedFileTarget = $filePath = '';
1064
+        $groupItemTarget = $itemTarget = $fileSource = $parent = 0;
1065
+
1066
+        $result = self::checkReshare('test', $itemSource, self::SHARE_TYPE_USER, $shareWith, $uidOwner, $permissions, null, null);
1067
+        if(!empty($result)) {
1068
+            $parent = $result['parent'];
1069
+            $itemSource = $result['itemSource'];
1070
+            $fileSource = $result['fileSource'];
1071
+            $suggestedItemTarget = $result['suggestedItemTarget'];
1072
+            $suggestedFileTarget = $result['suggestedFileTarget'];
1073
+            $filePath = $result['filePath'];
1074
+        }
1075
+
1076
+        $isGroupShare = false;
1077
+            $users = [$shareWith];
1078
+            $itemTarget = Helper::generateTarget($itemType, $itemSource, $shareType, $shareWith, $uidOwner,
1079
+                $suggestedItemTarget);
1080
+
1081
+        $run = true;
1082
+        $error = '';
1083
+        $preHookData = [
1084
+            'itemType' => $itemType,
1085
+            'itemSource' => $itemSource,
1086
+            'shareType' => $shareType,
1087
+            'uidOwner' => $uidOwner,
1088
+            'permissions' => $permissions,
1089
+            'fileSource' => $fileSource,
1090
+            'expiration' => null,
1091
+            'token' => null,
1092
+            'run' => &$run,
1093
+            'error' => &$error
1094
+        ];
1095
+
1096
+        $preHookData['itemTarget'] = $itemTarget;
1097
+        $preHookData['shareWith'] = $shareWith;
1098
+
1099
+        \OC_Hook::emit(\OCP\Share::class, 'pre_shared', $preHookData);
1100
+
1101
+        if ($run === false) {
1102
+            throw new \Exception($error);
1103
+        }
1104
+
1105
+        foreach ($users as $user) {
1106
+            $sourceId = ($itemType === 'file' || $itemType === 'folder') ? $fileSource : $itemSource;
1107
+            $sourceExists = self::getItemSharedWithBySource($itemType, $sourceId, self::FORMAT_NONE, null, true, $user);
1108
+
1109
+            $userShareType = $shareType;
1110
+
1111
+            if ($sourceExists && $sourceExists['item_source'] === $itemSource) {
1112
+                $fileTarget = $sourceExists['file_target'];
1113
+                $itemTarget = $sourceExists['item_target'];
1114
+
1115
+            } elseif(!$sourceExists)  {
1116
+
1117
+                $itemTarget = Helper::generateTarget($itemType, $itemSource, $userShareType, $user,
1118
+                    $uidOwner, $suggestedItemTarget, $parent);
1119
+                if (isset($fileSource)) {
1120
+                        $fileTarget = Helper::generateTarget('file', $filePath, $userShareType,
1121
+                            $user, $uidOwner, $suggestedFileTarget, $parent);
1122
+                } else {
1123
+                    $fileTarget = null;
1124
+                }
1125
+
1126
+            } else {
1127
+
1128
+                // group share which doesn't exists until now, check if we need a unique target for this user
1129
+
1130
+                $itemTarget = Helper::generateTarget($itemType, $itemSource, self::SHARE_TYPE_USER, $user,
1131
+                    $uidOwner, $suggestedItemTarget, $parent);
1132
+
1133
+                // do we also need a file target
1134
+                if (isset($fileSource)) {
1135
+                    $fileTarget = Helper::generateTarget('file', $filePath, self::SHARE_TYPE_USER, $user,
1136
+                        $uidOwner, $suggestedFileTarget, $parent);
1137
+                } else {
1138
+                    $fileTarget = null;
1139
+                }
1140
+
1141
+                if (($itemTarget === $groupItemTarget) &&
1142
+                    (!isset($fileSource) || $fileTarget === $groupFileTarget)) {
1143
+                    continue;
1144
+                }
1145
+            }
1146
+
1147
+            $queriesToExecute[] = [
1148
+                'itemType'			=> $itemType,
1149
+                'itemSource'		=> $itemSource,
1150
+                'itemTarget'		=> $itemTarget,
1151
+                'shareType'			=> $userShareType,
1152
+                'shareWith'			=> $user,
1153
+                'uidOwner'			=> $uidOwner,
1154
+                'permissions'		=> $permissions,
1155
+                'shareTime'			=> time(),
1156
+                'fileSource'		=> $fileSource,
1157
+                'fileTarget'		=> $fileTarget,
1158
+                'token'				=> null,
1159
+                'parent'			=> $parent,
1160
+                'expiration'		=> null,
1161
+            ];
1162
+
1163
+        }
1164
+
1165
+        $id = false;
1166
+
1167
+        foreach ($queriesToExecute as $shareQuery) {
1168
+            $shareQuery['parent'] = $parent;
1169
+            $id = self::insertShare($shareQuery);
1170
+        }
1171
+
1172
+        $postHookData = [
1173
+            'itemType' => $itemType,
1174
+            'itemSource' => $itemSource,
1175
+            'parent' => $parent,
1176
+            'shareType' => $shareType,
1177
+            'uidOwner' => $uidOwner,
1178
+            'permissions' => $permissions,
1179
+            'fileSource' => $fileSource,
1180
+            'id' => $parent,
1181
+            'token' => null,
1182
+            'expirationDate' => null,
1183
+        ];
1184
+
1185
+        $postHookData['shareWith'] = $isGroupShare ? $shareWith['group'] : $shareWith;
1186
+        $postHookData['itemTarget'] = $isGroupShare ? $groupItemTarget : $itemTarget;
1187
+        $postHookData['fileTarget'] = $isGroupShare ? $groupFileTarget : $fileTarget;
1188
+
1189
+        \OC_Hook::emit(\OCP\Share::class, 'post_shared', $postHookData);
1190
+
1191
+
1192
+        return $id ? $id : false;
1193
+    }
1194
+
1195
+    /**
1196
+     * @param string $itemType
1197
+     * @param string $itemSource
1198
+     * @param int $shareType
1199
+     * @param string $shareWith
1200
+     * @param string $uidOwner
1201
+     * @param int $permissions
1202
+     * @param string|null $itemSourceName
1203
+     * @param null|\DateTime $expirationDate
1204
+     * @deprecated TESTS ONLY - this methods is only used by tests
1205
+     * called like this:
1206
+     * self::checkReshare('test', $itemSource, self::SHARE_TYPE_USER, $shareWith, $uidOwner, $permissions, null, null);
1207
+     */
1208
+    private static function checkReshare($itemType, $itemSource, $shareType, $shareWith, $uidOwner, $permissions, $itemSourceName, $expirationDate) {
1209
+        $backend = self::getBackend($itemType);
1210
+
1211
+        $result = [];
1212
+
1213
+        $column = ($itemType === 'file' || $itemType === 'folder') ? 'file_source' : 'item_source';
1214
+
1215
+        $checkReshare = self::getItemSharedWithBySource($itemType, $itemSource, self::FORMAT_NONE, null, true);
1216
+        if ($checkReshare) {
1217
+            // Check if attempting to share back to owner
1218
+            if ($checkReshare['uid_owner'] == $shareWith) {
1219
+                $message = 'Sharing %1$s failed, because the user %2$s is the original sharer';
1220
+                throw new \Exception(sprintf($message, $itemSourceName, $shareWith));
1221
+            }
1222
+        }
1223
+
1224
+        if ($checkReshare && $checkReshare['uid_owner'] !== \OC_User::getUser()) {
1225
+            // Check if share permissions is granted
1226
+            if (self::isResharingAllowed() && (int)$checkReshare['permissions'] & \OCP\Constants::PERMISSION_SHARE) {
1227
+                if (~(int)$checkReshare['permissions'] & $permissions) {
1228
+                    $message = 'Sharing %1$s failed, because the permissions exceed permissions granted to %2$s';
1229
+                    throw new \Exception(sprintf($message, $itemSourceName, $uidOwner));
1230
+                } else {
1231
+                    // TODO Don't check if inside folder
1232
+                    $result['parent'] = $checkReshare['id'];
1233
+
1234
+                    $result['expirationDate'] = $expirationDate;
1235
+                    // $checkReshare['expiration'] could be null and then is always less than any value
1236
+                    if(isset($checkReshare['expiration']) && $checkReshare['expiration'] < $expirationDate) {
1237
+                        $result['expirationDate'] = $checkReshare['expiration'];
1238
+                    }
1239
+
1240
+                    // only suggest the same name as new target if it is a reshare of the
1241
+                    // same file/folder and not the reshare of a child
1242
+                    if ($checkReshare[$column] === $itemSource) {
1243
+                        $result['filePath'] = $checkReshare['file_target'];
1244
+                        $result['itemSource'] = $checkReshare['item_source'];
1245
+                        $result['fileSource'] = $checkReshare['file_source'];
1246
+                        $result['suggestedItemTarget'] = $checkReshare['item_target'];
1247
+                        $result['suggestedFileTarget'] = $checkReshare['file_target'];
1248
+                    } else {
1249
+                        $result['filePath'] = ($backend instanceof \OCP\Share_Backend_File_Dependent) ? $backend->getFilePath($itemSource, $uidOwner) : null;
1250
+                        $result['suggestedItemTarget'] = null;
1251
+                        $result['suggestedFileTarget'] = null;
1252
+                        $result['itemSource'] = $itemSource;
1253
+                        $result['fileSource'] = ($backend instanceof \OCP\Share_Backend_File_Dependent) ? $itemSource : null;
1254
+                    }
1255
+                }
1256
+            } else {
1257
+                $message = 'Sharing %s failed, because resharing is not allowed';
1258
+                throw new \Exception(sprintf($message, $itemSourceName));
1259
+            }
1260
+        } else {
1261
+            $result['parent'] = null;
1262
+            $result['suggestedItemTarget'] = null;
1263
+            $result['suggestedFileTarget'] = null;
1264
+            $result['itemSource'] = $itemSource;
1265
+            $result['expirationDate'] = $expirationDate;
1266
+            if (!$backend->isValidSource($itemSource, $uidOwner)) {
1267
+                $message = 'Sharing %1$s failed, because the sharing backend for '
1268
+                    .'%2$s could not find its source';
1269
+                throw new \Exception(sprintf($message, $itemSource, $itemType));
1270
+            }
1271
+            if ($backend instanceof \OCP\Share_Backend_File_Dependent) {
1272
+                $result['filePath'] = $backend->getFilePath($itemSource, $uidOwner);
1273
+                    $meta = \OC\Files\Filesystem::getFileInfo($result['filePath']);
1274
+                    $result['fileSource'] = $meta['fileid'];
1275
+                if ($result['fileSource'] == -1) {
1276
+                    $message = 'Sharing %s failed, because the file could not be found in the file cache';
1277
+                    throw new \Exception(sprintf($message, $itemSource));
1278
+                }
1279
+            } else {
1280
+                $result['filePath'] = null;
1281
+                $result['fileSource'] = null;
1282
+            }
1283
+        }
1284
+
1285
+        return $result;
1286
+    }
1287
+
1288
+    /**
1289
+     *
1290
+     * @param array $shareData
1291
+     * @return mixed false in case of a failure or the id of the new share
1292
+     */
1293
+    private static function insertShare(array $shareData) {
1294
+
1295
+        $query = \OC_DB::prepare('INSERT INTO `*PREFIX*share` ('
1296
+            .' `item_type`, `item_source`, `item_target`, `share_type`,'
1297
+            .' `share_with`, `uid_owner`, `permissions`, `stime`, `file_source`,'
1298
+            .' `file_target`, `token`, `parent`, `expiration`) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)');
1299
+        $query->bindValue(1, $shareData['itemType']);
1300
+        $query->bindValue(2, $shareData['itemSource']);
1301
+        $query->bindValue(3, $shareData['itemTarget']);
1302
+        $query->bindValue(4, $shareData['shareType']);
1303
+        $query->bindValue(5, $shareData['shareWith']);
1304
+        $query->bindValue(6, $shareData['uidOwner']);
1305
+        $query->bindValue(7, $shareData['permissions']);
1306
+        $query->bindValue(8, $shareData['shareTime']);
1307
+        $query->bindValue(9, $shareData['fileSource']);
1308
+        $query->bindValue(10, $shareData['fileTarget']);
1309
+        $query->bindValue(11, $shareData['token']);
1310
+        $query->bindValue(12, $shareData['parent']);
1311
+        $query->bindValue(13, $shareData['expiration'], 'datetime');
1312
+        $result = $query->execute();
1313
+
1314
+        $id = false;
1315
+        if ($result) {
1316
+            $id =  \OC::$server->getDatabaseConnection()->lastInsertId('*PREFIX*share');
1317
+        }
1318
+
1319
+        return $id;
1320
+
1321
+    }
1322
+
1323
+    /**
1324
+     * construct select statement
1325
+     * @param int $format
1326
+     * @param boolean $fileDependent ist it a file/folder share or a generla share
1327
+     * @param string $uidOwner
1328
+     * @return string select statement
1329
+     */
1330
+    private static function createSelectStatement($format, $fileDependent, $uidOwner = null) {
1331
+        $select = '*';
1332
+        if ($format == self::FORMAT_STATUSES) {
1333
+            if ($fileDependent) {
1334
+                $select = '`*PREFIX*share`.`id`, `*PREFIX*share`.`parent`, `share_type`, `path`, `storage`, '
1335
+                    . '`share_with`, `uid_owner` , `file_source`, `stime`, `*PREFIX*share`.`permissions`, '
1336
+                    . '`*PREFIX*storages`.`id` AS `storage_id`, `*PREFIX*filecache`.`parent` as `file_parent`, '
1337
+                    . '`uid_initiator`';
1338
+            } else {
1339
+                $select = '`id`, `parent`, `share_type`, `share_with`, `uid_owner`, `item_source`, `stime`, `*PREFIX*share`.`permissions`';
1340
+            }
1341
+        } else {
1342
+            if (isset($uidOwner)) {
1343
+                if ($fileDependent) {
1344
+                    $select = '`*PREFIX*share`.`id`, `item_type`, `item_source`, `*PREFIX*share`.`parent`,'
1345
+                        . ' `share_type`, `share_with`, `file_source`, `file_target`, `path`, `*PREFIX*share`.`permissions`, `stime`,'
1346
+                        . ' `expiration`, `token`, `storage`, `mail_send`, `uid_owner`, '
1347
+                        . '`*PREFIX*storages`.`id` AS `storage_id`, `*PREFIX*filecache`.`parent` as `file_parent`';
1348
+                } else {
1349
+                    $select = '`id`, `item_type`, `item_source`, `parent`, `share_type`, `share_with`, `*PREFIX*share`.`permissions`,'
1350
+                        . ' `stime`, `file_source`, `expiration`, `token`, `mail_send`, `uid_owner`';
1351
+                }
1352
+            } else {
1353
+                if ($fileDependent) {
1354
+                    if ($format == \OCA\Files_Sharing\ShareBackend\File::FORMAT_GET_FOLDER_CONTENTS || $format == \OCA\Files_Sharing\ShareBackend\File::FORMAT_FILE_APP_ROOT) {
1355
+                        $select = '`*PREFIX*share`.`id`, `item_type`, `item_source`, `*PREFIX*share`.`parent`, `uid_owner`, '
1356
+                            . '`share_type`, `share_with`, `file_source`, `path`, `file_target`, `stime`, '
1357
+                            . '`*PREFIX*share`.`permissions`, `expiration`, `storage`, `*PREFIX*filecache`.`parent` as `file_parent`, '
1358
+                            . '`name`, `mtime`, `mimetype`, `mimepart`, `size`, `encrypted`, `etag`, `mail_send`';
1359
+                    } else {
1360
+                        $select = '`*PREFIX*share`.`id`, `item_type`, `item_source`, `item_target`,'
1361
+                            . '`*PREFIX*share`.`parent`, `share_type`, `share_with`, `uid_owner`,'
1362
+                            . '`file_source`, `path`, `file_target`, `*PREFIX*share`.`permissions`,'
1363
+                            . '`stime`, `expiration`, `token`, `storage`, `mail_send`,'
1364
+                            . '`*PREFIX*storages`.`id` AS `storage_id`, `*PREFIX*filecache`.`parent` as `file_parent`';
1365
+                    }
1366
+                }
1367
+            }
1368
+        }
1369
+        return $select;
1370
+    }
1371
+
1372
+
1373
+    /**
1374
+     * transform db results
1375
+     * @param array $row result
1376
+     */
1377
+    private static function transformDBResults(&$row) {
1378
+        if (isset($row['id'])) {
1379
+            $row['id'] = (int) $row['id'];
1380
+        }
1381
+        if (isset($row['share_type'])) {
1382
+            $row['share_type'] = (int) $row['share_type'];
1383
+        }
1384
+        if (isset($row['parent'])) {
1385
+            $row['parent'] = (int) $row['parent'];
1386
+        }
1387
+        if (isset($row['file_parent'])) {
1388
+            $row['file_parent'] = (int) $row['file_parent'];
1389
+        }
1390
+        if (isset($row['file_source'])) {
1391
+            $row['file_source'] = (int) $row['file_source'];
1392
+        }
1393
+        if (isset($row['permissions'])) {
1394
+            $row['permissions'] = (int) $row['permissions'];
1395
+        }
1396
+        if (isset($row['storage'])) {
1397
+            $row['storage'] = (int) $row['storage'];
1398
+        }
1399
+        if (isset($row['stime'])) {
1400
+            $row['stime'] = (int) $row['stime'];
1401
+        }
1402
+        if (isset($row['expiration']) && $row['share_type'] !== self::SHARE_TYPE_LINK) {
1403
+            // discard expiration date for non-link shares, which might have been
1404
+            // set by ancient bugs
1405
+            $row['expiration'] = null;
1406
+        }
1407
+    }
1408
+
1409
+    /**
1410
+     * format result
1411
+     * @param array $items result
1412
+     * @param string $column is it a file share or a general share ('file_target' or 'item_target')
1413
+     * @param \OCP\Share_Backend $backend sharing backend
1414
+     * @param int $format
1415
+     * @param array $parameters additional format parameters
1416
+     * @return array format result
1417
+     */
1418
+    private static function formatResult($items, $column, $backend, $format = self::FORMAT_NONE , $parameters = null) {
1419
+        if ($format === self::FORMAT_NONE) {
1420
+            return $items;
1421
+        } else if ($format === self::FORMAT_STATUSES) {
1422
+            $statuses = [];
1423
+            foreach ($items as $item) {
1424
+                if ($item['share_type'] === self::SHARE_TYPE_LINK) {
1425
+                    if ($item['uid_initiator'] !== \OC::$server->getUserSession()->getUser()->getUID()) {
1426
+                        continue;
1427
+                    }
1428
+                    $statuses[$item[$column]]['link'] = true;
1429
+                } else if (!isset($statuses[$item[$column]])) {
1430
+                    $statuses[$item[$column]]['link'] = false;
1431
+                }
1432
+                if (!empty($item['file_target'])) {
1433
+                    $statuses[$item[$column]]['path'] = $item['path'];
1434
+                }
1435
+            }
1436
+            return $statuses;
1437
+        } else {
1438
+            return $backend->formatItems($items, $format, $parameters);
1439
+        }
1440
+    }
1441
+
1442
+    /**
1443
+     * remove protocol from URL
1444
+     *
1445
+     * @param string $url
1446
+     * @return string
1447
+     */
1448
+    public static function removeProtocolFromUrl($url) {
1449
+        if (strpos($url, 'https://') === 0) {
1450
+            return substr($url, strlen('https://'));
1451
+        } else if (strpos($url, 'http://') === 0) {
1452
+            return substr($url, strlen('http://'));
1453
+        }
1454
+
1455
+        return $url;
1456
+    }
1457
+
1458
+    /**
1459
+     * try http post first with https and then with http as a fallback
1460
+     *
1461
+     * @param string $remoteDomain
1462
+     * @param string $urlSuffix
1463
+     * @param array $fields post parameters
1464
+     * @return array
1465
+     */
1466
+    private static function tryHttpPostToShareEndpoint($remoteDomain, $urlSuffix, array $fields) {
1467
+        $protocol = 'https://';
1468
+        $result = [
1469
+            'success' => false,
1470
+            'result' => '',
1471
+        ];
1472
+        $try = 0;
1473
+        $discoveryService = \OC::$server->query(\OCP\OCS\IDiscoveryService::class);
1474
+        while ($result['success'] === false && $try < 2) {
1475
+            $federationEndpoints = $discoveryService->discover($protocol . $remoteDomain, 'FEDERATED_SHARING');
1476
+            $endpoint = isset($federationEndpoints['share']) ? $federationEndpoints['share'] : '/ocs/v2.php/cloud/shares';
1477
+            $client = \OC::$server->getHTTPClientService()->newClient();
1478
+
1479
+            try {
1480
+                $response = $client->post(
1481
+                    $protocol . $remoteDomain . $endpoint . $urlSuffix . '?format=' . self::RESPONSE_FORMAT,
1482
+                    [
1483
+                        'body' => $fields,
1484
+                        'connect_timeout' => 10,
1485
+                    ]
1486
+                );
1487
+
1488
+                $result = ['success' => true, 'result' => $response->getBody()];
1489
+            } catch (\Exception $e) {
1490
+                $result = ['success' => false, 'result' => $e->getMessage()];
1491
+            }
1492
+
1493
+            $try++;
1494
+            $protocol = 'http://';
1495
+        }
1496
+
1497
+        return $result;
1498
+    }
1499
+
1500
+    /**
1501
+     * send server-to-server unshare to remote server
1502
+     *
1503
+     * @param string $remote url
1504
+     * @param int $id share id
1505
+     * @param string $token
1506
+     * @return bool
1507
+     */
1508
+    private static function sendRemoteUnshare($remote, $id, $token) {
1509
+        $url = rtrim($remote, '/');
1510
+        $fields = ['token' => $token, 'format' => 'json'];
1511
+        $url = self::removeProtocolFromUrl($url);
1512
+        $result = self::tryHttpPostToShareEndpoint($url, '/'.$id.'/unshare', $fields);
1513
+        $status = json_decode($result['result'], true);
1514
+
1515
+        return ($result['success'] && ($status['ocs']['meta']['statuscode'] === 100 || $status['ocs']['meta']['statuscode'] === 200));
1516
+    }
1517
+
1518
+    /**
1519
+     * @return int
1520
+     */
1521
+    public static function getExpireInterval() {
1522
+        return (int)\OC::$server->getConfig()->getAppValue('core', 'shareapi_expire_after_n_days', '7');
1523
+    }
1524
+
1525
+    /**
1526
+     * Checks whether the given path is reachable for the given owner
1527
+     *
1528
+     * @param string $path path relative to files
1529
+     * @param string $ownerStorageId storage id of the owner
1530
+     *
1531
+     * @return boolean true if file is reachable, false otherwise
1532
+     */
1533
+    private static function isFileReachable($path, $ownerStorageId) {
1534
+        // if outside the home storage, file is always considered reachable
1535
+        if (!(substr($ownerStorageId, 0, 6) === 'home::' ||
1536
+            substr($ownerStorageId, 0, 13) === 'object::user:'
1537
+        )) {
1538
+            return true;
1539
+        }
1540
+
1541
+        // if inside the home storage, the file has to be under "/files/"
1542
+        $path = ltrim($path, '/');
1543
+        if (substr($path, 0, 6) === 'files/') {
1544
+            return true;
1545
+        }
1546
+
1547
+        return false;
1548
+    }
1549 1549
 }
Please login to merge, or discard this patch.
lib/private/CapabilitiesManager.php 1 patch
Indentation   +47 added lines, -47 removed lines patch added patch discarded remove patch
@@ -35,58 +35,58 @@
 block discarded – undo
35 35
 
36 36
 class CapabilitiesManager {
37 37
 
38
-	/** @var \Closure[] */
39
-	private $capabilities = [];
38
+    /** @var \Closure[] */
39
+    private $capabilities = [];
40 40
 
41
-	/** @var ILogger */
42
-	private $logger;
41
+    /** @var ILogger */
42
+    private $logger;
43 43
 
44
-	public function __construct(ILogger $logger) {
45
-		$this->logger = $logger;
46
-	}
44
+    public function __construct(ILogger $logger) {
45
+        $this->logger = $logger;
46
+    }
47 47
 
48
-	/**
49
-	 * Get an array of al the capabilities that are registered at this manager
48
+    /**
49
+     * Get an array of al the capabilities that are registered at this manager
50 50
      *
51
-	 * @param bool $public get public capabilities only
52
-	 * @throws \InvalidArgumentException
53
-	 * @return array
54
-	 */
55
-	public function getCapabilities(bool $public = false) : array {
56
-		$capabilities = [];
57
-		foreach($this->capabilities as $capability) {
58
-			try {
59
-				$c = $capability();
60
-			} catch (QueryException $e) {
61
-				$this->logger->logException($e, [
62
-					'message' => 'CapabilitiesManager',
63
-					'level' => ILogger::ERROR,
64
-					'app' => 'core',
65
-				]);
66
-				continue;
67
-			}
51
+     * @param bool $public get public capabilities only
52
+     * @throws \InvalidArgumentException
53
+     * @return array
54
+     */
55
+    public function getCapabilities(bool $public = false) : array {
56
+        $capabilities = [];
57
+        foreach($this->capabilities as $capability) {
58
+            try {
59
+                $c = $capability();
60
+            } catch (QueryException $e) {
61
+                $this->logger->logException($e, [
62
+                    'message' => 'CapabilitiesManager',
63
+                    'level' => ILogger::ERROR,
64
+                    'app' => 'core',
65
+                ]);
66
+                continue;
67
+            }
68 68
 
69
-			if ($c instanceof ICapability) {
70
-				if(!$public || $c instanceof IPublicCapability) {
71
-					$capabilities = array_replace_recursive($capabilities, $c->getCapabilities());
72
-				}
73
-			} else {
74
-				throw new \InvalidArgumentException('The given Capability (' . get_class($c) . ') does not implement the ICapability interface');
75
-			}
76
-		}
69
+            if ($c instanceof ICapability) {
70
+                if(!$public || $c instanceof IPublicCapability) {
71
+                    $capabilities = array_replace_recursive($capabilities, $c->getCapabilities());
72
+                }
73
+            } else {
74
+                throw new \InvalidArgumentException('The given Capability (' . get_class($c) . ') does not implement the ICapability interface');
75
+            }
76
+        }
77 77
 
78
-		return $capabilities;
79
-	}
78
+        return $capabilities;
79
+    }
80 80
 
81
-	/**
82
-	 * In order to improve lazy loading a closure can be registered which will be called in case
83
-	 * capabilities are actually requested
84
-	 *
85
-	 * $callable has to return an instance of OCP\Capabilities\ICapability
86
-	 *
87
-	 * @param \Closure $callable
88
-	 */
89
-	public function registerCapability(\Closure $callable) {
90
-		$this->capabilities[] = $callable;
91
-	}
81
+    /**
82
+     * In order to improve lazy loading a closure can be registered which will be called in case
83
+     * capabilities are actually requested
84
+     *
85
+     * $callable has to return an instance of OCP\Capabilities\ICapability
86
+     *
87
+     * @param \Closure $callable
88
+     */
89
+    public function registerCapability(\Closure $callable) {
90
+        $this->capabilities[] = $callable;
91
+    }
92 92
 }
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
@@ -52,313 +52,313 @@
 block discarded – undo
52 52
 
53 53
 class TemplateLayout extends \OC_Template {
54 54
 
55
-	private static $versionHash = '';
56
-
57
-	/**
58
-	 * @var \OCP\IConfig
59
-	 */
60
-	private $config;
61
-
62
-	/**
63
-	 * @param string $renderAs
64
-	 * @param string $appId application id
65
-	 */
66
-	public function __construct( $renderAs, $appId = '' ) {
67
-
68
-		// yes - should be injected ....
69
-		$this->config = \OC::$server->getConfig();
70
-
71
-		if(\OCP\Util::isIE()) {
72
-			\OC_Util::addStyle('ie');
73
-		}
74
-
75
-		// Decide which page we show
76
-		if($renderAs === 'user') {
77
-			parent::__construct( 'core', 'layout.user' );
78
-			if(in_array(\OC_App::getCurrentApp(), ['settings','admin', 'help']) !== false) {
79
-				$this->assign('bodyid', 'body-settings');
80
-			}else{
81
-				$this->assign('bodyid', 'body-user');
82
-			}
83
-
84
-			// Add navigation entry
85
-			$this->assign( 'application', '');
86
-			$this->assign( 'appid', $appId );
87
-			$navigation = \OC::$server->getNavigationManager()->getAll();
88
-			$this->assign( 'navigation', $navigation);
89
-			$settingsNavigation = \OC::$server->getNavigationManager()->getAll('settings');
90
-			$this->assign( 'settingsnavigation', $settingsNavigation);
91
-			foreach($navigation as $entry) {
92
-				if ($entry['active']) {
93
-					$this->assign( 'application', $entry['name'] );
94
-					break;
95
-				}
96
-			}
97
-
98
-			foreach($settingsNavigation as $entry) {
99
-				if ($entry['active']) {
100
-					$this->assign( 'application', $entry['name'] );
101
-					break;
102
-				}
103
-			}
104
-			$userDisplayName = \OC_User::getDisplayName();
105
-			$this->assign('user_displayname', $userDisplayName);
106
-			$this->assign('user_uid', \OC_User::getUser());
107
-
108
-			if (\OC_User::getUser() === false) {
109
-				$this->assign('userAvatarSet', false);
110
-			} else {
111
-				$this->assign('userAvatarSet', \OC::$server->getAvatarManager()->getAvatar(\OC_User::getUser())->exists());
112
-				$this->assign('userAvatarVersion', $this->config->getUserValue(\OC_User::getUser(), 'avatar', 'version', 0));
113
-			}
114
-
115
-			// check if app menu icons should be inverted
116
-			try {
117
-				/** @var \OCA\Theming\Util $util */
118
-				$util = \OC::$server->query(\OCA\Theming\Util::class);
119
-				$this->assign('themingInvertMenu', $util->invertTextColor(\OC::$server->getThemingDefaults()->getColorPrimary()));
120
-			} catch (\OCP\AppFramework\QueryException $e) {
121
-				$this->assign('themingInvertMenu', false);
122
-			} catch (\OCP\AutoloadNotAllowedException $e) {
123
-				$this->assign('themingInvertMenu', false);
124
-			}
125
-
126
-		} else if ($renderAs === 'error') {
127
-			parent::__construct('core', 'layout.guest', '', false);
128
-			$this->assign('bodyid', 'body-login');
129
-			$this->assign('user_displayname', '');
130
-			$this->assign('user_uid', '');
131
-		} else if ($renderAs === 'guest') {
132
-			parent::__construct('core', 'layout.guest');
133
-			\OC_Util::addStyle('guest');
134
-			$this->assign('bodyid', 'body-login');
135
-
136
-			$userDisplayName = \OC_User::getDisplayName();
137
-			$this->assign('user_displayname', $userDisplayName);
138
-			$this->assign('user_uid', \OC_User::getUser());
139
-		} else if ($renderAs === 'public') {
140
-			parent::__construct('core', 'layout.public');
141
-			$this->assign( 'appid', $appId );
142
-			$this->assign('bodyid', 'body-public');
143
-
144
-			/** @var IRegistry $subscription */
145
-			$subscription = \OC::$server->query(IRegistry::class);
146
-			$showSimpleSignup = $this->config->getSystemValueBool('simpleSignUpLink.shown', true);
147
-			if ($showSimpleSignup && $subscription->delegateHasValidSubscription()) {
148
-				$showSimpleSignup = false;
149
-			}
150
-			$this->assign('showSimpleSignUpLink', $showSimpleSignup);
151
-		} else {
152
-			parent::__construct('core', 'layout.base');
153
-
154
-		}
155
-		// Send the language and the locale to our layouts
156
-		$lang = \OC::$server->getL10NFactory()->findLanguage();
157
-		$locale = \OC::$server->getL10NFactory()->findLocale($lang);
158
-
159
-		$lang = str_replace('_', '-', $lang);
160
-		$this->assign('language', $lang);
161
-		$this->assign('locale', $locale);
162
-
163
-		if(\OC::$server->getSystemConfig()->getValue('installed', false)) {
164
-			if (empty(self::$versionHash)) {
165
-				$v = \OC_App::getAppVersions();
166
-				$v['core'] = implode('.', \OCP\Util::getVersion());
167
-				self::$versionHash = substr(md5(implode(',', $v)), 0, 8);
168
-			}
169
-		} else {
170
-			self::$versionHash = md5('not installed');
171
-		}
172
-
173
-		// Add the js files
174
-		$jsFiles = self::findJavascriptFiles(\OC_Util::$scripts);
175
-		$this->assign('jsfiles', []);
176
-		if ($this->config->getSystemValue('installed', false) && $renderAs != 'error') {
177
-			if (\OC::$server->getContentSecurityPolicyNonceManager()->browserSupportsCspV3()) {
178
-				$jsConfigHelper = new JSConfigHelper(
179
-					\OC::$server->getL10N('lib'),
180
-					\OC::$server->query(Defaults::class),
181
-					\OC::$server->getAppManager(),
182
-					\OC::$server->getSession(),
183
-					\OC::$server->getUserSession()->getUser(),
184
-					$this->config,
185
-					\OC::$server->getGroupManager(),
186
-					\OC::$server->getIniWrapper(),
187
-					\OC::$server->getURLGenerator(),
188
-					\OC::$server->getCapabilitiesManager()
189
-				);
190
-				$this->assign('inline_ocjs', $jsConfigHelper->getConfig());
191
-			} else {
192
-				$this->append('jsfiles', \OC::$server->getURLGenerator()->linkToRoute('core.OCJS.getConfig', ['v' => self::$versionHash]));
193
-			}
194
-		}
195
-		foreach($jsFiles as $info) {
196
-			$web = $info[1];
197
-			$file = $info[2];
198
-			$this->append( 'jsfiles', $web.'/'.$file . $this->getVersionHashSuffix() );
199
-		}
200
-
201
-		try {
202
-			$pathInfo = \OC::$server->getRequest()->getPathInfo();
203
-		} catch (\Exception $e) {
204
-			$pathInfo = '';
205
-		}
206
-
207
-		// Do not initialise scss appdata until we have a fully installed instance
208
-		// Do not load scss for update, errors, installation or login page
209
-		if(\OC::$server->getSystemConfig()->getValue('installed', false)
210
-			&& !\OCP\Util::needUpgrade()
211
-			&& $pathInfo !== ''
212
-			&& !preg_match('/^\/login/', $pathInfo)
213
-			&& $renderAs !== 'error'
214
-		) {
215
-			$cssFiles = self::findStylesheetFiles(\OC_Util::$styles);
216
-		} else {
217
-			// If we ignore the scss compiler,
218
-			// we need to load the guest css fallback
219
-			\OC_Util::addStyle('guest');
220
-			$cssFiles = self::findStylesheetFiles(\OC_Util::$styles, false);
221
-		}
222
-
223
-		$this->assign('cssfiles', []);
224
-		$this->assign('printcssfiles', []);
225
-		$this->assign('versionHash', self::$versionHash);
226
-		foreach($cssFiles as $info) {
227
-			$web = $info[1];
228
-			$file = $info[2];
229
-
230
-			if (substr($file, -strlen('print.css')) === 'print.css') {
231
-				$this->append( 'printcssfiles', $web.'/'.$file . $this->getVersionHashSuffix() );
232
-			} else {
233
-				$suffix = $this->getVersionHashSuffix($web, $file);
234
-
235
-				if (strpos($file, '?v=') == false) {
236
-					$this->append( 'cssfiles', $web.'/'.$file . $suffix);
237
-				} else {
238
-					$this->append( 'cssfiles', $web.'/'.$file . '-' . substr($suffix, 3));
239
-				}
240
-
241
-			}
242
-		}
243
-
244
-		/** @var InitialStateService $initialState */
245
-		$initialState = \OC::$server->query(InitialStateService::class);
246
-		$this->assign('initialStates', $initialState->getInitialStates());
247
-	}
248
-
249
-	/**
250
-	 * @param string $path
251
- 	 * @param string $file
252
-	 * @return string
253
-	 */
254
-	protected function getVersionHashSuffix($path = false, $file = false) {
255
-		if ($this->config->getSystemValue('debug', false)) {
256
-			// allows chrome workspace mapping in debug mode
257
-			return "";
258
-		}
259
-		$themingSuffix = '';
260
-		$v = [];
261
-
262
-		if ($this->config->getSystemValue('installed', false)) {
263
-			if (\OC::$server->getAppManager()->isInstalled('theming')) {
264
-				$themingSuffix = '-' . $this->config->getAppValue('theming', 'cachebuster', '0');
265
-			}
266
-			$v = \OC_App::getAppVersions();
267
-		}
268
-
269
-		// Try the webroot path for a match
270
-		if ($path !== false && $path !== '') {
271
-			$appName = $this->getAppNamefromPath($path);
272
-			if(array_key_exists($appName, $v)) {
273
-				$appVersion = $v[$appName];
274
-				return '?v=' . substr(md5($appVersion), 0, 8) . $themingSuffix;
275
-			}
276
-		}
277
-		// fallback to the file path instead
278
-		if ($file !== false && $file !== '') {
279
-			$appName = $this->getAppNamefromPath($file);
280
-			if(array_key_exists($appName, $v)) {
281
-				$appVersion = $v[$appName];
282
-				return '?v=' . substr(md5($appVersion), 0, 8) . $themingSuffix;
283
-			}
284
-		}
285
-
286
-		return '?v=' . self::$versionHash . $themingSuffix;
287
-	}
288
-
289
-	/**
290
-	 * @param array $styles
291
-	 * @return array
292
-	 */
293
-	static public function findStylesheetFiles($styles, $compileScss = true) {
294
-		// Read the selected theme from the config file
295
-		$theme = \OC_Util::getTheme();
296
-
297
-		if($compileScss) {
298
-			$SCSSCacher = \OC::$server->query(SCSSCacher::class);
299
-		} else {
300
-			$SCSSCacher = null;
301
-		}
302
-
303
-		$locator = new \OC\Template\CSSResourceLocator(
304
-			\OC::$server->getLogger(),
305
-			$theme,
306
-			[ \OC::$SERVERROOT => \OC::$WEBROOT ],
307
-			[ \OC::$SERVERROOT => \OC::$WEBROOT ],
308
-			$SCSSCacher
309
-		);
310
-		$locator->find($styles);
311
-		return $locator->getResources();
312
-	}
313
-
314
-	/**
315
-	 * @param string $path
316
-	 * @return string|boolean
317
-	 */
318
-	public function getAppNamefromPath($path) {
319
-		if ($path !== '' && is_string($path)) {
320
-			$pathParts = explode('/', $path);
321
-			if ($pathParts[0] === 'css') {
322
-				// This is a scss request
323
-				return $pathParts[1];
324
-			}
325
-			return end($pathParts);
326
-		}
327
-		return false;
328
-
329
-	}
330
-
331
-	/**
332
-	 * @param array $scripts
333
-	 * @return array
334
-	 */
335
-	static public function findJavascriptFiles($scripts) {
336
-		// Read the selected theme from the config file
337
-		$theme = \OC_Util::getTheme();
338
-
339
-		$locator = new \OC\Template\JSResourceLocator(
340
-			\OC::$server->getLogger(),
341
-			$theme,
342
-			[ \OC::$SERVERROOT => \OC::$WEBROOT ],
343
-			[ \OC::$SERVERROOT => \OC::$WEBROOT ],
344
-			\OC::$server->query(JSCombiner::class)
345
-			);
346
-		$locator->find($scripts);
347
-		return $locator->getResources();
348
-	}
349
-
350
-	/**
351
-	 * Converts the absolute file path to a relative path from \OC::$SERVERROOT
352
-	 * @param string $filePath Absolute path
353
-	 * @return string Relative path
354
-	 * @throws \Exception If $filePath is not under \OC::$SERVERROOT
355
-	 */
356
-	public static function convertToRelativePath($filePath) {
357
-		$relativePath = explode(\OC::$SERVERROOT, $filePath);
358
-		if(count($relativePath) !== 2) {
359
-			throw new \Exception('$filePath is not under the \OC::$SERVERROOT');
360
-		}
361
-
362
-		return $relativePath[1];
363
-	}
55
+    private static $versionHash = '';
56
+
57
+    /**
58
+     * @var \OCP\IConfig
59
+     */
60
+    private $config;
61
+
62
+    /**
63
+     * @param string $renderAs
64
+     * @param string $appId application id
65
+     */
66
+    public function __construct( $renderAs, $appId = '' ) {
67
+
68
+        // yes - should be injected ....
69
+        $this->config = \OC::$server->getConfig();
70
+
71
+        if(\OCP\Util::isIE()) {
72
+            \OC_Util::addStyle('ie');
73
+        }
74
+
75
+        // Decide which page we show
76
+        if($renderAs === 'user') {
77
+            parent::__construct( 'core', 'layout.user' );
78
+            if(in_array(\OC_App::getCurrentApp(), ['settings','admin', 'help']) !== false) {
79
+                $this->assign('bodyid', 'body-settings');
80
+            }else{
81
+                $this->assign('bodyid', 'body-user');
82
+            }
83
+
84
+            // Add navigation entry
85
+            $this->assign( 'application', '');
86
+            $this->assign( 'appid', $appId );
87
+            $navigation = \OC::$server->getNavigationManager()->getAll();
88
+            $this->assign( 'navigation', $navigation);
89
+            $settingsNavigation = \OC::$server->getNavigationManager()->getAll('settings');
90
+            $this->assign( 'settingsnavigation', $settingsNavigation);
91
+            foreach($navigation as $entry) {
92
+                if ($entry['active']) {
93
+                    $this->assign( 'application', $entry['name'] );
94
+                    break;
95
+                }
96
+            }
97
+
98
+            foreach($settingsNavigation as $entry) {
99
+                if ($entry['active']) {
100
+                    $this->assign( 'application', $entry['name'] );
101
+                    break;
102
+                }
103
+            }
104
+            $userDisplayName = \OC_User::getDisplayName();
105
+            $this->assign('user_displayname', $userDisplayName);
106
+            $this->assign('user_uid', \OC_User::getUser());
107
+
108
+            if (\OC_User::getUser() === false) {
109
+                $this->assign('userAvatarSet', false);
110
+            } else {
111
+                $this->assign('userAvatarSet', \OC::$server->getAvatarManager()->getAvatar(\OC_User::getUser())->exists());
112
+                $this->assign('userAvatarVersion', $this->config->getUserValue(\OC_User::getUser(), 'avatar', 'version', 0));
113
+            }
114
+
115
+            // check if app menu icons should be inverted
116
+            try {
117
+                /** @var \OCA\Theming\Util $util */
118
+                $util = \OC::$server->query(\OCA\Theming\Util::class);
119
+                $this->assign('themingInvertMenu', $util->invertTextColor(\OC::$server->getThemingDefaults()->getColorPrimary()));
120
+            } catch (\OCP\AppFramework\QueryException $e) {
121
+                $this->assign('themingInvertMenu', false);
122
+            } catch (\OCP\AutoloadNotAllowedException $e) {
123
+                $this->assign('themingInvertMenu', false);
124
+            }
125
+
126
+        } else if ($renderAs === 'error') {
127
+            parent::__construct('core', 'layout.guest', '', false);
128
+            $this->assign('bodyid', 'body-login');
129
+            $this->assign('user_displayname', '');
130
+            $this->assign('user_uid', '');
131
+        } else if ($renderAs === 'guest') {
132
+            parent::__construct('core', 'layout.guest');
133
+            \OC_Util::addStyle('guest');
134
+            $this->assign('bodyid', 'body-login');
135
+
136
+            $userDisplayName = \OC_User::getDisplayName();
137
+            $this->assign('user_displayname', $userDisplayName);
138
+            $this->assign('user_uid', \OC_User::getUser());
139
+        } else if ($renderAs === 'public') {
140
+            parent::__construct('core', 'layout.public');
141
+            $this->assign( 'appid', $appId );
142
+            $this->assign('bodyid', 'body-public');
143
+
144
+            /** @var IRegistry $subscription */
145
+            $subscription = \OC::$server->query(IRegistry::class);
146
+            $showSimpleSignup = $this->config->getSystemValueBool('simpleSignUpLink.shown', true);
147
+            if ($showSimpleSignup && $subscription->delegateHasValidSubscription()) {
148
+                $showSimpleSignup = false;
149
+            }
150
+            $this->assign('showSimpleSignUpLink', $showSimpleSignup);
151
+        } else {
152
+            parent::__construct('core', 'layout.base');
153
+
154
+        }
155
+        // Send the language and the locale to our layouts
156
+        $lang = \OC::$server->getL10NFactory()->findLanguage();
157
+        $locale = \OC::$server->getL10NFactory()->findLocale($lang);
158
+
159
+        $lang = str_replace('_', '-', $lang);
160
+        $this->assign('language', $lang);
161
+        $this->assign('locale', $locale);
162
+
163
+        if(\OC::$server->getSystemConfig()->getValue('installed', false)) {
164
+            if (empty(self::$versionHash)) {
165
+                $v = \OC_App::getAppVersions();
166
+                $v['core'] = implode('.', \OCP\Util::getVersion());
167
+                self::$versionHash = substr(md5(implode(',', $v)), 0, 8);
168
+            }
169
+        } else {
170
+            self::$versionHash = md5('not installed');
171
+        }
172
+
173
+        // Add the js files
174
+        $jsFiles = self::findJavascriptFiles(\OC_Util::$scripts);
175
+        $this->assign('jsfiles', []);
176
+        if ($this->config->getSystemValue('installed', false) && $renderAs != 'error') {
177
+            if (\OC::$server->getContentSecurityPolicyNonceManager()->browserSupportsCspV3()) {
178
+                $jsConfigHelper = new JSConfigHelper(
179
+                    \OC::$server->getL10N('lib'),
180
+                    \OC::$server->query(Defaults::class),
181
+                    \OC::$server->getAppManager(),
182
+                    \OC::$server->getSession(),
183
+                    \OC::$server->getUserSession()->getUser(),
184
+                    $this->config,
185
+                    \OC::$server->getGroupManager(),
186
+                    \OC::$server->getIniWrapper(),
187
+                    \OC::$server->getURLGenerator(),
188
+                    \OC::$server->getCapabilitiesManager()
189
+                );
190
+                $this->assign('inline_ocjs', $jsConfigHelper->getConfig());
191
+            } else {
192
+                $this->append('jsfiles', \OC::$server->getURLGenerator()->linkToRoute('core.OCJS.getConfig', ['v' => self::$versionHash]));
193
+            }
194
+        }
195
+        foreach($jsFiles as $info) {
196
+            $web = $info[1];
197
+            $file = $info[2];
198
+            $this->append( 'jsfiles', $web.'/'.$file . $this->getVersionHashSuffix() );
199
+        }
200
+
201
+        try {
202
+            $pathInfo = \OC::$server->getRequest()->getPathInfo();
203
+        } catch (\Exception $e) {
204
+            $pathInfo = '';
205
+        }
206
+
207
+        // Do not initialise scss appdata until we have a fully installed instance
208
+        // Do not load scss for update, errors, installation or login page
209
+        if(\OC::$server->getSystemConfig()->getValue('installed', false)
210
+            && !\OCP\Util::needUpgrade()
211
+            && $pathInfo !== ''
212
+            && !preg_match('/^\/login/', $pathInfo)
213
+            && $renderAs !== 'error'
214
+        ) {
215
+            $cssFiles = self::findStylesheetFiles(\OC_Util::$styles);
216
+        } else {
217
+            // If we ignore the scss compiler,
218
+            // we need to load the guest css fallback
219
+            \OC_Util::addStyle('guest');
220
+            $cssFiles = self::findStylesheetFiles(\OC_Util::$styles, false);
221
+        }
222
+
223
+        $this->assign('cssfiles', []);
224
+        $this->assign('printcssfiles', []);
225
+        $this->assign('versionHash', self::$versionHash);
226
+        foreach($cssFiles as $info) {
227
+            $web = $info[1];
228
+            $file = $info[2];
229
+
230
+            if (substr($file, -strlen('print.css')) === 'print.css') {
231
+                $this->append( 'printcssfiles', $web.'/'.$file . $this->getVersionHashSuffix() );
232
+            } else {
233
+                $suffix = $this->getVersionHashSuffix($web, $file);
234
+
235
+                if (strpos($file, '?v=') == false) {
236
+                    $this->append( 'cssfiles', $web.'/'.$file . $suffix);
237
+                } else {
238
+                    $this->append( 'cssfiles', $web.'/'.$file . '-' . substr($suffix, 3));
239
+                }
240
+
241
+            }
242
+        }
243
+
244
+        /** @var InitialStateService $initialState */
245
+        $initialState = \OC::$server->query(InitialStateService::class);
246
+        $this->assign('initialStates', $initialState->getInitialStates());
247
+    }
248
+
249
+    /**
250
+     * @param string $path
251
+     * @param string $file
252
+     * @return string
253
+     */
254
+    protected function getVersionHashSuffix($path = false, $file = false) {
255
+        if ($this->config->getSystemValue('debug', false)) {
256
+            // allows chrome workspace mapping in debug mode
257
+            return "";
258
+        }
259
+        $themingSuffix = '';
260
+        $v = [];
261
+
262
+        if ($this->config->getSystemValue('installed', false)) {
263
+            if (\OC::$server->getAppManager()->isInstalled('theming')) {
264
+                $themingSuffix = '-' . $this->config->getAppValue('theming', 'cachebuster', '0');
265
+            }
266
+            $v = \OC_App::getAppVersions();
267
+        }
268
+
269
+        // Try the webroot path for a match
270
+        if ($path !== false && $path !== '') {
271
+            $appName = $this->getAppNamefromPath($path);
272
+            if(array_key_exists($appName, $v)) {
273
+                $appVersion = $v[$appName];
274
+                return '?v=' . substr(md5($appVersion), 0, 8) . $themingSuffix;
275
+            }
276
+        }
277
+        // fallback to the file path instead
278
+        if ($file !== false && $file !== '') {
279
+            $appName = $this->getAppNamefromPath($file);
280
+            if(array_key_exists($appName, $v)) {
281
+                $appVersion = $v[$appName];
282
+                return '?v=' . substr(md5($appVersion), 0, 8) . $themingSuffix;
283
+            }
284
+        }
285
+
286
+        return '?v=' . self::$versionHash . $themingSuffix;
287
+    }
288
+
289
+    /**
290
+     * @param array $styles
291
+     * @return array
292
+     */
293
+    static public function findStylesheetFiles($styles, $compileScss = true) {
294
+        // Read the selected theme from the config file
295
+        $theme = \OC_Util::getTheme();
296
+
297
+        if($compileScss) {
298
+            $SCSSCacher = \OC::$server->query(SCSSCacher::class);
299
+        } else {
300
+            $SCSSCacher = null;
301
+        }
302
+
303
+        $locator = new \OC\Template\CSSResourceLocator(
304
+            \OC::$server->getLogger(),
305
+            $theme,
306
+            [ \OC::$SERVERROOT => \OC::$WEBROOT ],
307
+            [ \OC::$SERVERROOT => \OC::$WEBROOT ],
308
+            $SCSSCacher
309
+        );
310
+        $locator->find($styles);
311
+        return $locator->getResources();
312
+    }
313
+
314
+    /**
315
+     * @param string $path
316
+     * @return string|boolean
317
+     */
318
+    public function getAppNamefromPath($path) {
319
+        if ($path !== '' && is_string($path)) {
320
+            $pathParts = explode('/', $path);
321
+            if ($pathParts[0] === 'css') {
322
+                // This is a scss request
323
+                return $pathParts[1];
324
+            }
325
+            return end($pathParts);
326
+        }
327
+        return false;
328
+
329
+    }
330
+
331
+    /**
332
+     * @param array $scripts
333
+     * @return array
334
+     */
335
+    static public function findJavascriptFiles($scripts) {
336
+        // Read the selected theme from the config file
337
+        $theme = \OC_Util::getTheme();
338
+
339
+        $locator = new \OC\Template\JSResourceLocator(
340
+            \OC::$server->getLogger(),
341
+            $theme,
342
+            [ \OC::$SERVERROOT => \OC::$WEBROOT ],
343
+            [ \OC::$SERVERROOT => \OC::$WEBROOT ],
344
+            \OC::$server->query(JSCombiner::class)
345
+            );
346
+        $locator->find($scripts);
347
+        return $locator->getResources();
348
+    }
349
+
350
+    /**
351
+     * Converts the absolute file path to a relative path from \OC::$SERVERROOT
352
+     * @param string $filePath Absolute path
353
+     * @return string Relative path
354
+     * @throws \Exception If $filePath is not under \OC::$SERVERROOT
355
+     */
356
+    public static function convertToRelativePath($filePath) {
357
+        $relativePath = explode(\OC::$SERVERROOT, $filePath);
358
+        if(count($relativePath) !== 2) {
359
+            throw new \Exception('$filePath is not under the \OC::$SERVERROOT');
360
+        }
361
+
362
+        return $relativePath[1];
363
+    }
364 364
 }
Please login to merge, or discard this patch.
lib/private/Group/Backend.php 1 patch
Indentation   +93 added lines, -93 removed lines patch added patch discarded remove patch
@@ -28,107 +28,107 @@
 block discarded – undo
28 28
  * Abstract base class for user management
29 29
  */
30 30
 abstract class Backend implements \OCP\GroupInterface {
31
-	/**
32
-	 * error code for functions not provided by the group backend
33
-	 */
34
-	const NOT_IMPLEMENTED = -501;
31
+    /**
32
+     * error code for functions not provided by the group backend
33
+     */
34
+    const NOT_IMPLEMENTED = -501;
35 35
 
36
-	protected $possibleActions = [
37
-		self::CREATE_GROUP => 'createGroup',
38
-		self::DELETE_GROUP => 'deleteGroup',
39
-		self::ADD_TO_GROUP => 'addToGroup',
40
-		self::REMOVE_FROM_GOUP => 'removeFromGroup',
41
-		self::COUNT_USERS => 'countUsersInGroup',
42
-		self::GROUP_DETAILS => 'getGroupDetails',
43
-		self::IS_ADMIN => 'isAdmin',
44
-	];
36
+    protected $possibleActions = [
37
+        self::CREATE_GROUP => 'createGroup',
38
+        self::DELETE_GROUP => 'deleteGroup',
39
+        self::ADD_TO_GROUP => 'addToGroup',
40
+        self::REMOVE_FROM_GOUP => 'removeFromGroup',
41
+        self::COUNT_USERS => 'countUsersInGroup',
42
+        self::GROUP_DETAILS => 'getGroupDetails',
43
+        self::IS_ADMIN => 'isAdmin',
44
+    ];
45 45
 
46
-	/**
47
-	* Get all supported actions
48
-	* @return int bitwise-or'ed actions
49
-	*
50
-	* Returns the supported actions as int to be
51
-	* compared with \OC\Group\Backend::CREATE_GROUP etc.
52
-	*/
53
-	public function getSupportedActions() {
54
-		$actions = 0;
55
-		foreach($this->possibleActions AS $action => $methodName) {
56
-			if(method_exists($this, $methodName)) {
57
-				$actions |= $action;
58
-			}
59
-		}
46
+    /**
47
+     * Get all supported actions
48
+     * @return int bitwise-or'ed actions
49
+     *
50
+     * Returns the supported actions as int to be
51
+     * compared with \OC\Group\Backend::CREATE_GROUP etc.
52
+     */
53
+    public function getSupportedActions() {
54
+        $actions = 0;
55
+        foreach($this->possibleActions AS $action => $methodName) {
56
+            if(method_exists($this, $methodName)) {
57
+                $actions |= $action;
58
+            }
59
+        }
60 60
 
61
-		return $actions;
62
-	}
61
+        return $actions;
62
+    }
63 63
 
64
-	/**
65
-	* Check if backend implements actions
66
-	* @param int $actions bitwise-or'ed actions
67
-	* @return bool
68
-	*
69
-	* Returns the supported actions as int to be
70
-	* compared with \OC\Group\Backend::CREATE_GROUP etc.
71
-	*/
72
-	public function implementsActions($actions) {
73
-		return (bool)($this->getSupportedActions() & $actions);
74
-	}
64
+    /**
65
+     * Check if backend implements actions
66
+     * @param int $actions bitwise-or'ed actions
67
+     * @return bool
68
+     *
69
+     * Returns the supported actions as int to be
70
+     * compared with \OC\Group\Backend::CREATE_GROUP etc.
71
+     */
72
+    public function implementsActions($actions) {
73
+        return (bool)($this->getSupportedActions() & $actions);
74
+    }
75 75
 
76
-	/**
77
-	 * is user in group?
78
-	 * @param string $uid uid of the user
79
-	 * @param string $gid gid of the group
80
-	 * @return bool
81
-	 *
82
-	 * Checks whether the user is member of a group or not.
83
-	 */
84
-	public function inGroup($uid, $gid) {
85
-		return in_array($gid, $this->getUserGroups($uid));
86
-	}
76
+    /**
77
+     * is user in group?
78
+     * @param string $uid uid of the user
79
+     * @param string $gid gid of the group
80
+     * @return bool
81
+     *
82
+     * Checks whether the user is member of a group or not.
83
+     */
84
+    public function inGroup($uid, $gid) {
85
+        return in_array($gid, $this->getUserGroups($uid));
86
+    }
87 87
 
88
-	/**
89
-	 * Get all groups a user belongs to
90
-	 * @param string $uid Name of the user
91
-	 * @return array an array of group names
92
-	 *
93
-	 * This function fetches all groups a user belongs to. It does not check
94
-	 * if the user exists at all.
95
-	 */
96
-	public function getUserGroups($uid) {
97
-		return [];
98
-	}
88
+    /**
89
+     * Get all groups a user belongs to
90
+     * @param string $uid Name of the user
91
+     * @return array an array of group names
92
+     *
93
+     * This function fetches all groups a user belongs to. It does not check
94
+     * if the user exists at all.
95
+     */
96
+    public function getUserGroups($uid) {
97
+        return [];
98
+    }
99 99
 
100
-	/**
101
-	 * get a list of all groups
102
-	 * @param string $search
103
-	 * @param int $limit
104
-	 * @param int $offset
105
-	 * @return array an array of group names
106
-	 *
107
-	 * Returns a list with all groups
108
-	 */
100
+    /**
101
+     * get a list of all groups
102
+     * @param string $search
103
+     * @param int $limit
104
+     * @param int $offset
105
+     * @return array an array of group names
106
+     *
107
+     * Returns a list with all groups
108
+     */
109 109
 
110
-	public function getGroups($search = '', $limit = -1, $offset = 0) {
111
-		return [];
112
-	}
110
+    public function getGroups($search = '', $limit = -1, $offset = 0) {
111
+        return [];
112
+    }
113 113
 
114
-	/**
115
-	 * check if a group exists
116
-	 * @param string $gid
117
-	 * @return bool
118
-	 */
119
-	public function groupExists($gid) {
120
-		return in_array($gid, $this->getGroups($gid, 1));
121
-	}
114
+    /**
115
+     * check if a group exists
116
+     * @param string $gid
117
+     * @return bool
118
+     */
119
+    public function groupExists($gid) {
120
+        return in_array($gid, $this->getGroups($gid, 1));
121
+    }
122 122
 
123
-	/**
124
-	 * get a list of all users in a group
125
-	 * @param string $gid
126
-	 * @param string $search
127
-	 * @param int $limit
128
-	 * @param int $offset
129
-	 * @return array an array of user ids
130
-	 */
131
-	public function usersInGroup($gid, $search = '', $limit = -1, $offset = 0) {
132
-		return [];
133
-	}
123
+    /**
124
+     * get a list of all users in a group
125
+     * @param string $gid
126
+     * @param string $search
127
+     * @param int $limit
128
+     * @param int $offset
129
+     * @return array an array of user ids
130
+     */
131
+    public function usersInGroup($gid, $search = '', $limit = -1, $offset = 0) {
132
+        return [];
133
+    }
134 134
 }
Please login to merge, or discard this patch.
lib/private/Group/Manager.php 1 patch
Indentation   +349 added lines, -349 removed lines patch added patch discarded remove patch
@@ -63,353 +63,353 @@
 block discarded – undo
63 63
  * @package OC\Group
64 64
  */
65 65
 class Manager extends PublicEmitter implements IGroupManager {
66
-	/** @var GroupInterface[] */
67
-	private $backends = [];
68
-
69
-	/** @var \OC\User\Manager */
70
-	private $userManager;
71
-	/** @var EventDispatcherInterface */
72
-	private $dispatcher;
73
-	/** @var ILogger */
74
-	private $logger;
75
-
76
-	/** @var \OC\Group\Group[] */
77
-	private $cachedGroups = [];
78
-
79
-	/** @var \OC\Group\Group[] */
80
-	private $cachedUserGroups = [];
81
-
82
-	/** @var \OC\SubAdmin */
83
-	private $subAdmin = null;
84
-
85
-	/**
86
-	 * @param \OC\User\Manager $userManager
87
-	 * @param EventDispatcherInterface $dispatcher
88
-	 * @param ILogger $logger
89
-	 */
90
-	public function __construct(\OC\User\Manager $userManager,
91
-								EventDispatcherInterface $dispatcher,
92
-								ILogger $logger) {
93
-		$this->userManager = $userManager;
94
-		$this->dispatcher = $dispatcher;
95
-		$this->logger = $logger;
96
-
97
-		$cachedGroups = &$this->cachedGroups;
98
-		$cachedUserGroups = &$this->cachedUserGroups;
99
-		$this->listen('\OC\Group', 'postDelete', function ($group) use (&$cachedGroups, &$cachedUserGroups) {
100
-			/**
101
-			 * @var \OC\Group\Group $group
102
-			 */
103
-			unset($cachedGroups[$group->getGID()]);
104
-			$cachedUserGroups = [];
105
-		});
106
-		$this->listen('\OC\Group', 'postAddUser', function ($group) use (&$cachedUserGroups) {
107
-			/**
108
-			 * @var \OC\Group\Group $group
109
-			 */
110
-			$cachedUserGroups = [];
111
-		});
112
-		$this->listen('\OC\Group', 'postRemoveUser', function ($group) use (&$cachedUserGroups) {
113
-			/**
114
-			 * @var \OC\Group\Group $group
115
-			 */
116
-			$cachedUserGroups = [];
117
-		});
118
-	}
119
-
120
-	/**
121
-	 * Checks whether a given backend is used
122
-	 *
123
-	 * @param string $backendClass Full classname including complete namespace
124
-	 * @return bool
125
-	 */
126
-	public function isBackendUsed($backendClass) {
127
-		$backendClass = strtolower(ltrim($backendClass, '\\'));
128
-
129
-		foreach ($this->backends as $backend) {
130
-			if (strtolower(get_class($backend)) === $backendClass) {
131
-				return true;
132
-			}
133
-		}
134
-
135
-		return false;
136
-	}
137
-
138
-	/**
139
-	 * @param \OCP\GroupInterface $backend
140
-	 */
141
-	public function addBackend($backend) {
142
-		$this->backends[] = $backend;
143
-		$this->clearCaches();
144
-	}
145
-
146
-	public function clearBackends() {
147
-		$this->backends = [];
148
-		$this->clearCaches();
149
-	}
150
-
151
-	/**
152
-	 * Get the active backends
153
-	 *
154
-	 * @return \OCP\GroupInterface[]
155
-	 */
156
-	public function getBackends() {
157
-		return $this->backends;
158
-	}
159
-
160
-
161
-	protected function clearCaches() {
162
-		$this->cachedGroups = [];
163
-		$this->cachedUserGroups = [];
164
-	}
165
-
166
-	/**
167
-	 * @param string $gid
168
-	 * @return IGroup|null
169
-	 */
170
-	public function get($gid) {
171
-		if (isset($this->cachedGroups[$gid])) {
172
-			return $this->cachedGroups[$gid];
173
-		}
174
-		return $this->getGroupObject($gid);
175
-	}
176
-
177
-	/**
178
-	 * @param string $gid
179
-	 * @param string $displayName
180
-	 * @return \OCP\IGroup|null
181
-	 */
182
-	protected function getGroupObject($gid, $displayName = null) {
183
-		$backends = [];
184
-		foreach ($this->backends as $backend) {
185
-			if ($backend->implementsActions(Backend::GROUP_DETAILS)) {
186
-				$groupData = $backend->getGroupDetails($gid);
187
-				if (is_array($groupData) && !empty($groupData)) {
188
-					// take the display name from the first backend that has a non-null one
189
-					if (is_null($displayName) && isset($groupData['displayName'])) {
190
-						$displayName = $groupData['displayName'];
191
-					}
192
-					$backends[] = $backend;
193
-				}
194
-			} else if ($backend->groupExists($gid)) {
195
-				$backends[] = $backend;
196
-			}
197
-		}
198
-		if (count($backends) === 0) {
199
-			return null;
200
-		}
201
-		$this->cachedGroups[$gid] = new Group($gid, $backends, $this->dispatcher, $this->userManager, $this, $displayName);
202
-		return $this->cachedGroups[$gid];
203
-	}
204
-
205
-	/**
206
-	 * @param string $gid
207
-	 * @return bool
208
-	 */
209
-	public function groupExists($gid) {
210
-		return $this->get($gid) instanceof IGroup;
211
-	}
212
-
213
-	/**
214
-	 * @param string $gid
215
-	 * @return IGroup|null
216
-	 */
217
-	public function createGroup($gid) {
218
-		if ($gid === '' || $gid === null) {
219
-			return null;
220
-		} else if ($group = $this->get($gid)) {
221
-			return $group;
222
-		} else {
223
-			$this->emit('\OC\Group', 'preCreate', [$gid]);
224
-			foreach ($this->backends as $backend) {
225
-				if ($backend->implementsActions(Backend::CREATE_GROUP)) {
226
-					if ($backend->createGroup($gid)) {
227
-						$group = $this->getGroupObject($gid);
228
-						$this->emit('\OC\Group', 'postCreate', [$group]);
229
-						return $group;
230
-					}
231
-				}
232
-			}
233
-			return null;
234
-		}
235
-	}
236
-
237
-	/**
238
-	 * @param string $search
239
-	 * @param int $limit
240
-	 * @param int $offset
241
-	 * @return \OC\Group\Group[]
242
-	 */
243
-	public function search($search, $limit = null, $offset = null) {
244
-		$groups = [];
245
-		foreach ($this->backends as $backend) {
246
-			$groupIds = $backend->getGroups($search, $limit, $offset);
247
-			foreach ($groupIds as $groupId) {
248
-				$aGroup = $this->get($groupId);
249
-				if ($aGroup instanceof IGroup) {
250
-					$groups[$groupId] = $aGroup;
251
-				} else {
252
-					$this->logger->debug('Group "' . $groupId . '" was returned by search but not found through direct access', ['app' => 'core']);
253
-				}
254
-			}
255
-			if (!is_null($limit) and $limit <= 0) {
256
-				return array_values($groups);
257
-			}
258
-		}
259
-		return array_values($groups);
260
-	}
261
-
262
-	/**
263
-	 * @param IUser|null $user
264
-	 * @return \OC\Group\Group[]
265
-	 */
266
-	public function getUserGroups(IUser $user = null) {
267
-		if (!$user instanceof IUser) {
268
-			return [];
269
-		}
270
-		return $this->getUserIdGroups($user->getUID());
271
-	}
272
-
273
-	/**
274
-	 * @param string $uid the user id
275
-	 * @return \OC\Group\Group[]
276
-	 */
277
-	public function getUserIdGroups($uid) {
278
-		if (isset($this->cachedUserGroups[$uid])) {
279
-			return $this->cachedUserGroups[$uid];
280
-		}
281
-		$groups = [];
282
-		foreach ($this->backends as $backend) {
283
-			$groupIds = $backend->getUserGroups($uid);
284
-			if (is_array($groupIds)) {
285
-				foreach ($groupIds as $groupId) {
286
-					$aGroup = $this->get($groupId);
287
-					if ($aGroup instanceof IGroup) {
288
-						$groups[$groupId] = $aGroup;
289
-					} else {
290
-						$this->logger->debug('User "' . $uid . '" belongs to deleted group: "' . $groupId . '"', ['app' => 'core']);
291
-					}
292
-				}
293
-			}
294
-		}
295
-		$this->cachedUserGroups[$uid] = $groups;
296
-		return $this->cachedUserGroups[$uid];
297
-	}
298
-
299
-	/**
300
-	 * Checks if a userId is in the admin group
301
-	 *
302
-	 * @param string $userId
303
-	 * @return bool if admin
304
-	 */
305
-	public function isAdmin($userId) {
306
-		foreach ($this->backends as $backend) {
307
-			if ($backend->implementsActions(Backend::IS_ADMIN) && $backend->isAdmin($userId)) {
308
-				return true;
309
-			}
310
-		}
311
-		return $this->isInGroup($userId, 'admin');
312
-	}
313
-
314
-	/**
315
-	 * Checks if a userId is in a group
316
-	 *
317
-	 * @param string $userId
318
-	 * @param string $group
319
-	 * @return bool if in group
320
-	 */
321
-	public function isInGroup($userId, $group) {
322
-		return array_key_exists($group, $this->getUserIdGroups($userId));
323
-	}
324
-
325
-	/**
326
-	 * get a list of group ids for a user
327
-	 *
328
-	 * @param IUser $user
329
-	 * @return array with group ids
330
-	 */
331
-	public function getUserGroupIds(IUser $user) {
332
-		return array_map(function ($value) {
333
-			return (string)$value;
334
-		}, array_keys($this->getUserGroups($user)));
335
-	}
336
-
337
-	/**
338
-	 * get an array of groupid and displayName for a user
339
-	 *
340
-	 * @param IUser $user
341
-	 * @return array ['displayName' => displayname]
342
-	 */
343
-	public function getUserGroupNames(IUser $user) {
344
-		return array_map(function ($group) {
345
-			return ['displayName' => $group->getDisplayName()];
346
-		}, $this->getUserGroups($user));
347
-	}
348
-
349
-	/**
350
-	 * get a list of all display names in a group
351
-	 *
352
-	 * @param string $gid
353
-	 * @param string $search
354
-	 * @param int $limit
355
-	 * @param int $offset
356
-	 * @return array an array of display names (value) and user ids (key)
357
-	 */
358
-	public function displayNamesInGroup($gid, $search = '', $limit = -1, $offset = 0) {
359
-		$group = $this->get($gid);
360
-		if (is_null($group)) {
361
-			return [];
362
-		}
363
-
364
-		$search = trim($search);
365
-		$groupUsers = [];
366
-
367
-		if (!empty($search)) {
368
-			// only user backends have the capability to do a complex search for users
369
-			$searchOffset = 0;
370
-			$searchLimit = $limit * 100;
371
-			if ($limit === -1) {
372
-				$searchLimit = 500;
373
-			}
374
-
375
-			do {
376
-				$filteredUsers = $this->userManager->searchDisplayName($search, $searchLimit, $searchOffset);
377
-				foreach ($filteredUsers as $filteredUser) {
378
-					if ($group->inGroup($filteredUser)) {
379
-						$groupUsers[] = $filteredUser;
380
-					}
381
-				}
382
-				$searchOffset += $searchLimit;
383
-			} while (count($groupUsers) < $searchLimit + $offset && count($filteredUsers) >= $searchLimit);
384
-
385
-			if ($limit === -1) {
386
-				$groupUsers = array_slice($groupUsers, $offset);
387
-			} else {
388
-				$groupUsers = array_slice($groupUsers, $offset, $limit);
389
-			}
390
-		} else {
391
-			$groupUsers = $group->searchUsers('', $limit, $offset);
392
-		}
393
-
394
-		$matchingUsers = [];
395
-		foreach ($groupUsers as $groupUser) {
396
-			$matchingUsers[(string) $groupUser->getUID()] = $groupUser->getDisplayName();
397
-		}
398
-		return $matchingUsers;
399
-	}
400
-
401
-	/**
402
-	 * @return \OC\SubAdmin
403
-	 */
404
-	public function getSubAdmin() {
405
-		if (!$this->subAdmin) {
406
-			$this->subAdmin = new \OC\SubAdmin(
407
-				$this->userManager,
408
-				$this,
409
-				\OC::$server->getDatabaseConnection()
410
-			);
411
-		}
412
-
413
-		return $this->subAdmin;
414
-	}
66
+    /** @var GroupInterface[] */
67
+    private $backends = [];
68
+
69
+    /** @var \OC\User\Manager */
70
+    private $userManager;
71
+    /** @var EventDispatcherInterface */
72
+    private $dispatcher;
73
+    /** @var ILogger */
74
+    private $logger;
75
+
76
+    /** @var \OC\Group\Group[] */
77
+    private $cachedGroups = [];
78
+
79
+    /** @var \OC\Group\Group[] */
80
+    private $cachedUserGroups = [];
81
+
82
+    /** @var \OC\SubAdmin */
83
+    private $subAdmin = null;
84
+
85
+    /**
86
+     * @param \OC\User\Manager $userManager
87
+     * @param EventDispatcherInterface $dispatcher
88
+     * @param ILogger $logger
89
+     */
90
+    public function __construct(\OC\User\Manager $userManager,
91
+                                EventDispatcherInterface $dispatcher,
92
+                                ILogger $logger) {
93
+        $this->userManager = $userManager;
94
+        $this->dispatcher = $dispatcher;
95
+        $this->logger = $logger;
96
+
97
+        $cachedGroups = &$this->cachedGroups;
98
+        $cachedUserGroups = &$this->cachedUserGroups;
99
+        $this->listen('\OC\Group', 'postDelete', function ($group) use (&$cachedGroups, &$cachedUserGroups) {
100
+            /**
101
+             * @var \OC\Group\Group $group
102
+             */
103
+            unset($cachedGroups[$group->getGID()]);
104
+            $cachedUserGroups = [];
105
+        });
106
+        $this->listen('\OC\Group', 'postAddUser', function ($group) use (&$cachedUserGroups) {
107
+            /**
108
+             * @var \OC\Group\Group $group
109
+             */
110
+            $cachedUserGroups = [];
111
+        });
112
+        $this->listen('\OC\Group', 'postRemoveUser', function ($group) use (&$cachedUserGroups) {
113
+            /**
114
+             * @var \OC\Group\Group $group
115
+             */
116
+            $cachedUserGroups = [];
117
+        });
118
+    }
119
+
120
+    /**
121
+     * Checks whether a given backend is used
122
+     *
123
+     * @param string $backendClass Full classname including complete namespace
124
+     * @return bool
125
+     */
126
+    public function isBackendUsed($backendClass) {
127
+        $backendClass = strtolower(ltrim($backendClass, '\\'));
128
+
129
+        foreach ($this->backends as $backend) {
130
+            if (strtolower(get_class($backend)) === $backendClass) {
131
+                return true;
132
+            }
133
+        }
134
+
135
+        return false;
136
+    }
137
+
138
+    /**
139
+     * @param \OCP\GroupInterface $backend
140
+     */
141
+    public function addBackend($backend) {
142
+        $this->backends[] = $backend;
143
+        $this->clearCaches();
144
+    }
145
+
146
+    public function clearBackends() {
147
+        $this->backends = [];
148
+        $this->clearCaches();
149
+    }
150
+
151
+    /**
152
+     * Get the active backends
153
+     *
154
+     * @return \OCP\GroupInterface[]
155
+     */
156
+    public function getBackends() {
157
+        return $this->backends;
158
+    }
159
+
160
+
161
+    protected function clearCaches() {
162
+        $this->cachedGroups = [];
163
+        $this->cachedUserGroups = [];
164
+    }
165
+
166
+    /**
167
+     * @param string $gid
168
+     * @return IGroup|null
169
+     */
170
+    public function get($gid) {
171
+        if (isset($this->cachedGroups[$gid])) {
172
+            return $this->cachedGroups[$gid];
173
+        }
174
+        return $this->getGroupObject($gid);
175
+    }
176
+
177
+    /**
178
+     * @param string $gid
179
+     * @param string $displayName
180
+     * @return \OCP\IGroup|null
181
+     */
182
+    protected function getGroupObject($gid, $displayName = null) {
183
+        $backends = [];
184
+        foreach ($this->backends as $backend) {
185
+            if ($backend->implementsActions(Backend::GROUP_DETAILS)) {
186
+                $groupData = $backend->getGroupDetails($gid);
187
+                if (is_array($groupData) && !empty($groupData)) {
188
+                    // take the display name from the first backend that has a non-null one
189
+                    if (is_null($displayName) && isset($groupData['displayName'])) {
190
+                        $displayName = $groupData['displayName'];
191
+                    }
192
+                    $backends[] = $backend;
193
+                }
194
+            } else if ($backend->groupExists($gid)) {
195
+                $backends[] = $backend;
196
+            }
197
+        }
198
+        if (count($backends) === 0) {
199
+            return null;
200
+        }
201
+        $this->cachedGroups[$gid] = new Group($gid, $backends, $this->dispatcher, $this->userManager, $this, $displayName);
202
+        return $this->cachedGroups[$gid];
203
+    }
204
+
205
+    /**
206
+     * @param string $gid
207
+     * @return bool
208
+     */
209
+    public function groupExists($gid) {
210
+        return $this->get($gid) instanceof IGroup;
211
+    }
212
+
213
+    /**
214
+     * @param string $gid
215
+     * @return IGroup|null
216
+     */
217
+    public function createGroup($gid) {
218
+        if ($gid === '' || $gid === null) {
219
+            return null;
220
+        } else if ($group = $this->get($gid)) {
221
+            return $group;
222
+        } else {
223
+            $this->emit('\OC\Group', 'preCreate', [$gid]);
224
+            foreach ($this->backends as $backend) {
225
+                if ($backend->implementsActions(Backend::CREATE_GROUP)) {
226
+                    if ($backend->createGroup($gid)) {
227
+                        $group = $this->getGroupObject($gid);
228
+                        $this->emit('\OC\Group', 'postCreate', [$group]);
229
+                        return $group;
230
+                    }
231
+                }
232
+            }
233
+            return null;
234
+        }
235
+    }
236
+
237
+    /**
238
+     * @param string $search
239
+     * @param int $limit
240
+     * @param int $offset
241
+     * @return \OC\Group\Group[]
242
+     */
243
+    public function search($search, $limit = null, $offset = null) {
244
+        $groups = [];
245
+        foreach ($this->backends as $backend) {
246
+            $groupIds = $backend->getGroups($search, $limit, $offset);
247
+            foreach ($groupIds as $groupId) {
248
+                $aGroup = $this->get($groupId);
249
+                if ($aGroup instanceof IGroup) {
250
+                    $groups[$groupId] = $aGroup;
251
+                } else {
252
+                    $this->logger->debug('Group "' . $groupId . '" was returned by search but not found through direct access', ['app' => 'core']);
253
+                }
254
+            }
255
+            if (!is_null($limit) and $limit <= 0) {
256
+                return array_values($groups);
257
+            }
258
+        }
259
+        return array_values($groups);
260
+    }
261
+
262
+    /**
263
+     * @param IUser|null $user
264
+     * @return \OC\Group\Group[]
265
+     */
266
+    public function getUserGroups(IUser $user = null) {
267
+        if (!$user instanceof IUser) {
268
+            return [];
269
+        }
270
+        return $this->getUserIdGroups($user->getUID());
271
+    }
272
+
273
+    /**
274
+     * @param string $uid the user id
275
+     * @return \OC\Group\Group[]
276
+     */
277
+    public function getUserIdGroups($uid) {
278
+        if (isset($this->cachedUserGroups[$uid])) {
279
+            return $this->cachedUserGroups[$uid];
280
+        }
281
+        $groups = [];
282
+        foreach ($this->backends as $backend) {
283
+            $groupIds = $backend->getUserGroups($uid);
284
+            if (is_array($groupIds)) {
285
+                foreach ($groupIds as $groupId) {
286
+                    $aGroup = $this->get($groupId);
287
+                    if ($aGroup instanceof IGroup) {
288
+                        $groups[$groupId] = $aGroup;
289
+                    } else {
290
+                        $this->logger->debug('User "' . $uid . '" belongs to deleted group: "' . $groupId . '"', ['app' => 'core']);
291
+                    }
292
+                }
293
+            }
294
+        }
295
+        $this->cachedUserGroups[$uid] = $groups;
296
+        return $this->cachedUserGroups[$uid];
297
+    }
298
+
299
+    /**
300
+     * Checks if a userId is in the admin group
301
+     *
302
+     * @param string $userId
303
+     * @return bool if admin
304
+     */
305
+    public function isAdmin($userId) {
306
+        foreach ($this->backends as $backend) {
307
+            if ($backend->implementsActions(Backend::IS_ADMIN) && $backend->isAdmin($userId)) {
308
+                return true;
309
+            }
310
+        }
311
+        return $this->isInGroup($userId, 'admin');
312
+    }
313
+
314
+    /**
315
+     * Checks if a userId is in a group
316
+     *
317
+     * @param string $userId
318
+     * @param string $group
319
+     * @return bool if in group
320
+     */
321
+    public function isInGroup($userId, $group) {
322
+        return array_key_exists($group, $this->getUserIdGroups($userId));
323
+    }
324
+
325
+    /**
326
+     * get a list of group ids for a user
327
+     *
328
+     * @param IUser $user
329
+     * @return array with group ids
330
+     */
331
+    public function getUserGroupIds(IUser $user) {
332
+        return array_map(function ($value) {
333
+            return (string)$value;
334
+        }, array_keys($this->getUserGroups($user)));
335
+    }
336
+
337
+    /**
338
+     * get an array of groupid and displayName for a user
339
+     *
340
+     * @param IUser $user
341
+     * @return array ['displayName' => displayname]
342
+     */
343
+    public function getUserGroupNames(IUser $user) {
344
+        return array_map(function ($group) {
345
+            return ['displayName' => $group->getDisplayName()];
346
+        }, $this->getUserGroups($user));
347
+    }
348
+
349
+    /**
350
+     * get a list of all display names in a group
351
+     *
352
+     * @param string $gid
353
+     * @param string $search
354
+     * @param int $limit
355
+     * @param int $offset
356
+     * @return array an array of display names (value) and user ids (key)
357
+     */
358
+    public function displayNamesInGroup($gid, $search = '', $limit = -1, $offset = 0) {
359
+        $group = $this->get($gid);
360
+        if (is_null($group)) {
361
+            return [];
362
+        }
363
+
364
+        $search = trim($search);
365
+        $groupUsers = [];
366
+
367
+        if (!empty($search)) {
368
+            // only user backends have the capability to do a complex search for users
369
+            $searchOffset = 0;
370
+            $searchLimit = $limit * 100;
371
+            if ($limit === -1) {
372
+                $searchLimit = 500;
373
+            }
374
+
375
+            do {
376
+                $filteredUsers = $this->userManager->searchDisplayName($search, $searchLimit, $searchOffset);
377
+                foreach ($filteredUsers as $filteredUser) {
378
+                    if ($group->inGroup($filteredUser)) {
379
+                        $groupUsers[] = $filteredUser;
380
+                    }
381
+                }
382
+                $searchOffset += $searchLimit;
383
+            } while (count($groupUsers) < $searchLimit + $offset && count($filteredUsers) >= $searchLimit);
384
+
385
+            if ($limit === -1) {
386
+                $groupUsers = array_slice($groupUsers, $offset);
387
+            } else {
388
+                $groupUsers = array_slice($groupUsers, $offset, $limit);
389
+            }
390
+        } else {
391
+            $groupUsers = $group->searchUsers('', $limit, $offset);
392
+        }
393
+
394
+        $matchingUsers = [];
395
+        foreach ($groupUsers as $groupUser) {
396
+            $matchingUsers[(string) $groupUser->getUID()] = $groupUser->getDisplayName();
397
+        }
398
+        return $matchingUsers;
399
+    }
400
+
401
+    /**
402
+     * @return \OC\SubAdmin
403
+     */
404
+    public function getSubAdmin() {
405
+        if (!$this->subAdmin) {
406
+            $this->subAdmin = new \OC\SubAdmin(
407
+                $this->userManager,
408
+                $this,
409
+                \OC::$server->getDatabaseConnection()
410
+            );
411
+        }
412
+
413
+        return $this->subAdmin;
414
+    }
415 415
 }
Please login to merge, or discard this patch.
lib/private/Group/MetaData.php 1 patch
Indentation   +172 added lines, -172 removed lines patch added patch discarded remove patch
@@ -34,176 +34,176 @@
 block discarded – undo
34 34
 use OCP\IUserSession;
35 35
 
36 36
 class MetaData {
37
-	const SORT_NONE = 0;
38
-	const SORT_USERCOUNT = 1; // May have performance issues on LDAP backends
39
-	const SORT_GROUPNAME = 2;
40
-
41
-	/** @var string */
42
-	protected $user;
43
-	/** @var bool */
44
-	protected $isAdmin;
45
-	/** @var array */
46
-	protected $metaData = [];
47
-	/** @var IGroupManager */
48
-	protected $groupManager;
49
-	/** @var bool */
50
-	protected $sorting = false;
51
-	/** @var IUserSession */
52
-	protected $userSession;
53
-
54
-	/**
55
-	 * @param string $user the uid of the current user
56
-	 * @param bool $isAdmin whether the current users is an admin
57
-	 * @param IGroupManager $groupManager
58
-	 * @param IUserManager $userManager
59
-	 * @param IUserSession $userSession
60
-	 */
61
-	public function __construct(
62
-			$user,
63
-			$isAdmin,
64
-			IGroupManager $groupManager,
65
-			IUserSession $userSession
66
-			) {
67
-		$this->user = $user;
68
-		$this->isAdmin = (bool)$isAdmin;
69
-		$this->groupManager = $groupManager;
70
-		$this->userSession = $userSession;
71
-	}
72
-
73
-	/**
74
-	 * returns an array with meta data about all available groups
75
-	 * the array is structured as follows:
76
-	 * [0] array containing meta data about admin groups
77
-	 * [1] array containing meta data about unprivileged groups
78
-	 * @param string $groupSearch only effective when instance was created with
79
-	 * isAdmin being true
80
-	 * @param string $userSearch the pattern users are search for
81
-	 * @return array
82
-	 */
83
-	public function get($groupSearch = '', $userSearch = '') {
84
-		$key = $groupSearch . '::' . $userSearch;
85
-		if(isset($this->metaData[$key])) {
86
-			return $this->metaData[$key];
87
-		}
88
-
89
-		$adminGroups = [];
90
-		$groups = [];
91
-		$sortGroupsIndex = 0;
92
-		$sortGroupsKeys = [];
93
-		$sortAdminGroupsIndex = 0;
94
-		$sortAdminGroupsKeys = [];
95
-
96
-		foreach($this->getGroups($groupSearch) as $group) {
97
-			$groupMetaData = $this->generateGroupMetaData($group, $userSearch);
98
-			if (strtolower($group->getGID()) !== 'admin') {
99
-				$this->addEntry(
100
-					$groups,
101
-					$sortGroupsKeys,
102
-					$sortGroupsIndex,
103
-					$groupMetaData);
104
-			} else {
105
-				//admin group is hard coded to 'admin' for now. In future,
106
-				//backends may define admin groups too. Then the if statement
107
-				//has to be adjusted accordingly.
108
-				$this->addEntry(
109
-					$adminGroups,
110
-					$sortAdminGroupsKeys,
111
-					$sortAdminGroupsIndex,
112
-					$groupMetaData);
113
-			}
114
-		}
115
-
116
-		//whether sorting is necessary is will be checked in sort()
117
-		$this->sort($groups, $sortGroupsKeys);
118
-		$this->sort($adminGroups, $sortAdminGroupsKeys);
119
-
120
-		$this->metaData[$key] = [$adminGroups, $groups];
121
-		return $this->metaData[$key];
122
-	}
123
-
124
-	/**
125
-	 * sets the sort mode, see SORT_* constants for supported modes
126
-	 *
127
-	 * @param int $sortMode
128
-	 */
129
-	public function setSorting($sortMode) {
130
-		switch ($sortMode) {
131
-			case self::SORT_USERCOUNT:
132
-			case self::SORT_GROUPNAME:
133
-				$this->sorting = $sortMode;
134
-				break;
135
-
136
-			default:
137
-				$this->sorting = self::SORT_NONE;
138
-		}
139
-	}
140
-
141
-	/**
142
-	 * adds an group entry to the resulting array
143
-	 * @param array $entries the resulting array, by reference
144
-	 * @param array $sortKeys the sort key array, by reference
145
-	 * @param int $sortIndex the sort key index, by reference
146
-	 * @param array $data the group's meta data as returned by generateGroupMetaData()
147
-	 */
148
-	private function addEntry(&$entries, &$sortKeys, &$sortIndex, $data) {
149
-		$entries[] = $data;
150
-		if ($this->sorting === self::SORT_USERCOUNT) {
151
-			$sortKeys[$sortIndex] = $data['usercount'];
152
-			$sortIndex++;
153
-		} else if ($this->sorting === self::SORT_GROUPNAME) {
154
-			$sortKeys[$sortIndex] = $data['name'];
155
-			$sortIndex++;
156
-		}
157
-	}
158
-
159
-	/**
160
-	 * creates an array containing the group meta data
161
-	 * @param \OCP\IGroup $group
162
-	 * @param string $userSearch
163
-	 * @return array with the keys 'id', 'name', 'usercount' and 'disabled'
164
-	 */
165
-	private function generateGroupMetaData(\OCP\IGroup $group, $userSearch) {
166
-		return [
167
-				'id' => $group->getGID(),
168
-				'name' => $group->getDisplayName(),
169
-				'usercount' => $this->sorting === self::SORT_USERCOUNT ? $group->count($userSearch) : 0,
170
-				'disabled' => $group->countDisabled(),
171
-				'canAdd' => $group->canAddUser(),
172
-				'canRemove' => $group->canRemoveUser(),
173
-			];
174
-	}
175
-
176
-	/**
177
-	 * sorts the result array, if applicable
178
-	 * @param array $entries the result array, by reference
179
-	 * @param array $sortKeys the array containing the sort keys
180
-	 * @param return null
181
-	 */
182
-	private function sort(&$entries, $sortKeys) {
183
-		if ($this->sorting === self::SORT_USERCOUNT) {
184
-			array_multisort($sortKeys, SORT_DESC, $entries);
185
-		} else if ($this->sorting === self::SORT_GROUPNAME) {
186
-			array_multisort($sortKeys, SORT_ASC, $entries);
187
-		}
188
-	}
189
-
190
-	/**
191
-	 * returns the available groups
192
-	 * @param string $search a search string
193
-	 * @return \OCP\IGroup[]
194
-	 */
195
-	public function getGroups($search = '') {
196
-		if($this->isAdmin) {
197
-			return $this->groupManager->search($search);
198
-		} else {
199
-			$userObject = $this->userSession->getUser();
200
-			if($userObject !== null) {
201
-				$groups = $this->groupManager->getSubAdmin()->getSubAdminsGroups($userObject);
202
-			} else {
203
-				$groups = [];
204
-			}
205
-
206
-			return $groups;
207
-		}
208
-	}
37
+    const SORT_NONE = 0;
38
+    const SORT_USERCOUNT = 1; // May have performance issues on LDAP backends
39
+    const SORT_GROUPNAME = 2;
40
+
41
+    /** @var string */
42
+    protected $user;
43
+    /** @var bool */
44
+    protected $isAdmin;
45
+    /** @var array */
46
+    protected $metaData = [];
47
+    /** @var IGroupManager */
48
+    protected $groupManager;
49
+    /** @var bool */
50
+    protected $sorting = false;
51
+    /** @var IUserSession */
52
+    protected $userSession;
53
+
54
+    /**
55
+     * @param string $user the uid of the current user
56
+     * @param bool $isAdmin whether the current users is an admin
57
+     * @param IGroupManager $groupManager
58
+     * @param IUserManager $userManager
59
+     * @param IUserSession $userSession
60
+     */
61
+    public function __construct(
62
+            $user,
63
+            $isAdmin,
64
+            IGroupManager $groupManager,
65
+            IUserSession $userSession
66
+            ) {
67
+        $this->user = $user;
68
+        $this->isAdmin = (bool)$isAdmin;
69
+        $this->groupManager = $groupManager;
70
+        $this->userSession = $userSession;
71
+    }
72
+
73
+    /**
74
+     * returns an array with meta data about all available groups
75
+     * the array is structured as follows:
76
+     * [0] array containing meta data about admin groups
77
+     * [1] array containing meta data about unprivileged groups
78
+     * @param string $groupSearch only effective when instance was created with
79
+     * isAdmin being true
80
+     * @param string $userSearch the pattern users are search for
81
+     * @return array
82
+     */
83
+    public function get($groupSearch = '', $userSearch = '') {
84
+        $key = $groupSearch . '::' . $userSearch;
85
+        if(isset($this->metaData[$key])) {
86
+            return $this->metaData[$key];
87
+        }
88
+
89
+        $adminGroups = [];
90
+        $groups = [];
91
+        $sortGroupsIndex = 0;
92
+        $sortGroupsKeys = [];
93
+        $sortAdminGroupsIndex = 0;
94
+        $sortAdminGroupsKeys = [];
95
+
96
+        foreach($this->getGroups($groupSearch) as $group) {
97
+            $groupMetaData = $this->generateGroupMetaData($group, $userSearch);
98
+            if (strtolower($group->getGID()) !== 'admin') {
99
+                $this->addEntry(
100
+                    $groups,
101
+                    $sortGroupsKeys,
102
+                    $sortGroupsIndex,
103
+                    $groupMetaData);
104
+            } else {
105
+                //admin group is hard coded to 'admin' for now. In future,
106
+                //backends may define admin groups too. Then the if statement
107
+                //has to be adjusted accordingly.
108
+                $this->addEntry(
109
+                    $adminGroups,
110
+                    $sortAdminGroupsKeys,
111
+                    $sortAdminGroupsIndex,
112
+                    $groupMetaData);
113
+            }
114
+        }
115
+
116
+        //whether sorting is necessary is will be checked in sort()
117
+        $this->sort($groups, $sortGroupsKeys);
118
+        $this->sort($adminGroups, $sortAdminGroupsKeys);
119
+
120
+        $this->metaData[$key] = [$adminGroups, $groups];
121
+        return $this->metaData[$key];
122
+    }
123
+
124
+    /**
125
+     * sets the sort mode, see SORT_* constants for supported modes
126
+     *
127
+     * @param int $sortMode
128
+     */
129
+    public function setSorting($sortMode) {
130
+        switch ($sortMode) {
131
+            case self::SORT_USERCOUNT:
132
+            case self::SORT_GROUPNAME:
133
+                $this->sorting = $sortMode;
134
+                break;
135
+
136
+            default:
137
+                $this->sorting = self::SORT_NONE;
138
+        }
139
+    }
140
+
141
+    /**
142
+     * adds an group entry to the resulting array
143
+     * @param array $entries the resulting array, by reference
144
+     * @param array $sortKeys the sort key array, by reference
145
+     * @param int $sortIndex the sort key index, by reference
146
+     * @param array $data the group's meta data as returned by generateGroupMetaData()
147
+     */
148
+    private function addEntry(&$entries, &$sortKeys, &$sortIndex, $data) {
149
+        $entries[] = $data;
150
+        if ($this->sorting === self::SORT_USERCOUNT) {
151
+            $sortKeys[$sortIndex] = $data['usercount'];
152
+            $sortIndex++;
153
+        } else if ($this->sorting === self::SORT_GROUPNAME) {
154
+            $sortKeys[$sortIndex] = $data['name'];
155
+            $sortIndex++;
156
+        }
157
+    }
158
+
159
+    /**
160
+     * creates an array containing the group meta data
161
+     * @param \OCP\IGroup $group
162
+     * @param string $userSearch
163
+     * @return array with the keys 'id', 'name', 'usercount' and 'disabled'
164
+     */
165
+    private function generateGroupMetaData(\OCP\IGroup $group, $userSearch) {
166
+        return [
167
+                'id' => $group->getGID(),
168
+                'name' => $group->getDisplayName(),
169
+                'usercount' => $this->sorting === self::SORT_USERCOUNT ? $group->count($userSearch) : 0,
170
+                'disabled' => $group->countDisabled(),
171
+                'canAdd' => $group->canAddUser(),
172
+                'canRemove' => $group->canRemoveUser(),
173
+            ];
174
+    }
175
+
176
+    /**
177
+     * sorts the result array, if applicable
178
+     * @param array $entries the result array, by reference
179
+     * @param array $sortKeys the array containing the sort keys
180
+     * @param return null
181
+     */
182
+    private function sort(&$entries, $sortKeys) {
183
+        if ($this->sorting === self::SORT_USERCOUNT) {
184
+            array_multisort($sortKeys, SORT_DESC, $entries);
185
+        } else if ($this->sorting === self::SORT_GROUPNAME) {
186
+            array_multisort($sortKeys, SORT_ASC, $entries);
187
+        }
188
+    }
189
+
190
+    /**
191
+     * returns the available groups
192
+     * @param string $search a search string
193
+     * @return \OCP\IGroup[]
194
+     */
195
+    public function getGroups($search = '') {
196
+        if($this->isAdmin) {
197
+            return $this->groupManager->search($search);
198
+        } else {
199
+            $userObject = $this->userSession->getUser();
200
+            if($userObject !== null) {
201
+                $groups = $this->groupManager->getSubAdmin()->getSubAdminsGroups($userObject);
202
+            } else {
203
+                $groups = [];
204
+            }
205
+
206
+            return $groups;
207
+        }
208
+    }
209 209
 }
Please login to merge, or discard this patch.