Passed
Push — php8 ( 2fa786...6e3a93 )
by Fabio
12:43 queued 07:21
created

TWeakCollectionTrait::weakClone()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 2
c 1
b 0
f 0
nc 2
nop 0
dl 0
loc 4
rs 10
1
<?php
2
/**
3
 * TWeakCollectionTrait class
4
 *
5
 * @author Brad Anderson <[email protected]>
6
 * @link https://github.com/pradosoft/prado
7
 * @license https://github.com/pradosoft/prado/blob/master/LICENSE
8
 */
9
10
namespace Prado\Collections;
11
12
/**
13
 * TWeakCollectionTrait trait
14
 *
15
 * This is the common WeakMap caching implementation for Weak Collections. It constructs
16
 * a WeakMap, where available, and tracks the number of times an object is {@link
17
 * weakAdd added} to and {@link weakRemove removed} from the Collection.
18
 *
19
 * When the PHP environment invalidates a WeakReference, it is no longer linked in
20
 * the WeakMap.  The number of known objects is tracked and upon deviations in the
21
 * WeakMap count then {@link weakChanged} becomes true.  When weakChanged is true
22
 * the implementing class can scrub the list of invalidated WeakReference.
23
 *
24
 * There are utility functions for managing the WeakMap to {@link weakStart start},
25
 * {@link weakRestart restart}, {@link weakClone clone}, and {@link weakStop stop}
26
 * the WeakMap.  The total number of objects in the WeakMap can be retrieved with
27
 * {@link weakCount} and the count of each object with {@link weakObjectCount}.
28
 *
29
 * @author Brad Anderson <[email protected]>
30
 * @since 4.2.3
31
 * @see https://www.php.net/manual/en/class.weakmap.php
32
 */
33
trait TWeakCollectionTrait
34
{
35
	/**
36
	 * @var null|\WeakMap Maintains the cache of list objects.  Any invalid weak references
37
	 *  change the WeakMap count automatically.  This also tracks the number of times
38
	 *  on object has been inserted in the collection.
39
	 */
40
	private ?object $_weakMap = null;
41
42
	/** @var int Number of known objects in the collection. */
43
	private int $_weakCount = 0;
44
45
	private static ?bool $_hasWeakMap = null;
46
	/**
47
	 * Initializes a new WeakMap in PHP 8.0+.
48
	 */
49
	protected function weakStart(): void
50
	{
51
		if (self::$_hasWeakMap === null) { // PHP 8.0+
52
			self::$_hasWeakMap = class_exists('\WeakMap', false);
53
		}
54
		if (self::$_hasWeakMap) {
55
			$this->_weakMap = new \WeakMap();
56
		}
57
	}
58
59
	/**
60
	 * Restarts the WeakMap cache if it exists.
61
	 */
62
	protected function weakRestart(): void
63
	{
64
		if ($this->_weakMap) {
65
			$this->_weakMap = new \WeakMap();
66
		}
67
	}
68
69
	/**
70
	 * Stops the WeakMap cache.
71
	 */
72
	protected function weakClone(): void
73
	{
74
		if ($this->_weakMap) {
75
			$this->_weakMap = clone $this->_weakMap;
76
		}
77
	}
78
79
	/**
80
	 * Checks if the WeakMap has changed.  Prior to PHP 8.0, this will always return
81
	 * true.
82
	 * @return bool Are there any changes to the WeakMap.
83
	 */
84
	protected function weakChanged(): bool
85
	{
86
		return $this->_weakMap && $this->_weakMap->count() !== $this->_weakCount || !self::$_hasWeakMap;
0 ignored issues
show
Bug Best Practice introduced by
The expression self::_hasWeakMap of type boolean|null is loosely compared to false; this is ambiguous if the boolean can be false. You might want to explicitly use !== null instead.

If an expression can have both false, and null as possible values. It is generally a good practice to always use strict comparison to clearly distinguish between those two values.

$a = canBeFalseAndNull();

// Instead of
if ( ! $a) { }

// Better use one of the explicit versions:
if ($a !== null) { }
if ($a !== false) { }
if ($a !== null && $a !== false) { }
Loading history...
87
	}
88
89
	/**
90
	 * Resets the new number of known objects in the list to the current WeakMap count.
91
	 */
92
	protected function weakResetCount(): void
93
	{
94
		if ($this->_weakMap) {
95
			$this->_weakCount = $this->_weakMap->count();
96
		}
97
	}
98
99
	/**
100
	 * @return ?int The number of items being tracked in the WeakMap. null if there is
101
	 *   no WeakMap.
102
	 */
103
	protected function weakCount(): ?int
104
	{
105
		if ($this->_weakMap) {
106
			return $this->_weakMap->count();
107
		}
108
		return null;
109
	}
110
111
	/**
112
	 * Adds or updates an object to track with the WeakMap.
113
	 * @param object $object The object being tracked for existence.
114
	 * @return int The number of times the object has been added.
115
	 */
116
	protected function weakAdd(object $object): int
117
	{
118
		if ($this->_weakMap) {
119
			if (!$this->_weakMap->offsetExists($object)) {
120
				$count = 1;
121
				$this->_weakCount++;
122
			} else {
123
				$count = $this->_weakMap->offsetGet($object) + 1;
124
			}
125
			$this->_weakMap->offsetSet($object, $count);
126
			return $count;
127
		}
128
		return 0;
129
	}
130
131
	/**
132
	 * @param object $object The object being tracked.
133
	 * @return ?int The number of instances of the object in the Collection.
134
	 */
135
	protected function weakObjectCount(object $object): ?int
136
	{
137
		if ($this->_weakMap && $this->_weakMap->offsetExists($object)) {
138
			return $this->_weakMap->offsetGet($object);
139
		}
140
		return null;
141
	}
142
143
	/**
144
	 * Removes or updates an object from WeakMap tracking.
145
	 * @param object $object The object being tracked for existence.
146
	 * @return int The number of remaining instances of the object in the Collection.
147
	 */
148
	protected function weakRemove(object $object): int
149
	{
150
		if ($this->_weakMap) {
151
			$count = $this->_weakMap->offsetGet($object) - 1;
152
			if ($count) {
153
				$this->_weakMap->offsetSet($object, $count);
154
			} else {
155
				$this->_weakMap->offsetUnset($object);
156
				$this->_weakCount--;
157
			}
158
			return $count;
159
		}
160
		return 0;
161
	}
162
163
	/**
164
	 * Stops the WeakMap cache.
165
	 */
166
	protected function weakStop(): void
167
	{
168
		$this->_weakMap = null;
169
	}
170
171
	/**
172
	 * @param array &$exprops Properties to remove from serialize.
173
	 */
174
	protected function _weakZappableSleepProps(array &$exprops): void
175
	{
176
		$exprops[] = "\0" . __CLASS__ . "\0_weakMap";
177
		$exprops[] = "\0" . __CLASS__ . "\0_weakCount";
178
	}
179
}
180