Completed
Pull Request — master (#26608)
by
unknown
09:04
created

Helper::delete()   C

Complexity

Conditions 11
Paths 168

Size

Total Lines 71

Duplication

Lines 10
Ratio 14.08 %

Importance

Changes 0
Metric Value
cc 11
nc 168
nop 5
dl 10
loc 71
rs 6.0327
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * @author Björn Schießle <[email protected]>
4
 * @author Joas Schilling <[email protected]>
5
 * @author Miguel Prokop <[email protected]>
6
 * @author Morris Jobke <[email protected]>
7
 * @author Robin Appelman <[email protected]>
8
 * @author Robin McCorkell <[email protected]>
9
 * @author Thomas Müller <[email protected]>
10
 * @author Vincent Petry <[email protected]>
11
 *
12
 * @copyright Copyright (c) 2018, ownCloud GmbH
13
 * @license AGPL-3.0
14
 *
15
 * This code is free software: you can redistribute it and/or modify
16
 * it under the terms of the GNU Affero General Public License, version 3,
17
 * as published by the Free Software Foundation.
18
 *
19
 * This program is distributed in the hope that it will be useful,
20
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22
 * GNU Affero General Public License for more details.
23
 *
24
 * You should have received a copy of the GNU Affero General Public License, version 3,
25
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
26
 *
27
 */
28
29
namespace OC\Share;
30
31
use OC\HintException;
32
33
class Helper extends \OC\Share\Constants {
34
35
	/**
36
	 * Delete all reshares and group share children of an item
37
	 * @param int $parent Id of item to delete
38
	 * @param bool $excludeParent If true, exclude the parent from the delete (optional)
39
	 * @param string $uidOwner The user that the parent was shared with (optional)
40
	 * @param int $newParent new parent for the childrens
41
	 * @param bool $excludeGroupChildren exclude group children elements
42
	 * @return array of deleted items
43
	 */
44
	public static function delete($parent, $excludeParent = false, $uidOwner = null, $newParent = null, $excludeGroupChildren = false) {
45
		$ids = [$parent];
46
		$deletedItems = [];
47
		$changeParent = [];
48
		$parents = [$parent];
49
		while (!empty($parents)) {
50
			$parents = "'".\implode("','", $parents)."'";
51
			// Check the owner on the first search of reshares, useful for
52
			// finding and deleting the reshares by a single user of a group share
53
			$params = [];
54
			if (\count($ids) == 1 && isset($uidOwner)) {
55
				// FIXME: don't concat $parents, use Docrine's PARAM_INT_ARRAY approach
56
				$queryString = 'SELECT `id`, `share_with`, `item_type`, `share_type`, ' .
57
					'`item_target`, `file_target`, `parent` ' .
58
					'FROM `*PREFIX*share` ' .
59
					'WHERE `parent` IN ('.$parents.') AND `uid_owner` = ? ';
60
				$params[] = $uidOwner;
61
			} else {
62
				$queryString = 'SELECT `id`, `share_with`, `item_type`, `share_type`, ' .
63
					'`item_target`, `file_target`, `parent`, `uid_owner` ' .
64
					'FROM `*PREFIX*share` WHERE `parent` IN ('.$parents.') ';
65
			}
66
			if ($excludeGroupChildren) {
67
				$queryString .= ' AND `share_type` != ?';
68
				$params[] = self::$shareTypeGroupUserUnique;
69
			}
70
			$query = \OC_DB::prepare($queryString);
71
			$result = $query->execute($params);
72
			// Reset parents array, only go through loop again if items are found
73
			$parents = [];
74
			while ($item = $result->fetchRow()) {
75
				$tmpItem = [
76
					'id' => $item['id'],
77
					'shareWith' => $item['share_with'],
78
					'itemTarget' => $item['item_target'],
79
					'itemType' => $item['item_type'],
80
					'shareType' => (int)$item['share_type'],
81
				];
82
				if (isset($item['file_target'])) {
83
					$tmpItem['fileTarget'] = $item['file_target'];
84
				}
85
				// if we have a new parent for the child we remember the child
86
				// to update the parent, if not we add it to the list of items
87
				// which should be deleted
88
				if ($newParent !== null) {
89
					$changeParent[] = $item['id'];
90
				} else {
91
					$deletedItems[] = $tmpItem;
92
					$ids[] = $item['id'];
93
					$parents[] = $item['id'];
94
				}
95
			}
96
		}
97
		if ($excludeParent) {
98
			unset($ids[0]);
99
		}
100
101 View Code Duplication
		if (!empty($changeParent)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
102
			$idList = "'".\implode("','", $changeParent)."'";
103
			$query = \OC_DB::prepare('UPDATE `*PREFIX*share` SET `parent` = ? WHERE `id` IN ('.$idList.')');
104
			$query->execute([$newParent]);
105
		}
106
107 View Code Duplication
		if (!empty($ids)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
108
			$idList = "'".\implode("','", $ids)."'";
109
			$query = \OC_DB::prepare('DELETE FROM `*PREFIX*share` WHERE `id` IN ('.$idList.')');
110
			$query->execute();
111
		}
112
113
		return $deletedItems;
114
	}
115
116
	/**
117
	 * get default expire settings defined by the admin
118
	 * @return array contains 'defaultExpireDateSet', 'enforceExpireDate', 'expireAfterDays'
119
	 */
120
	public static function getDefaultExpireSetting() {
121
		$config = \OC::$server->getConfig();
122
123
		$defaultExpireSettings = ['defaultExpireDateSet' => false];
124
125
		// get default expire settings
126
		$defaultExpireDate = $config->getAppValue('core', 'shareapi_default_expire_date', 'no');
127
		if ($defaultExpireDate === 'yes') {
128
			$enforceExpireDate = $config->getAppValue('core', 'shareapi_enforce_expire_date', 'no');
129
			$defaultExpireSettings['defaultExpireDateSet'] = true;
130
			$defaultExpireSettings['expireAfterDays'] = (int)($config->getAppValue('core', 'shareapi_expire_after_n_days', '7'));
131
			$defaultExpireSettings['enforceExpireDate'] = $enforceExpireDate === 'yes' ? true : false;
132
		}
133
134
		return $defaultExpireSettings;
135
	}
136
137
	/**
138
	 * calculate expire date
139
	 * @param array $defaultExpireSettings contains 'defaultExpireDateSet', 'enforceExpireDate', 'expireAfterDays'
140
	 * @param int $creationTime timestamp when the share was created
141
	 * @param int $userExpireDate expire timestamp set by the user
142
	 * @return mixed integer timestamp or False
143
	 */
144
	public static function calculateExpireDate($defaultExpireSettings, $creationTime, $userExpireDate = null) {
145
		$expires = false;
146
		$defaultExpires = null;
147
148
		if (!empty($defaultExpireSettings['defaultExpireDateSet'])) {
149
			$defaultExpires = $creationTime + $defaultExpireSettings['expireAfterDays'] * 86400;
150
		}
151
152
		if (isset($userExpireDate)) {
153
			// if the admin decided to enforce the default expire date then we only take
154
			// the user defined expire date of it is before the default expire date
155
			if ($defaultExpires && !empty($defaultExpireSettings['enforceExpireDate'])) {
156
				$expires = \min($userExpireDate, $defaultExpires);
157
			} else {
158
				$expires = $userExpireDate;
159
			}
160
		} elseif ($defaultExpires && !empty($defaultExpireSettings['enforceExpireDate'])) {
161
			$expires = $defaultExpires;
162
		}
163
164
		return $expires;
165
	}
166
167
	/**
168
	 * Strips away a potential file names and trailing slashes:
169
	 * - http://localhost
170
	 * - http://localhost/
171
	 * - http://localhost/index.php
172
	 * - http://localhost/index.php/s/{shareToken}
173
	 *
174
	 * all return: http://localhost
175
	 *
176
	 * @param string $remote
177
	 * @return string
178
	 */
179 View Code Duplication
	protected static function fixRemoteURL($remote) {
180
		$remote = \str_replace('\\', '/', $remote);
181
		if ($fileNamePosition = \strpos($remote, '/index.php')) {
182
			$remote = \substr($remote, 0, $fileNamePosition);
183
		}
184
		$remote = \rtrim($remote, '/');
185
186
		return $remote;
187
	}
188
189
	/**
190
	 * split user and remote from federated cloud id
191
	 *
192
	 * @param string $id
193
	 * @return string[]
194
	 * @throws HintException
195
	 */
196
	public static function splitUserRemote($id) {
197
		if (\strpos($id, '@') === false) {
198
			$l = \OC::$server->getL10N('core');
199
			$hint = $l->t('Invalid Federated Cloud ID');
200
			throw new HintException('Invalid Federated Cloud ID', $hint);
201
		}
202
203
		// Find the first character that is not allowed in user names
204
		$id = \str_replace('\\', '/', $id);
205
		$posSlash = \strpos($id, '/');
206
		$posColon = \strpos($id, ':');
207
208 View Code Duplication
		if ($posSlash === false && $posColon === false) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
209
			$invalidPos = \strlen($id);
210
		} elseif ($posSlash === false) {
211
			$invalidPos = $posColon;
212
		} elseif ($posColon === false) {
213
			$invalidPos = $posSlash;
214
		} else {
215
			$invalidPos = \min($posSlash, $posColon);
216
		}
217
218
		// Find the last @ before $invalidPos
219
		$pos = $lastAtPos = 0;
220 View Code Duplication
		while ($lastAtPos !== false && $lastAtPos <= $invalidPos) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
221
			$pos = $lastAtPos;
222
			$lastAtPos = \strpos($id, '@', $pos + 1);
223
		}
224
225 View Code Duplication
		if ($pos !== false) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
226
			$user = \substr($id, 0, $pos);
227
			$remote = \substr($id, $pos + 1);
228
			$remote = self::fixRemoteURL($remote);
229
			if (!empty($user) && !empty($remote)) {
230
				return [$user, $remote];
231
			}
232
		}
