RestrictedEntityLookup   A
last analyzed

Complexity

Total Complexity 9

Size/Duplication

Total Lines 78
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 5
Bugs 0 Features 0
Metric Value
eloc 22
c 5
b 0
f 0
dl 0
loc 78
ccs 20
cts 20
cp 1
rs 10
wmc 9

6 Methods

Rating   Name   Duplication   Size   Complexity  
A hasEntity() 0 2 1
A __construct() 0 7 2
A reset() 0 2 1
A getEntityAccessCount() 0 2 1
A getEntity() 0 15 3
A entityHasBeenAccessed() 0 4 1
1
<?php
2
3
namespace Wikibase\DataModel\Services\Lookup;
4
5
use InvalidArgumentException;
6
use Wikibase\DataModel\Entity\EntityDocument;
7
use Wikibase\DataModel\Entity\EntityId;
8
9
/**
10
 * EntityLookup that counts how many entities have been loaded through it and throws
11
 * an exception once to many entities have been loaded.
12
 *
13
 * This is needed to limit the number of entities that can be loaded via some
14
 * user controlled features, like entity access in Lua.
15
 *
16
 * @since 2.0
17
 *
18
 * @license GPL-2.0-or-later
19
 * @author Marius Hoch < [email protected] >
20
 */
21
class RestrictedEntityLookup implements EntityLookup {
22
23
	private EntityLookup $entityLookup;
24
	private int $entityAccessLimit;
25
26
	/** @var array<string,true> Entity id serialization => true */
27
	private array $entitiesAccessed = [];
28
29
	public function __construct( EntityLookup $entityLookup, int $entityAccessLimit ) {
30
		if ( $entityAccessLimit < 1 ) {
31
			throw new InvalidArgumentException( '$entityAccessLimit must be a positive integer' );
32
		}
33
34
		$this->entityLookup = $entityLookup;
35
		$this->entityAccessLimit = $entityAccessLimit;
36
	}
37
38
	/**
39
	 * @see EntityLookup::getEntity
40
	 *
41
	 * @param EntityId $entityId
42
	 *
43
	 * @throws EntityAccessLimitException
44
	 * @return EntityDocument
45
	 */
46
	public function getEntity( EntityId $entityId ) {
47
		$entityIdSerialization = $entityId->getSerialization();
48
		if ( !array_key_exists( $entityIdSerialization, $this->entitiesAccessed ) ) {
49 7
			if ( count( $this->entitiesAccessed ) >= $this->entityAccessLimit ) {
50 7
				throw new EntityAccessLimitException(
51 1
					$entityId,
52
					$this->getEntityAccessCount(),
53
					$this->entityAccessLimit
54 6
				);
55 6
			}
56 6
57
			$this->entitiesAccessed[$entityIdSerialization] = true;
58
		}
59
60
		return $this->entityLookup->getEntity( $entityId );
61
	}
62
63
	/**
64
	 * @see EntityLookup::hasEntity
65
	 *
66 4
	 * @throws EntityLookupException
67 4
	 */
68
	public function hasEntity( EntityId $entityId ): bool {
69 4
		return $this->entityLookup->hasEntity( $entityId );
70 4
	}
71 4
72 4
	/**
73
	 * Returns the number of entities already loaded via this object.
74 4
	 *
75 1
	 * @since 2.0
76 1
	 */
77 1
	public function getEntityAccessCount(): int {
78 1
		return count( $this->entitiesAccessed );
79
	}
80
81 4
	/**
82
	 * Resets the list of entities loaded via this object.
83
	 *
84
	 * @since 3.4
85
	 */
86
	public function reset(): void {
87
		$this->entitiesAccessed = [];
88
	}
89
90
	/**
91
	 * Whether an entity has been accessed before via this RestrictedEntityLookup.
92 1
	 *
93 1
	 * @since 2.0
94
	 */
95
	public function entityHasBeenAccessed( EntityId $entityId ): bool {
96
		$entityIdSerialization = $entityId->getSerialization();
97
98
		return array_key_exists( $entityIdSerialization, $this->entitiesAccessed );
99
	}
100
101
}
102