Completed
Push — master ( ad9ce2...b11c6d )
by mw
02:04
created

findLinksBySubject()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 32
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 19
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 32
rs 8.8571
c 0
b 0
f 0
ccs 19
cts 19
cp 1
cc 3
eloc 18
nc 3
nop 1
crap 3
1
<?php
2
3
namespace SBL;
4
5
use SMW\DIWikiPage;
6
use SMW\DIProperty;
7
use SMW\Store;
8
use SMWRequestOptions as RequestOptions;
9
use Title;
10
11
/**
12
 * @license GNU GPL v2+
13
 * @since 1.0
14
 *
15
 * @author mwjames
16
 */
17
class ByPropertyHierarchicalLinksFinder {
18
19
	/**
20
	 * @var Store
21
	 */
22
	private $store;
23
24
	/**
25
	 * @var boolean
26
	 */
27
	private $findClosestDescendant = true;
28
29
	/**
30
	 * @var array
31
	 */
32
	private $propertySearchPatternByNamespace = array();
33
34
	/**
35
	 * @var array
36
	 */
37
	private $antecedentHierarchyLinks = array();
38
39
	/**
40
	 * @var array
41
	 */
42
	private $closestDescendantLinks = array();
43
44
	/**
45
	 * @since 1.0
46
	 *
47
	 * @param Store $store
48
	 */
49 7
	public function __construct( Store $store ) {
50 7
		$this->store = $store;
51 7
	}
52
53
	/**
54
	 * @since 1.0
55
	 *
56
	 * @param boolean $findClosestDescendant
57
	 */
58 5
	public function setFindClosestDescendantState( $findClosestDescendant ) {
59 5
		$this->findClosestDescendant = $findClosestDescendant;
60 5
	}
61
62
	/**
63
	 * @since 1.0
64
	 *
65
	 * @param array $propertySearchPatternByNamespace
66
	 */
67 5
	public function setPropertySearchPatternByNamespace( array $propertySearchPatternByNamespace ) {
68 5
		$this->propertySearchPatternByNamespace = $propertySearchPatternByNamespace;
69 5
	}
70
71
	/**
72
	 * @since  1.0
73
	 *
74
	 * @param DIWikiPage $subject
75
	 */
76 6
	public function findLinksBySubject( DIWikiPage $subject ) {
77
78 6
		if ( !isset( $this->propertySearchPatternByNamespace[ $subject->getNamespace() ] ) ) {
79 1
			return;
80
		}
81
82 5
		$propertySearchPattern = $this->propertySearchPatternByNamespace[ $subject->getNamespace() ];
83
84 5
		$requestOptions = new RequestOptions();
85 5
		$requestOptions->sort = true;
86
87
		// Use 3 as buffer to broaden match possibilities
88 5
		$requestOptions->limit = 3;
89
90 5
		$this->doResolveAntecedentHierarchyRecursively(
91 5
			$subject,
92 5
			$propertySearchPattern,
93
			$requestOptions
94 5
		);
95
96 5
		krsort( $this->antecedentHierarchyLinks );
97
98 5
		if ( !$this->findClosestDescendant ) {
99 3
			return;
100
		}
101
102 2
		$this->doFindClosestDescendantByInverseLink(
103 2
			$subject,
104 2
			$propertySearchPattern,
105
			$requestOptions
106 2
		);
107 2
	}
108
109
	/**
110
	 * @since  1.0
111
	 *
112
	 * @return array
113
	 */
114 6
	public function getParents() {
115 6
		return $this->antecedentHierarchyLinks;
116
	}
117
118
	/**
119
	 * @since  1.0
120
	 *
121
	 * @return array
122
	 */
123 6
	public function getChildren() {
124 6
		return $this->closestDescendantLinks;
125
	}
126
127 5
	private function doResolveAntecedentHierarchyRecursively( DIWikiPage $subject, array $propertySearchPattern, RequestOptions $requestOptions, $currentDepth = 0 ) {
128
129 5
		$dataItem = null;
130
131 5
		if ( $propertySearchPattern === array() ) {
132 1
			return null;
133
		}
134
135 5
		$property = array_shift( $propertySearchPattern );
136
137 5
		$propertyValues = $this->store->getPropertyValues(
138 5
			$subject,
139 5
			DIProperty::newFromUserLabel( $property ),
140
			$requestOptions
141 5
		);
142
143 5
		if ( $propertyValues === array() ) {
144 3
			return null;
145
		}
146
147 2
		foreach ( $propertyValues as $value ) {
148
149 2
			if ( !$value instanceOf DIWikiPage || $subject->equals( $value ) ) {
150 1
				continue;
151
			}
152
153
			// A flat display can only display one parent in its hierarchy
154 1
			$dataItem =  $this->store->getRedirectTarget( $value );
155 1
			break;
156 2
		}
157
158 2
		if ( $dataItem === null ) {
159 1
			return null;
160
		}
161
162 1
		$this->antecedentHierarchyLinks[] = $dataItem;
163 1
		$currentDepth++;
164
165 1
		return $this->doResolveAntecedentHierarchyRecursively(
166 1
			$dataItem,
0 ignored issues
show
Compatibility introduced by
$dataItem of type object<SMWDataItem> is not a sub-type of object<SMW\DIWikiPage>. It seems like you assume a child class of the class SMWDataItem to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
167 1
			$propertySearchPattern,
168 1
			$requestOptions,
169
			$currentDepth
170 1
		);
171
	}
172
173 2
	private function doFindClosestDescendantByInverseLink( DIWikiPage $subject, array $propertySearchPattern, RequestOptions $requestOptions ) {
174
175 2
		$property = array_shift( $propertySearchPattern );
176
177 2
		$property = DIProperty::newFromUserLabel( $property );
178
179 2
		if ( $property->findPropertyTypeId() !== '_wpg' ) {
180 1
			return;
181
		}
182
183
		// Limit the search
184 1
		$requestOptions->limit = 20;
185
186 1
		$children = $this->store->getPropertySubjects(
187 1
			$property,
188 1
			$subject,
189
			$requestOptions
190 1
		);
191
192 1
		foreach ( $children as $dataItem ) {
193
194 1
			if ( $subject->equals( $dataItem ) ) {
195 1
				continue;
196
			}
197
198 1
			$this->closestDescendantLinks[] = $this->store->getRedirectTarget(
199
				$dataItem
200 1
			);
201 1
		}
202 1
	}
203
204
}
205