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