Completed
Push — stable9 ( 485cb1...e094cf )
by Lukas
26:41 queued 26:23
created

SharedMount   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 210
Duplicated Lines 1.9 %

Coupling/Cohesion

Components 1
Dependencies 10

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 4
loc 210
rs 10
wmc 25
lcom 1
cbo 10

8 Methods

Rating   Name   Duplication   Size   Complexity  
B updateFileTarget() 0 24 4
A stripUserFilesPath() 0 18 3
B moveMount() 0 28 6
A removeMount() 0 9 1
A getShare() 0 5 1
A __construct() 0 8 1
A verifyMountPoint() 0 23 3
B generateUniqueTarget() 4 24 6

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 *
5
 * @author Björn Schießle <[email protected]>
6
 * @author Joas Schilling <[email protected]>
7
 * @author Morris Jobke <[email protected]>
8
 * @author Robin Appelman <[email protected]>
9
 * @author Roeland Jago Douma <[email protected]>
10
 * @author Vincent Petry <[email protected]>
11
 *
12
 * @license AGPL-3.0
13
 *
14
 * This code is free software: you can redistribute it and/or modify
15
 * it under the terms of the GNU Affero General Public License, version 3,
16
 * as published by the Free Software Foundation.
17
 *
18
 * This program is distributed in the hope that it will be useful,
19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21
 * GNU Affero General Public License for more details.
22
 *
23
 * You should have received a copy of the GNU Affero General Public License, version 3,
24
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
25
 *
26
 */
27
28
namespace OCA\Files_Sharing;
29
30
use OC\Files\Filesystem;
31
use OC\Files\Mount\MountPoint;
32
use OC\Files\Mount\MoveableMount;
33
use OC\Files\View;
34
35
/**
36
 * Shared mount points can be moved by the user
37
 */