233
234
		$l = \OC::$server->getL10N('core');
235
		$hint = $l->t('Invalid Federated Cloud ID');
236
		throw new HintException('Invalid Fededrated Cloud ID', $hint);
237
	}
238
239
	/**
240
	 * check if two federated cloud IDs refer to the same user
241
	 *
242
	 * @param string $user1
243
	 * @param string $server1
244
	 * @param string $user2
245
	 * @param string $server2
246
	 * @return bool true if both users and servers are the same
247
	 */
248
	public static function isSameUserOnSameServer($user1, $server1, $user2, $server2) {
249
		$normalizedServer1 = \strtolower(\OC\Share\Share::removeProtocolFromUrl($server1));
250
		$normalizedServer2 = \strtolower(\OC\Share\Share::removeProtocolFromUrl($server2));
251
252 View Code Duplication
		if (\rtrim($normalizedServer1, '/') === \rtrim($normalizedServer2, '/')) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
253
			// FIXME this should be a method in the user management instead
254
			\OCP\Util::emitHook(
255
					'\OCA\Files_Sharing\API\Server2Server',
256
					'preLoginNameUsedAsUserName',
257
					['uid' => &$user1]
258
			);
259
			\OCP\Util::emitHook(
260
					'\OCA\Files_Sharing\API\Server2Server',
261
					'preLoginNameUsedAsUserName',
262
					['uid' => &$user2]
263
			);
264
265
			if ($user1 === $user2) {
266
				return true;
267
			}
268
		}
269
270
		return false;
271
	}
272
}
273