Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
89.19% covered (warning)
89.19%
33 / 37
60.00% covered (warning)
60.00%
3 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
CirrusShowSearchHitHooksHandler
89.19% covered (warning)
89.19%
33 / 37
60.00% covered (warning)
60.00%
3 / 5
9.10
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 onShowSearchHit
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 showEntityResultHit
100.00% covered (success)
100.00%
15 / 15
100.00% covered (success)
100.00%
1 / 1
2
 onShowSearchHitTitle
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 getEntityLink
92.86% covered (success)
92.86%
13 / 14
0.00% covered (danger)
0.00%
0 / 1
2.00
1<?php
2
3declare( strict_types = 1 );
4
5namespace Wikibase\Search\Elastic\Hooks;
6
7use HtmlArmor;
8use MediaWiki\Context\IContextSource;
9use MediaWiki\Html\Html;
10use MediaWiki\Search\Hook\ShowSearchHitHook;
11use MediaWiki\Search\Hook\ShowSearchHitTitleHook;
12use MediaWiki\Specials\SpecialSearch;
13use MediaWiki\Title\Title;
14use Wikibase\Lib\Store\EntityIdLookup;
15use Wikibase\Repo\Hooks\Formatters\EntityLinkFormatterFactory;
16use Wikibase\Repo\Hooks\ShowSearchHitHandler;
17use 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 */
27class 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}