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

getSubstituteLinksParentsOnDiscoveryFallback()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 10
rs 9.4285
c 0
b 0
f 0
ccs 5
cts 5
cp 1
cc 3
eloc 5
nc 2
nop 2
crap 3
1
<?php
2
3
namespace SBL;
4
5
use SMW\DIWikiPage;
6
use SMW\DataValueFactory;
7
use Title;
8
use Html;
9
use DummyLinker;
10
11
/**
12
 * @license GNU GPL v2+
13
 * @since 1.0
14
 *
15
 * @author mwjames
16
 */
17
class HtmlBreadcrumbLinksBuilder {
18
19
	/**
20
	 * @var ByPropertyHierarchicalLinksFinder
21
	 */
22
	private $byPropertyHierarchicalLinksFinder;
23
24
	/**
25
	 * @var BySubpageLinksFinder
26
	 */
27
	private $bySubpageLinksFinder;
28
29
	/**
30
	 * @var DataValueFactory
31
	 */
32
	private $dataValueFactory;
33
34
	/**
35
	 * @var DummyLinker|null
36
	 */
37
	private $linker = null;
38
39
	/**
40
	 * @var string
41
	 */
42
	private $breadcrumbs = '';
43
44
	/**
45
	 * @var string
46
	 */
47
	private $breadcrumbTrailStyleClass = 'sbl-breadcrumb-trail-boxed';
48
49
	/**
50
	 * @var string
51
	 */
52
	private $breadcrumbDividerStyleClass = 'sbl-breadcrumb-arrow';
53
54
	/**
55
	 * @var boolean
56
	 */
57
	private $isRTL = false;
58
59
	/**
60
	 * @var boolean
61
	 */
62
	private $hasChildren = false;
63
64
	/**
65
	 * @var boolean
66
	 */
67
	private $hideSubpageParent = false;
68
69
	/**
70
	 * @since 1.0
71
	 *
72
	 * @param ByPropertyHierarchicalLinksFinder $byPropertyHierarchicalLinksFinder
73
	 * @param BySubpageLinksFinder $bySubpageLinksFinder
74
	 */
75 7
	public function __construct( ByPropertyHierarchicalLinksFinder $byPropertyHierarchicalLinksFinder, BySubpageLinksFinder $bySubpageLinksFinder ) {
76 7
		$this->byPropertyHierarchicalLinksFinder = $byPropertyHierarchicalLinksFinder;
77 7
		$this->bySubpageLinksFinder = $bySubpageLinksFinder;
78 7
		$this->dataValueFactory = DataValueFactory::getInstance();
79 7
	}
80
81
	/**
82
	 * @since 1.0
83
	 *
84
	 * @param DummyLinker $linker
85
	 */
86 1
	public function setLinker( DummyLinker $linker ) {
87 1
		$this->linker = $linker;
88 1
	}
89
90
	/**
91
	 * @since 1.3
92
	 *
93
	 * @param DataValueFactory $dataValueFactory
94
	 */
95 1
	public function setDataValueFactory( DataValueFactory $dataValueFactory ) {
96 1
		$this->dataValueFactory = $dataValueFactory;
97 1
	}
98
99
	/**
100
	 * @since 1.0
101
	 *
102
	 * @param string $breadcrumbTrailStyleClass
103
	 */
104 1
	public function setBreadcrumbTrailStyleClass( $breadcrumbTrailStyleClass ) {
105 1
		$this->breadcrumbTrailStyleClass = $breadcrumbTrailStyleClass;
106 1
	}
107
108
	/**
109
	 * @since 1.0
110
	 *
111
	 * @param string $breadcrumbDividerStyleClass
112
	 */
113 1
	public function setBreadcrumbDividerStyleClass( $breadcrumbDividerStyleClass ) {
114 1
		$this->breadcrumbDividerStyleClass = $breadcrumbDividerStyleClass;
115 1
	}
116
117
	/**
118
	 * @since 1.3
119
	 *
120
	 * @param boolean $hideSubpageParent
121
	 */
122 1
	public function hideSubpageParent( $hideSubpageParent ) {
123 1
		$this->hideSubpageParent = $hideSubpageParent;
124 1
	}
125
126
	/**
127
	 * @since 1.0
128
	 *
129
	 * @param boolean $isRTL
130
	 */
131 1
	public function isRTL( $isRTL ) {
132 1
		$this->isRTL = $isRTL;
133 1
	}
134
135
	/**
136
	 * @since  1.0
137
	 *
138
	 * @param Title $title
139
	 */
140 5
	public function buildBreadcrumbs( Title $title ) {
141
142 5
		if ( $title->isRedirect() ) {
143 1
			return;
144
		}
145
146
		// Ensure no subobject is used by replacing the fragment
147 4
		$title->setFragment( '' );
148 4
		$subject = DIWikiPage::newFromTitle( $title );
149
150 4
		$this->byPropertyHierarchicalLinksFinder->findLinksBySubject( $subject );
151
152 4
		$parents = $this->byPropertyHierarchicalLinksFinder->getParents();
153 4
		$children = $this->byPropertyHierarchicalLinksFinder->getChildren();
154
155 4
		$parents = $this->getSubstituteLinksParentsOnDiscoveryFallback(
156 4
			$subject,
157
			$parents
158 4
		);
159
160 4
		$this->formatToFlatList( $subject, $parents, $children );
161 4
	}
162
163
	/**
164
	 * @since 1.0
165
	 *
166
	 * @return string
167
	 */
168 3
	public function getHtml() {
169
170 3
		if ( $this->breadcrumbs === '' ) {
171 1
			return $this->breadcrumbs;
172
		}
173
174 2
		return Html::rawElement( 'div', array(
175 2
			'id'    => 'sbl-breadcrumbs',
176 2
			'class' => $this->breadcrumbTrailStyleClass,
177 2
			'dir'   => $this->isRTL ? 'rtl' : 'ltr' ),
178 2
			$this->breadcrumbs
179 2
		);
180
	}
181
182 4
	private function getSubstituteLinksParentsOnDiscoveryFallback( $subject, $parents ) {
183
184 4
		if ( $parents !== array() || !$this->bySubpageLinksFinder->isDiscoveryFallback() ) {
185 3
			return $parents;
186
		}
187
188 1
		$this->bySubpageLinksFinder->findLinksBySubject( $subject );
189
190 1
		return $this->bySubpageLinksFinder->getParents();
191
	}
192
193 4
	private function formatToFlatList( DIWikiPage $subject, $parents, $children ) {
194
195 4
		$parent = '';
196
197 4
		foreach ( $parents as $breadcrumb ) {
198 3
			$parent .= $this->wrapHtml( 'parent', $this->getDvShortHtmlText( $breadcrumb, $this->linker ) ) .  $this->wrapHtml( 'right' );
199 4
		}
200
201 4
		$this->hasChildren = count( $children ) > 1;
202
203 4
		list( $child, $data ) = $this->findElementsForChildren( $children  );
204
205 4
		if ( $parent !== '' || $child !== '' ) {
206 3
			$this->breadcrumbs = $parent . $this->wrapHtml( 'location', $this->getDvShortHtmlText( $subject ) ) . $child . $this->addHtmlDataElement( $data );
207 3
		}
208 4
	}
209
210 3
	private function getDvShortHtmlText( $subject, $linker = null ) {
211
212 3
		$displayTitle = '';
213
214 3
		$dataValue = $this->dataValueFactory->newDataValueByItem(
215
			$subject
216 3
		);
217
218
		// 2.4+
219 3
		if ( method_exists( $dataValue , 'getDisplayTitle' ) ) {
220 3
			$displayTitle = $dataValue->getDisplayTitle();
221 3
		}
222
223 3
		$dataValue->setCaption(
224 3
			$this->hideSubpageParent && $displayTitle === '' ? $subject->getTitle()->getSubpageText() : false
225 3
		);
226
227
		// Make sure non-linked titles use the _DTITLE, if available
228 3
		if ( $linker === null && $displayTitle !== '' ) {
229 1
			$dataValue->setCaption( $displayTitle );
230 1
		}
231
232 3
		return $dataValue->getShortHtmlText( $linker );
233
	}
234
235 3
	private function wrapHtml( $subClass, $html = '' ) {
236 3
		return Html::rawElement( 'span', array(
237 3
				'class' => $this->breadcrumbDividerStyleClass . '-' . $subClass,
238 3
				'style' => $subClass === 'child' && $this->hasChildren ? 'font-style:italic;' : ''
239 3
			),
240
			$html
241 3
		);
242
	}
243
244 4
	private function findElementsForChildren( array $children ) {
245
246 4
		$child = '';
247 4
		$data = '';
248
249 4
		foreach ( $children as $breadcrumb ) {
250
251
			// The first child is added as visible element while others
252
			// are added as data-element
253 1
			if ( $child !== '' ) {
254 1
				$this->hasChildren = true;
255 1
				$data .=  $this->addHtmlListElement( $this->getDvShortHtmlText( $breadcrumb, $this->linker ) );
256 1
				continue;
257
			}
258
259 1
			$child .=  $this->wrapHtml( 'left' ) . $this->wrapHtml( 'child', $this->getDvShortHtmlText( $breadcrumb, $this->linker ) );
260 4
		}
261
262 4
		return array( $child, $data );
263
	}
264
265 1
	private function addHtmlListElement( $html = '' ) {
266 1
		return Html::rawElement( 'li', array(), $html );
267
	}
268
269 3
	private function addHtmlDataElement( $data = '' ) {
270
271 3
		if ( $data === '' ) {
272 2
			return '';
273
		}
274
275 1
		return Html::rawElement( 'span', array(
276 1
			'class' => 'sbl-breadcrumb-children',
277 1
			'data-children' => '<ul class="sbl-breadcrumb-children-list">' . $data . '</ul>' ),
278
			''
279 1
		);
280
	}
281
282
}
283