ScopedLock   A
last analyzed

Complexity

Total Complexity 7

Size/Duplication

Total Lines 74
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 2

Importance

Changes 0
Metric Value
dl 0
loc 74
rs 10
c 0
b 0
f 0
wmc 7
lcom 0
cbo 2

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 1
A factory() 0 12 3
A release() 0 3 1
A __destruct() 0 8 2
1
<?php
2
/**
3
 * Resource locking handling.
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License along
16
 * with this program; if not, write to the Free Software Foundation, Inc.,
17
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18
 * http://www.gnu.org/copyleft/gpl.html
19
 *
20
 * @file
21
 * @ingroup LockManager
22
 * @author Aaron Schulz
23
 */
24
25
/**
26
 * Self-releasing locks
27
 *
28
 * LockManager helper class to handle scoped locks, which
29
 * release when an object is destroyed or goes out of scope.
30
 *
31
 * @ingroup LockManager
32
 * @since 1.19
33
 */
34
class ScopedLock {
35
	/** @var LockManager */
36
	protected $manager;
37
38
	/** @var StatusValue */
39
	protected $status;
40
41
	/** @var array Map of lock types to resource paths */
42
	protected $pathsByType;
43
44
	/**
45
	 * @param LockManager $manager
46
	 * @param array $pathsByType Map of lock types to path lists
47
	 * @param StatusValue $status
48
	 */
49
	protected function __construct(
50
		LockManager $manager, array $pathsByType, StatusValue $status
51
	) {
52
		$this->manager = $manager;
53
		$this->pathsByType = $pathsByType;
54
		$this->status = $status;
55
	}
56
57
	/**
58
	 * Get a ScopedLock object representing a lock on resource paths.
59
	 * Any locks are released once this object goes out of scope.
60
	 * The StatusValue object is updated with any errors or warnings.
61
	 *
62
	 * @param LockManager $manager
63
	 * @param array $paths List of storage paths or map of lock types to path lists
64
	 * @param int|string $type LockManager::LOCK_* constant or "mixed" and $paths
65
	 *   can be a map of types to paths (since 1.22). Otherwise $type should be an
66
	 *   integer and $paths should be a list of paths.
67
	 * @param StatusValue $status
68
	 * @param int $timeout Timeout in seconds (0 means non-blocking) (since 1.22)
69
	 * @return ScopedLock|null Returns null on failure
70
	 */
71
	public static function factory(
72
		LockManager $manager, array $paths, $type, StatusValue $status, $timeout = 0
73
	) {
74
		$pathsByType = is_integer( $type ) ? [ $type => $paths ] : $paths;
75
		$lockStatus = $manager->lockByType( $pathsByType, $timeout );
76
		$status->merge( $lockStatus );
0 ignored issues
show
Bug introduced by
It seems like $lockStatus defined by $manager->lockByType($pathsByType, $timeout) on line 75 can be null; however, StatusValue::merge() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
77
		if ( $lockStatus->isOK() ) {
78
			return new self( $manager, $pathsByType, $status );
79
		}
80
81
		return null;
82
	}
83
84
	/**
85
	 * Release a scoped lock and set any errors in the attatched StatusValue object.
86
	 * This is useful for early release of locks before function scope is destroyed.
87
	 * This is the same as setting the lock object to null.
88
	 *
89
	 * @param ScopedLock $lock
90
	 * @since 1.21
91
	 */
92
	public static function release( ScopedLock &$lock = null ) {
93
		$lock = null;
94
	}
95
96
	/**
97
	 * Release the locks when this goes out of scope
98
	 */
99
	function __destruct() {
100
		$wasOk = $this->status->isOK();
101
		$this->status->merge( $this->manager->unlockByType( $this->pathsByType ) );
102
		if ( $wasOk ) {
103
			// Make sure StatusValue is OK, despite any unlockFiles() fatals
104
			$this->status->setResult( true, $this->status->value );
105
		}
106
	}
107
}
108