LockManager::lock()   F
last analyzed

Complexity

Conditions 17
Paths 418

Size

Total Lines 69

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 17
nc 418
nop 4
dl 0
loc 69
rs 1.8583
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
declare(strict_types=1);
3
/**
4
 * @author Thomas Müller <[email protected]>
5
 * @copyright Copyright (c) 2018, ownCloud GmbH
6
 * @license AGPL-3.0
7
 *
8
 * This code is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Affero General Public License, version 3,
10
 * as published by the Free Software Foundation.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
 * GNU Affero General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Affero General Public License, version 3,
18
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
19
 */
20
21
namespace OC\Lock\Persistent;
22
23
use OCP\AppFramework\Utility\ITimeFactory;
24
use OCP\IUserSession;
25
use OCP\Lock\Persistent\ILock;
26
27
class LockManager {
28
29
	/** @var LockMapper */
30
	private $lockMapper;
31
	/** @var IUserSession */
32
	private $userSession;
33
	/** @var ITimeFactory */
34
	private $timeFactory;
35
36
	public function __construct(LockMapper $lockMapper,
37
								IUserSession $userSession,
38
								ITimeFactory $timeFactory) {
39
		$this->lockMapper = $lockMapper;
40
		$this->userSession = $userSession;
41
		$this->timeFactory = $timeFactory;
42
	}
43
44
	public function lock(int $storageId, string $internalPath, int $fileId, array $lockInfo) : bool {
45
		if ($fileId <= 0) {
46
			throw new \InvalidArgumentException('Invalid file id');
47
		}
48
		if (!isset($lockInfo['token'])) {
49
			throw new \InvalidArgumentException('No token provided in $lockInfo');
50
		}
51
52
		// We're making the lock timeout 30 minutes
53
		$timeout = 30*60;
54
		if (isset($lockInfo['timeout'])) {
55
			$timeout = $lockInfo['timeout'];
56
		}
57
		$owner = $lockInfo['owner'] ?? null;
58
		if ($owner === null && $this->userSession->isLoggedIn()) {
59
			$user = $this->userSession->getUser();
60
			if ($user !== null) {
61
				$owner = $user->getDisplayName();
62
				if ($user->getEMailAddress() !== null) {
63
					$owner .= " <{$user->getEMailAddress()}>";
64
				}
65
			}
66
		}
67
68
		$locks = $this->lockMapper->getLocksByPath($storageId, $internalPath, false);
69
		$exists = false;
70
		foreach ($locks as $lock) {
71
			if ($lock->getToken() === $lockInfo['token']) {
72
				$exists = true;
73
				$lock->setCreatedAt($this->timeFactory->getTime());
74
				$lock->setTimeout($timeout);
75
				if ($lock->getOwner() === '' || $lock->getOwner() === null) {
76
					$lock->setOwner($owner);
77
				}
78
				$this->lockMapper->update($lock);
79
			}
80
		}
81
82
		if ($exists) {
83
			return true;
84
		}
85
86
		$depth = 0;
87
		if (isset($lockInfo['depth'])) {
88
			$depth = $lockInfo['depth'];
89
		}
90
		$scope = ILock::LOCK_SCOPE_EXCLUSIVE;
91
		if (isset($lockInfo['scope'])) {
92
			$scope = $lockInfo['scope'];
93
		}
94
95
		$lock = new Lock();
96
		$lock->setFileId($fileId);
97
		$lock->setCreatedAt($this->timeFactory->getTime());
98
		$lock->setTimeout($timeout);
99
		$lock->setOwner($owner);
100
		$lock->setToken($lockInfo['token']);
101
		$lock->setScope($scope);
102
		$lock->setDepth($depth);
103
104
		if ($this->userSession->isLoggedIn()) {
105
			$user = $this->userSession->getUser();
106
			if ($user !== null) {
107
				$lock->setOwnerAccountId($user->getAccountId());
0 ignored issues
show
Documentation Bug introduced by
The method setOwnerAccountId does not exist on object<OC\Lock\Persistent\Lock>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
108
			}
109
		}
110
		$this->lockMapper->insert($lock);
111
		return true;
112
	}
113
114
	/**
115
	 * @param int $fileId
116
	 * @param string $token
117
	 * @return bool
118
	 */
119
	public function unlock(int $fileId, string $token) : bool {
120
		return $this->lockMapper->deleteByFileIdAndToken($fileId, $token);
121
	}
122
123
	/**
124
	 * @param int $storageId
125
	 * @param string $internalPath
126
	 * @param bool $returnChildLocks
127
	 * @return ILock[]
128
	 */
129
	public function getLocks(int $storageId, string $internalPath, bool $returnChildLocks) : array {
130
		return $this->lockMapper->getLocksByPath($storageId, $internalPath, $returnChildLocks);
131
	}
132
}
133