1 | <?php |
||
16 | class ReferenceListOutputRenderer { |
||
17 | |||
18 | /** |
||
19 | * @var CitationResourceMatchFinder |
||
20 | */ |
||
21 | private $citationResourceMatchFinder; |
||
22 | |||
23 | /** |
||
24 | * @var CitationReferencePositionJournal |
||
25 | */ |
||
26 | private $citationReferencePositionJournal; |
||
27 | |||
28 | /** |
||
29 | * @var HtmlColumnListRenderer |
||
30 | */ |
||
31 | private $htmlColumnListRenderer; |
||
32 | |||
33 | /** |
||
34 | * @var integer |
||
35 | */ |
||
36 | private $numberOfReferenceListColumns = 0; |
||
37 | |||
38 | /** |
||
39 | * @var boolean |
||
40 | */ |
||
41 | private $browseLinkToCitationResourceVisibility = true; |
||
42 | |||
43 | /** |
||
44 | * @var string |
||
45 | */ |
||
46 | private $referenceListType = 'ol'; |
||
47 | |||
48 | /** |
||
49 | * @var string |
||
50 | */ |
||
51 | private $referenceListHeader = ''; |
||
52 | |||
53 | /** |
||
54 | * @var string |
||
55 | */ |
||
56 | private $referenceListHeaderTocId = ''; |
||
57 | |||
58 | /** |
||
59 | * @var integer |
||
60 | */ |
||
61 | private $citationReferenceCaptionFormat = SCI_CITEREF_NUM; |
||
62 | |||
63 | /** |
||
64 | * @var integer |
||
65 | */ |
||
66 | private $responsiveMonoColumnCharacterBoundLength = 400; |
||
67 | |||
68 | /** |
||
69 | * @since 1.0 |
||
70 | * |
||
71 | * @param CitationResourceMatchFinder $citationResourceMatchFinder |
||
72 | * @param CitationReferencePositionJournal $citationReferencePositionJournal |
||
73 | * @param HtmlColumnListRenderer $htmlColumnListRenderer |
||
74 | */ |
||
75 | 12 | public function __construct( CitationResourceMatchFinder $citationResourceMatchFinder, CitationReferencePositionJournal $citationReferencePositionJournal, HtmlColumnListRenderer $htmlColumnListRenderer ) { |
|
80 | |||
81 | /** |
||
82 | * @since 1.0 |
||
83 | * |
||
84 | * @param integer $citationReferenceCaptionFormat |
||
85 | */ |
||
86 | 9 | public function setCitationReferenceCaptionFormat( $citationReferenceCaptionFormat ) { |
|
89 | |||
90 | /** |
||
91 | * @since 1.2 |
||
92 | * |
||
93 | * @param integer $responsiveMonoColumnCharacterBoundLength |
||
94 | */ |
||
95 | 10 | public function setResponsiveMonoColumnCharacterBoundLength( $responsiveMonoColumnCharacterBoundLength ) { |
|
98 | |||
99 | /** |
||
100 | * @since 1.0 |
||
101 | * |
||
102 | * @param integer $numberOfReferenceListColumns |
||
103 | */ |
||
104 | 11 | public function setNumberOfReferenceListColumns( $numberOfReferenceListColumns ) { |
|
107 | |||
108 | /** |
||
109 | * @since 1.0 |
||
110 | * |
||
111 | * @param integer |
||
112 | */ |
||
113 | 10 | public function getNumberOfReferenceListColumns() { |
|
116 | |||
117 | /** |
||
118 | * @since 1.0 |
||
119 | * |
||
120 | * @param string $referenceListType |
||
121 | */ |
||
122 | 10 | public function setReferenceListType( $referenceListType ) { |
|
125 | |||
126 | /** |
||
127 | * @since 1.0 |
||
128 | * |
||
129 | * @param string |
||
130 | */ |
||
131 | 10 | public function getReferenceListType() { |
|
134 | |||
135 | /** |
||
136 | * @since 1.0 |
||
137 | * |
||
138 | * @param boolean $browseLinkToCitationResourceVisibility |
||
139 | */ |
||
140 | 11 | public function setBrowseLinkToCitationResourceVisibility( $browseLinkToCitationResourceVisibility ) { |
|
143 | |||
144 | /** |
||
145 | * @since 1.0 |
||
146 | * |
||
147 | * @param boolean |
||
148 | */ |
||
149 | 10 | public function getBrowseLinkToCitationResourceVisibility() { |
|
152 | |||
153 | /** |
||
154 | * @since 1.0 |
||
155 | * |
||
156 | * @param string $referenceListHeader |
||
157 | */ |
||
158 | 5 | public function setReferenceListHeader( $referenceListHeader ) { |
|
161 | |||
162 | /** |
||
163 | * @since 1.0 |
||
164 | * |
||
165 | * @param string $referenceListHeaderTocId |
||
166 | */ |
||
167 | 5 | public function setReferenceListHeaderTocId( $referenceListHeaderTocId ) { |
|
170 | |||
171 | /** |
||
172 | * @since 1.0 |
||
173 | * |
||
174 | * @param DIWikiPage $subject |
||
175 | * @param array|null $referenceList |
||
176 | * |
||
177 | * @return string |
||
178 | */ |
||
179 | 10 | public function doRenderReferenceListFor( DIWikiPage $subject, array $referenceList = null ) { |
|
180 | |||
181 | 10 | if ( $referenceList !== null ) { |
|
182 | 2 | $journal = $this->citationReferencePositionJournal->buildJournalForUnboundReferenceList( |
|
183 | 2 | $referenceList |
|
184 | ); |
||
185 | } else { |
||
186 | 9 | $journal = $this->citationReferencePositionJournal->getJournalBySubject( |
|
187 | 9 | $subject |
|
188 | ); |
||
189 | } |
||
190 | |||
191 | 10 | if ( $journal !== null ) { |
|
192 | 9 | return $this->createHtmlFromJournal( $journal ); |
|
193 | } |
||
194 | |||
195 | 1 | return ''; |
|
196 | } |
||
197 | |||
198 | /** |
||
199 | * The journal is expected to contain: |
||
200 | * |
||
201 | * 'total' => a number |
||
202 | * 'reference-list' => array of hashes for references used |
||
203 | * 'reference-pos' => individual reference links (1-a, 1-b) assigned to a hash |
||
204 | */ |
||
205 | 9 | private function createHtmlFromJournal( array $journal ) { |
|
206 | |||
207 | 9 | $listOfFormattedReferences = []; |
|
208 | 9 | $targetList = []; |
|
209 | 9 | $length = 0; |
|
210 | |||
211 | 9 | foreach ( $journal['reference-pos'] as $hash => $linkList ) { |
|
212 | |||
213 | 9 | $citationText = ''; |
|
214 | // Get the "human" readable citation key/reference from the hashmap |
||
215 | // intead of trying to access the DB/Store |
||
216 | 9 | $reference = $journal['reference-list'][$hash]; |
|
217 | |||
218 | 9 | list( $subjects, $citationText ) = $this->findCitationTextFor( |
|
219 | 9 | $reference |
|
220 | ); |
||
221 | |||
222 | 9 | $length += mb_strlen( $citationText ); |
|
223 | |||
224 | 9 | $flatHtmlReferenceLinks = $this->createFlatHtmlListForReferenceLinks( |
|
225 | 9 | $linkList, |
|
226 | 9 | $hash |
|
227 | ); |
||
228 | |||
229 | 9 | $browseLinks = $this->createBrowseLinksWith( |
|
230 | 9 | $subjects, |
|
231 | 9 | $reference, |
|
232 | 9 | $citationText |
|
233 | ); |
||
234 | |||
235 | 9 | if ( method_exists( $this->htmlColumnListRenderer, 'setItemAttributes' ) ) { |
|
236 | $attribs = [ |
||
237 | 9 | 'class' => 'scite-referencelinks' |
|
238 | ]; |
||
239 | } else { |
||
240 | $attribs = [ |
||
241 | 'id' => 'scite-'. $hash, |
||
242 | 'class' => 'scite-referencelinks' |
||
243 | ]; |
||
244 | } |
||
245 | |||
246 | 9 | $ref = Html::rawElement( |
|
247 | 9 | 'span', |
|
248 | 9 | $attribs, |
|
249 | 9 | $flatHtmlReferenceLinks |
|
250 | ) . |
||
251 | 9 | ( $flatHtmlReferenceLinks !== '' ? ' ' : '' ) . |
|
252 | 9 | Html::rawElement( |
|
253 | 9 | 'span', |
|
254 | [ |
||
255 | 9 | 'class' => 'scite-citation' |
|
256 | ], |
||
257 | 9 | ( $browseLinks !== '' ? $browseLinks . ' ' : '' ) . Html::rawElement( |
|
258 | 9 | 'span', |
|
259 | 9 | [ 'class' => 'scite-citation-text' ], |
|
260 | 9 | $citationText |
|
261 | ) |
||
262 | ); |
||
263 | |||
264 | 9 | $listOfFormattedReferences[] = $ref; |
|
265 | 9 | $targetList[md5($ref)] = [ 'id' => 'scite-'. $hash ]; |
|
266 | } |
||
267 | |||
268 | 9 | return $this->makeList( $listOfFormattedReferences, $targetList, $length ); |
|
269 | } |
||
270 | |||
271 | 9 | private function makeList( $listOfFormattedReferences, $targetList, $length ) { |
|
272 | |||
273 | 9 | $monoClass = ( $length > $this->responsiveMonoColumnCharacterBoundLength ? '' : '-mono' ); |
|
274 | |||
275 | // #33, #32 |
||
276 | 9 | $this->htmlColumnListRenderer->setColumnListClass( |
|
277 | 9 | 'scite-referencelist' . ( $this->numberOfReferenceListColumns == 0 ? ' responsive-list' . $monoClass : '' ) |
|
278 | ); |
||
279 | |||
280 | 9 | $this->htmlColumnListRenderer->setListType( $this->referenceListType ); |
|
281 | 9 | $this->htmlColumnListRenderer->addContentsByNoIndex( $listOfFormattedReferences ); |
|
282 | |||
283 | 9 | if ( method_exists( $this->htmlColumnListRenderer, 'setItemAttributes' ) ) { |
|
284 | 9 | $this->htmlColumnListRenderer->setItemAttributes( $targetList ); |
|
285 | } |
||
286 | |||
287 | 9 | if ( $this->numberOfReferenceListColumns == 0 ) { |
|
288 | 1 | $this->htmlColumnListRenderer->setColumnClass( 'scite-referencelist-columns-responsive'. $monoClass ); |
|
289 | } else { |
||
290 | 8 | $this->htmlColumnListRenderer->setNumberOfColumns( $this->numberOfReferenceListColumns ); |
|
291 | 8 | $this->htmlColumnListRenderer->setColumnClass( 'scite-referencelist-columns-fixed' ); |
|
292 | } |
||
293 | |||
294 | 9 | if ( $this->referenceListHeader === '' ) { |
|
295 | 8 | $this->referenceListHeader = wfMessage( 'sci-referencelist-header' )->text(); |
|
296 | } |
||
297 | |||
298 | 9 | if ( $this->referenceListHeaderTocId === '' ) { |
|
299 | 9 | $this->referenceListHeaderTocId = $this->referenceListHeader; |
|
300 | } |
||
301 | |||
302 | 9 | return Html::rawElement( |
|
303 | 9 | 'div', |
|
304 | [ |
||
305 | 9 | 'class' => 'scite-content' |
|
306 | ], |
||
307 | 9 | Html::element( |
|
308 | 9 | 'h2', |
|
309 | [ |
||
310 | 9 | 'id' => $this->referenceListHeaderTocId |
|
311 | ], |
||
312 | 9 | $this->referenceListHeader |
|
313 | 9 | ) . "\n" . $this->htmlColumnListRenderer->getHtml() . "\n" |
|
314 | ); |
||
315 | } |
||
316 | |||
317 | 9 | private function findCitationTextFor( $reference ) { |
|
318 | |||
319 | 9 | list( $subjects, $text ) = $this->citationResourceMatchFinder->findCitationTextFor( |
|
320 | 9 | $reference |
|
321 | ); |
||
322 | |||
323 | // Using Message:parse as shortcut to ensure the text is appropriately |
||
324 | // parsed and escaped which saves the trouble to deal with Parser stubobject |
||
325 | return [ |
||
326 | 9 | $subjects, |
|
327 | 9 | wfMessage( 'sci-referencelist-text', $text )->parse() |
|
328 | ]; |
||
329 | } |
||
330 | |||
331 | 9 | private function createFlatHtmlListForReferenceLinks( array $linkList, $referenceHash ) { |
|
332 | |||
333 | 9 | $referenceLinks = []; |
|
334 | 9 | $class = 'scite-backlinks'; |
|
335 | |||
336 | 9 | foreach ( $linkList as $value ) { |
|
337 | |||
338 | 7 | $isOneLinkElement = count( $linkList ) == 1; |
|
339 | |||
340 | // Split a value of 1-a, 1-b, 2-a into its parts |
||
341 | 7 | list( $major, $minor ) = explode( '-', $value ); |
|
342 | |||
343 | // Show a simple link similar to what is done on en.wp |
||
344 | // for a one-link-reference |
||
345 | 7 | if ( $isOneLinkElement ) { |
|
346 | 6 | $minor = '^'; |
|
347 | 6 | $class = 'scite-backlink'; |
|
348 | } |
||
349 | |||
350 | // Only display the "full" number for the combination of UL/SCI_CITEREF_NUM |
||
351 | 7 | if ( $this->referenceListType === 'ul' && $this->citationReferenceCaptionFormat === SCI_CITEREF_NUM ) { |
|
352 | 1 | $minor = $isOneLinkElement ? $major : str_replace( '-', '.', $value ); |
|
353 | } |
||
354 | |||
355 | 7 | $referenceLinks[] = Html::rawElement( |
|
356 | 7 | 'a', |
|
357 | [ |
||
358 | 7 | 'href' => "#scite-ref-{$referenceHash}-" . $value, |
|
359 | 7 | 'class' => $class, |
|
360 | 7 | 'data-citeref-format' => $this->citationReferenceCaptionFormat === SCI_CITEREF_NUM ? 'number' : 'key' |
|
361 | ], |
||
362 | 7 | $minor |
|
363 | ); |
||
364 | } |
||
365 | |||
366 | 9 | return implode( ' ', $referenceLinks ); |
|
367 | } |
||
368 | |||
369 | 9 | private function createBrowseLinksWith( array $subjects, $reference, $citationText ) { |
|
397 | |||
398 | } |
||
399 |