WikibaseEntityIdParser::getEntityIdsForValue()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3.1825

Importance

Changes 0
Metric Value
dl 0
loc 14
ccs 8
cts 11
cp 0.7272
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 11
nc 3
nop 1
crap 3.1825
1
<?php
2
3
namespace PPP\Wikidata\ValueParsers;
4
5
use InvalidArgumentException;
6
use ValueParsers\ParserOptions;
7
use ValueParsers\StringValueParser;
8
use ValueParsers\ValueParser;
9
use Wikibase\DataModel\Entity\EntityIdValue;
10
use Wikibase\DataModel\Entity\Item;
11
use Wikibase\DataModel\Entity\ItemId;
12
use Wikibase\DataModel\Entity\PropertyId;
13
use Wikibase\DataModel\Snak\PropertyValueSnak;
14
use Wikibase\DataModel\Statement\Statement;
15
use Wikibase\DataModel\Term\Term;
16
use Wikibase\EntityStore\EntityStore;
17
18
/**
19
 * Try to find a Wikibase entities from a given string.
20
 *
21
 * @licence AGPLv3+
22
 * @author Thomas Pellissier Tanon
23
 */
24
class WikibaseEntityIdParser extends StringValueParser {
25
26
	const FORMAT_NAME = 'wikibase-entity';
27
28
	private static $INSTANCES_TO_FILTER = array('Q4167410', 'Q17362920', 'Q4167836', 'Q13406463', 'Q11266439', 'Q14204246', 'Q21286738');
29
30
	const INSTANCEOF_PID = 'P31';
31
32
	/**
33
	 * Identifier for the option that holds the type of entity the parser should looks for.
34
	 */
35
	const OPT_ENTITY_TYPE = 'type';
36
37
	/**
38
	 * @var EntityStore
39
	 */
40
	private $entityStore;
41
42
	/**
43
	 * @param EntityStore $entityStore
44
	 * @param ParserOptions|null $options
45
	 */
46 9
	public function __construct(EntityStore $entityStore, ParserOptions $options = null) {
47 9
		$options->requireOption(self::OPT_ENTITY_TYPE);
0 ignored issues
show
Bug introduced by
It seems like $options is not always an object, but can also be of type null. Maybe add an additional type check?

If a variable is not always an object, we recommend to add an additional type check to ensure your method call is safe:

function someFunction(A $objectMaybe = null)
{
    if ($objectMaybe instanceof A) {
        $objectMaybe->doSomething();
    }
}
Loading history...
48
49 9
		$this->entityStore = $entityStore;
50 9
		parent::__construct($options);
51 9
	}
52
53 10
	protected function stringParse($value) {
54 10
		if($value === '') {
55 1
			return array();
56
		}
57
58 9
		return $this->entityIdsToEntityIdValues($this->getEntityIdsForValue($value));
59
	}
60
61 9
	private function getEntityIdsForValue($value) {
62 9
		$languageCode = $this->getOption(ValueParser::OPT_LANG);
63 9
		$term = new Term($languageCode, $value);
64
65 9
		$entityType = $this->getOption(self::OPT_ENTITY_TYPE);
66
		switch($entityType) {
67 9
			case 'item':
68 7
				return $this->getItemIdsForTerm($term);
69 2
			case 'property':
70 2
				return $this->getPropertyIdsForTerm($term);
71
			default:
72
				throw new InvalidArgumentException('Unknown entity type ' . $entityType);
73
		}
74
	}
75
76 7
	private function getItemIdsForTerm(Term $term) {
77 7
		$itemIds = $this->filterItemIds(
78 7
			$this->entityStore->getItemIdForTermLookup()->getItemIdsForTerm($term)
79 7
		);
80
81
		try {
82 7
			$itemIds[] = new ItemId($term->getText());
83 7
		} catch(InvalidArgumentException $e) {
84
			//The term is not a valid QID
85
		}
86
87 7
		return $this->sortItemIds(array_unique($itemIds));
88
	}
89
90 2
	private function getPropertyIdsForTerm(Term $term) {
91 2
		$propertyIds = $this->entityStore->getPropertyIdForTermLookup()->getPropertyIdsForTerm($term);
92
93
		try {
94 2
			$propertyIds[] = new PropertyId($term->getText());
95 2
		} catch(InvalidArgumentException $e) {
96
			//The term is not a valid PID
97
		}
98
99 2
		return array_unique($propertyIds);
100
	}
101
102 7
	private function filterItemIds(array $itemIds) {
103 7
		$entities = $this->entityStore->getEntityDocumentLookup()->getEntityDocumentsForIds($itemIds);
104 7
		$filtered = array();
105
106 7
		foreach($entities as $entity) {
107 6
			if($entity instanceof Item && !$this->shouldItemBeIgnored($entity)) {
108 6
				$filtered[] = $entity->getId();
109 6
			}
110 7
		}
111
112 7
		return $filtered;
113
	}
114
115 6
	private function shouldItemBeIgnored(Item $item) {
116
		/** @var Statement $statement */
117 6
		foreach($item->getStatements()->getByPropertyId(new PropertyId(self::INSTANCEOF_PID)) as $statement) {
118 6
			$mainSnak = $statement->getMainSnak();
119
			if(
120 6
				$mainSnak instanceof PropertyValueSnak &&
121 6
				$mainSnak->getDataValue() instanceof EntityIdValue &&
122 6
				in_array($mainSnak->getDataValue()->getEntityId()->getSerialization(), self::$INSTANCES_TO_FILTER)
123 6
			) {
124 5
				return true;
125
			}
126 6
		}
127
128 6
		return false;
129
	}
130
131 9
	private function entityIdsToEntityIdValues(array $entityIds) {
132 9
		$values = array();
133 9
		foreach($entityIds as $entityId) {
134 8
			$values[] = new EntityIdValue($entityId);
135 9
		}
136
137 9
		return $values;
138
	}
139
140
141 7
	private function sortItemIds(array $itemIds) {
142 7
		usort(
143 7
			$itemIds,
144 3
			function(ItemId $a, ItemId $b) {
145 3
				return $a->getNumericId() - $b->getNumericId();
146
			}
147 7
		);
148
149 7
		return $itemIds;
150
	}
151
}
152