Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
89.19% |
33 / 37 |
|
60.00% |
3 / 5 |
CRAP | |
0.00% |
0 / 1 |
CirrusShowSearchHitHooksHandler | |
89.19% |
33 / 37 |
|
60.00% |
3 / 5 |
9.10 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
onShowSearchHit | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
showEntityResultHit | |
100.00% |
15 / 15 |
|
100.00% |
1 / 1 |
2 | |||
onShowSearchHitTitle | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
getEntityLink | |
92.86% |
13 / 14 |
|
0.00% |
0 / 1 |
2.00 |
1 | <?php |
2 | |
3 | declare( strict_types = 1 ); |
4 | |
5 | namespace Wikibase\Search\Elastic\Hooks; |
6 | |
7 | use HtmlArmor; |
8 | use MediaWiki\Context\IContextSource; |
9 | use MediaWiki\Html\Html; |
10 | use MediaWiki\Search\Hook\ShowSearchHitHook; |
11 | use MediaWiki\Search\Hook\ShowSearchHitTitleHook; |
12 | use MediaWiki\Specials\SpecialSearch; |
13 | use MediaWiki\Title\Title; |
14 | use Wikibase\Lib\Store\EntityIdLookup; |
15 | use Wikibase\Repo\Hooks\Formatters\EntityLinkFormatterFactory; |
16 | use Wikibase\Repo\Hooks\ShowSearchHitHandler; |
17 | use Wikibase\Search\Elastic\EntityResult; |
18 | |
19 | /** |
20 | * Handler to format entities in the search results |
21 | * |
22 | * @license GPL-2.0-or-later |
23 | * @author Matěj Suchánek |
24 | * @author Daniel Kinzler |
25 | * @author Stas Malyshev |
26 | */ |
27 | class CirrusShowSearchHitHooksHandler implements ShowSearchHitHook, ShowSearchHitTitleHook { |
28 | |
29 | private EntityLinkFormatterFactory $linkFormatterFactory; |
30 | private EntityIdLookup $entityIdLookup; |
31 | |
32 | /** |
33 | * @param EntityIdLookup $entityIdLookup |
34 | * @param EntityLinkFormatterFactory $linkFormatterFactory |
35 | */ |
36 | public function __construct( |
37 | EntityIdLookup $entityIdLookup, |
38 | EntityLinkFormatterFactory $linkFormatterFactory |
39 | ) { |
40 | $this->entityIdLookup = $entityIdLookup; |
41 | $this->linkFormatterFactory = $linkFormatterFactory; |
42 | } |
43 | |
44 | /** |
45 | * @inheritDoc |
46 | */ |
47 | public function onShowSearchHit( $searchPage, $result, |
48 | $terms, &$link, &$redirect, &$section, &$extract, &$score, &$size, &$date, &$related, |
49 | &$html |
50 | ) { |
51 | if ( $result instanceof EntityResult ) { |
52 | $this->showEntityResultHit( $searchPage, $result, |
53 | $link, $redirect, $section, $extract, $score, $size, $date, $related, $html ); |
54 | } |
55 | } |
56 | |
57 | /** |
58 | * Show result hit which is the result of Cirrus-driven entity search. |
59 | * |
60 | * @param SpecialSearch $searchPage |
61 | * @param EntityResult $result |
62 | * @param string &$link |
63 | * @param string &$redirect |
64 | * @param string &$section |
65 | * @param string &$extract |
66 | * @param string &$score |
67 | * @param string &$size |
68 | * @param string &$date |
69 | * @param string &$related |
70 | * @param string &$html |
71 | */ |
72 | private function showEntityResultHit( SpecialSearch $searchPage, EntityResult $result, |
73 | &$link, &$redirect, &$section, &$extract, &$score, &$size, &$date, &$related, &$html |
74 | ) { |
75 | $extract = ''; |
76 | $displayLanguage = $searchPage->getLanguage()->getCode(); |
77 | // Put highlighted description of the item as the extract |
78 | ShowSearchHitHandler::addDescription( $extract, $result->getDescriptionHighlightedData(), $searchPage ); |
79 | // Add extra data |
80 | $extra = $result->getExtraDisplay(); |
81 | if ( $extra ) { |
82 | $attr = [ 'class' => 'wb-itemlink-description' ]; |
83 | $extra = ShowSearchHitHandler::withLanguage( $extra, $displayLanguage ); |
84 | ShowSearchHitHandler::addLanguageAttrs( $attr, $displayLanguage, $extra ); |
85 | $section = $searchPage->msg( 'colon-separator' )->escaped(); |
86 | $section .= Html::rawElement( 'span', $attr, HtmlArmor::getHtml( $extra['value'] ) ); |
87 | } |
88 | // set $size to size metrics |
89 | $size = $searchPage->msg( |
90 | 'wikibase-search-result-stats', |
91 | $result->getStatementCount(), |
92 | $result->getSitelinkCount() |
93 | )->escaped(); |
94 | } |
95 | |
96 | /** |
97 | * @inheritDoc |
98 | * |
99 | * @todo Add highlighting when Q##-id matches and not label text. |
100 | */ |
101 | public function onShowSearchHitTitle( |
102 | &$title, |
103 | &$titleSnippet, |
104 | $result, |
105 | $terms, |
106 | $specialSearch, |
107 | &$query, |
108 | &$attributes |
109 | ) { |
110 | if ( $result instanceof EntityResult ) { |
111 | $this->getEntityLink( $specialSearch->getContext(), $result, $title, $titleSnippet, $attributes, |
112 | $specialSearch->getLanguage()->getCode() ); |
113 | } |
114 | } |
115 | |
116 | /** |
117 | * Generate link text for Title link in search hit. |
118 | * @param IContextSource $context |
119 | * @param EntityResult $result |
120 | * @param Title $title |
121 | * @param string|HtmlArmor &$html Variable where HTML will be placed |
122 | * @param array &$attributes Link tag attributes, can add more |
123 | * @param string $displayLanguage |
124 | */ |
125 | private function getEntityLink( |
126 | IContextSource $context, |
127 | EntityResult $result, |
128 | Title $title, |
129 | &$html, |
130 | &$attributes, |
131 | $displayLanguage |
132 | ) { |
133 | $entityId = $this->entityIdLookup->getEntityIdForTitle( $title ); |
134 | if ( !$entityId ) { |
135 | return; |
136 | } |
137 | $linkFormatter = $this->linkFormatterFactory->getDefaultLinkFormatter( $context->getLanguage() ); |
138 | // Highlighter already encodes and marks up the HTML |
139 | $html = new HtmlArmor( |
140 | $linkFormatter->getHtml( $entityId, |
141 | ShowSearchHitHandler::withLanguage( $result->getLabelHighlightedData(), $displayLanguage ) |
142 | ) |
143 | ); |
144 | |
145 | $attributes['title'] = $linkFormatter->getTitleAttribute( |
146 | $entityId, |
147 | $result->getLabelData(), |
148 | $result->getDescriptionData() |
149 | ); |
150 | } |
151 | |
152 | } |