38
class SharedMount extends MountPoint implements MoveableMount {
39
	/**
40
	 * @var \OC\Files\Storage\Shared $storage
41
	 */
42
	protected $storage = null;
43
44
	/**
45
	 * @var \OC\Files\View
46
	 */
47
	private $recipientView;
48
49
	/**
50
	 * @var string
51
	 */
52
	private $user;
53
54
	/**
55
	 * @param string $storage
56
	 * @param SharedMount[] $mountpoints
57
	 * @param array|null $arguments
58
	 * @param \OCP\Files\Storage\IStorageFactory $loader
59
	 */
60
	public function __construct($storage, array $mountpoints, $arguments = null, $loader = null) {
61
		$this->user = $arguments['user'];
62
		$this->recipientView = new View('/' . $this->user . '/files');
63
		$newMountPoint = $this->verifyMountPoint($arguments['share'], $mountpoints);
64
		$absMountPoint = '/' . $this->user . '/files' . $newMountPoint;
65
		$arguments['ownerView'] = new View('/' . $arguments['share']['uid_owner'] . '/files');
66
		parent::__construct($storage, $absMountPoint, $arguments, $loader);
67
	}
68
69
	/**
70
	 * check if the parent folder exists otherwise move the mount point up
71
	 *
72
	 * @param array $share
73
	 * @param SharedMount[] $mountpoints
74
	 * @return string
75
	 */
76
	private function verifyMountPoint(&$share, array $mountpoints) {
77
78
		$mountPoint = basename($share['file_target']);
79
		$parent = dirname($share['file_target']);
80
81
		if (!$this->recipientView->is_dir($parent)) {
82
			$parent = Helper::getShareFolder($this->recipientView);
83
		}
84
85
		$newMountPoint = $this->generateUniqueTarget(
86
			\OC\Files\Filesystem::normalizePath($parent . '/' . $mountPoint),
87
			$this->recipientView,
88
			$mountpoints
89
		);
90
91
		if ($newMountPoint !== $share['file_target']) {
92
			$this->updateFileTarget($newMountPoint, $share);
93
			$share['file_target'] = $newMountPoint;
94
			$share['unique_name'] = true;
95
		}
96
97
		return $newMountPoint;
98
	}
99
100
	/**
101
	 * @param string $path
102
	 * @param View $view
103
	 * @param SharedMount[] $mountpoints
104
	 * @return mixed
105
	 */
106
	private function generateUniqueTarget($path, $view, array $mountpoints) {
107
		$pathinfo = pathinfo($path);
108
		$ext = (isset($pathinfo['extension'])) ? '.'.$pathinfo['extension'] : '';
109
		$name = $pathinfo['filename'];
110
		$dir = $pathinfo['dirname'];
111
112
		// Helper function to find existing mount points
113
		$mountpointExists = function($path) use ($mountpoints) {
114
			foreach ($mountpoints as $mountpoint) {
115
				if ($mountpoint->getShare()['file_target'] === $path) {
116
					return true;
117
				}
118
			}
119
			return false;
120
		};
121
122
		$i = 2;
123 View Code Duplication
		while ($view->file_exists($path) || $mountpointExists($path)) {
124
			$path = Filesystem::normalizePath($dir . '/' . $name . ' ('.$i.')' . $ext);
125
			$i++;
126
		}
127
128
		return $path;
129
	}
130
131
	/**
132
	 * update fileTarget in the database if the mount point changed
133
	 *
134
	 * @param string $newPath
135
	 * @param array $share reference to the share which should be modified
136
	 * @return bool
137
	 */
138
	private function updateFileTarget($newPath, &$share) {
139
		// if the user renames a mount point from a group share we need to create a new db entry
140
		// for the unique name
141
		if ($share['share_type'] === \OCP\Share::SHARE_TYPE_GROUP && empty($share['unique_name'])) {
142
			$query = \OCP\DB::prepare('INSERT INTO `*PREFIX*share` (`item_type`, `item_source`, `item_target`,'
0 ignored issues
show
Deprecated Code introduced by
The method OCP\DB::prepare() has been deprecated with message: 8.1.0 use prepare() of \OCP\IDBConnection - \OC::$server->getDatabaseConnection()

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
143
			.' `share_type`, `share_with`, `uid_owner`, `permissions`, `stime`, `file_source`,'
144
			.' `file_target`, `token`, `parent`) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)');
145
			$arguments = array($share['item_type'], $share['item_source'], $share['item_target'],
146
				2, $this->user, $share['uid_owner'], $share['permissions'], $share['stime'], $share['file_source'],
147
				$newPath, $share['token'], $share['id']);
148
		} else {
149
			// rename mount point
150
			$query = \OCP\DB::prepare(
0 ignored issues
show
Deprecated Code introduced by
The method OCP\DB::prepare() has been deprecated with message: 8.1.0 use prepare() of \OCP\IDBConnection - \OC::$server->getDatabaseConnection()

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
151
					'Update `*PREFIX*share`
152
						SET `file_target` = ?
153
						WHERE `id` = ?'
154
			);
155
			$arguments = array($newPath, $share['id']);
156
		}
157
158
		$result = $query->execute($arguments);
159
160
		return $result === 1 ? true : false;
161
	}
162
163
	/**
164
	 * Format a path to be relative to the /user/files/ directory
165
	 *
166
	 * @param string $path the absolute path
167
	 * @return string e.g. turns '/admin/files/test.txt' into '/test.txt'
168
	 * @throws \OCA\Files_Sharing\Exceptions\BrokenPath
169
	 */
170
	protected function stripUserFilesPath($path) {
171
		$trimmed = ltrim($path, '/');
172
		$split = explode('/', $trimmed);
173
174
		// it is not a file relative to data/user/files
175
		if (count($split) < 3 || $split[1] !== 'files') {
176
			\OCP\Util::writeLog('file sharing',
177
				'Can not strip userid and "files/" from path: ' . $path,
178
				\OCP\Util::ERROR);
179
			throw new \OCA\Files_Sharing\Exceptions\BrokenPath('Path does not start with /user/files', 10);
180
		}
181
182
		// skip 'user' and 'files'
0 ignored issues
show
Unused Code Comprehensibility introduced by
38% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
183
		$sliced = array_slice($split, 2);
184
		$relPath = implode('/', $sliced);
185
186
		return '/' . $relPath;
187
	}
188
189
	/**
190
	 * Move the mount point to $target
191
	 *
192
	 * @param string $target the target mount point
193
	 * @return bool
194
	 */
195
	public function moveMount($target) {
196
197
		$relTargetPath = $this->stripUserFilesPath($target);
198
		$share = $this->storage->getShare();
199
200
		$result = true;
201
202
		if (!empty($share['grouped'])) {
203
			foreach ($share['grouped'] as $s) {
204
				$result = $this->updateFileTarget($relTargetPath, $s) && $result;
205
			}
206
		} else {
207
			$result = $this->updateFileTarget($relTargetPath, $share) && $result;
208
		}
209
210
		if ($result) {
211
			$this->setMountPoint($target);
212
			$this->storage->setUniqueName();
213
			$this->storage->setMountPoint($relTargetPath);
214
215
		} else {
216
			\OCP\Util::writeLog('file sharing',
217
				'Could not rename mount point for shared folder "' . $this->getMountPoint() . '" to "' . $target . '"',
218
				\OCP\Util::ERROR);
219
		}
220
221
		return $result;
222
	}
223
224
	/**
225
	 * Remove the mount points
226
	 *
227
	 * @return bool
228
	 */
229
	public function removeMount() {
230
		$mountManager = \OC\Files\Filesystem::getMountManager();
231
		/** @var $storage \OC\Files\Storage\Shared */
232
		$storage = $this->getStorage();
233
		$result = $storage->unshareStorage();
234
		$mountManager->removeMount($this->mountPoint);
235
236
		return $result;
237
	}
238
239
	/**
240
	 * @return array
241
	 */
242
	public function getShare() {
243
		/** @var $storage \OC\Files\Storage\Shared */
244
		$storage = $this->getStorage();
245
		return $storage->getShare();
246
	}
247
}
248