Passed
Pull Request — master (#187)
by Amir
02:29
created

RestrictedEntityLookup::getEntity()   B

Complexity

Conditions 4
Paths 5

Size

Total Lines 23
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 4

Importance

Changes 0
Metric Value
dl 0
loc 23
ccs 10
cts 10
cp 1
rs 8.7972
c 0
b 0
f 0
cc 4
eloc 14
nc 5
nop 1
crap 4
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+
19
 * @author Marius Hoch < [email protected] >
20
 */
21
class RestrictedEntityLookup implements EntityLookup {
22
23
	/**
24
	 * @var EntityLookup
25
	 */
26
	private $entityLookup;
27
28
	/**
29
	 * @var int
30
	 */
31
	private $entityAccessLimit;
32
33
	/**
34
	 * @var bool[] Entity id serialization => bool
35
	 */
36
	private $entitiesAccessed = [];
37
38
	/**
39
	 * @var int
40
	 */
41
	private $entityAccessCount = 0;
42
43
	/**
44
	 * @var string[]
45
	 */
46
	private $disabledEntityTypes = [];
47
48
	/**
49 7
	 * @param EntityLookup $entityLookup
50 7
	 * @param int $entityAccessLimit
51 1
	 *
52
	 * @throws InvalidArgumentException
53
	 */
54 6
	public function __construct( EntityLookup $entityLookup, $entityAccessLimit ) {
55 6
		if ( !is_int( $entityAccessLimit ) || $entityAccessLimit < 1 ) {
56 6
			throw new InvalidArgumentException( '$entityAccessLimit must be a positive integer' );
57
		}
58
59
		$this->entityLookup = $entityLookup;
60
		$this->entityAccessLimit = $entityAccessLimit;
61
	}
62
63
	/**
64
	 * @see EntityLookup::getEntity
65
	 *
66 4
	 * @param EntityId $entityId
67 4
	 *
68
	 * @throws EntityAccessLimitException
69 4
	 * @return EntityDocument
70 4
	 */
71 4
	public function getEntity( EntityId $entityId ) {
72 4
		$entityIdSerialization = $entityId->getSerialization();
73
74 4
		if ( in_array( $entityId->getEntityType(), $this->disabledEntityTypes ) ) {
75 1
			throw new EntityLookupException(
76 1
				$entityId,
77 1
				'Entity access for this type of entity is disabled: ' . $entityId->getEntityType()
78 1
			);
79
		}
80
		if ( !array_key_exists( $entityIdSerialization, $this->entitiesAccessed ) ) {
81 4
			$this->entityAccessCount++;
82
			$this->entitiesAccessed[$entityIdSerialization] = true;
83
		}
84
85
		if ( $this->entityAccessCount > $this->entityAccessLimit ) {
86
			throw new EntityAccessLimitException(
87
				$entityId,
88
				'To many entities loaded, must not load more than ' . $this->entityAccessLimit . ' entities.'
89
			);
90
		}
91
92 1
		return $this->entityLookup->getEntity( $entityId );
93 1
	}
94
95
	/**
96
	 * @see EntityLookup::hasEntity
97
	 *
98
	 * @param EntityId $entityId
99
	 *
100
	 * @return bool
101
	 * @throws EntityLookupException
102
	 */
103 1
	public function hasEntity( EntityId $entityId ) {
104 1
		return $this->entityLookup->hasEntity( $entityId );
105
	}
106
107
	/**
108
	 * Returns the number of entities already loaded via this object.
109
	 *
110
	 * @since 2.0
111
	 *
112
	 * @return int
113
	 */
114
	public function getEntityAccessCount() {
115
		return $this->entityAccessCount;
116 1
	}
117 1
118
	/**
119 1
	 * Resets the number and list of entities loaded via this object.
120
	 *
121
	 * @since 3.4
122
	 */
123
	public function reset() {
124
		$this->entityAccessCount = 0;
125
		$this->entitiesAccessed = [];
126
	}
127
128
	/**
129
	 * Whether an entity has been accessed before via this RestrictedEntityLookup.
130
	 *
131
	 * @since 2.0
132
	 *
133
	 * @param EntityId $entityId
134
	 *
135
	 * @return bool
136
	 */
137
	public function entityHasBeenAccessed( EntityId $entityId ) {
138
		$entityIdSerialization = $entityId->getSerialization();
139
140
		return array_key_exists( $entityIdSerialization, $this->entitiesAccessed );
141
	}
142
143
	/**
144
	 * @param string[] $disabledEntityTypes
145
	 */
146
	public function setDisabledEntityTypes( array $disabledEntityTypes ) {
147
		$this->disabledEntityTypes = $disabledEntityTypes;
148
	}
149
150
}
151