Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
62 / 62
100.00% covered (success)
100.00%
5 / 5
CRAP
100.00% covered (success)
100.00%
1 / 1
FormIdHtmlFormatter
100.00% covered (success)
100.00%
62 / 62
100.00% covered (success)
100.00%
5 / 5
13
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
1
 formatEntityId
100.00% covered (success)
100.00%
24 / 24
100.00% covered (success)
100.00%
1 / 1
6
 getLinkTitle
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
1 / 1
2
 getLabels
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
 buildRepresentationMarkupElements
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3declare( strict_types = 1 );
4
5namespace Wikibase\Lexeme\Presentation\Formatters;
6
7use InvalidArgumentException;
8use MediaWiki\Html\Html;
9use MediaWiki\Languages\LanguageFactory;
10use Wikibase\DataModel\Entity\EntityId;
11use Wikibase\DataModel\Services\EntityId\EntityIdFormatter;
12use Wikibase\DataModel\Services\Lookup\LabelDescriptionLookup;
13use Wikibase\DataModel\Services\Lookup\UnresolvedEntityRedirectException;
14use Wikibase\DataModel\Term\Term;
15use Wikibase\DataModel\Term\TermList;
16use Wikibase\Lexeme\Domain\Model\Form;
17use Wikibase\Lexeme\Domain\Model\FormId;
18use Wikibase\Lib\Formatters\NonExistingEntityIdHtmlFormatter;
19use Wikibase\Lib\Store\EntityRevisionLookup;
20use Wikibase\Lib\Store\EntityTitleLookup;
21use Wikibase\View\LocalizedTextProvider;
22
23/**
24 * @license GPL-2.0-or-later
25 */
26class FormIdHtmlFormatter implements EntityIdFormatter {
27
28    private const REPRESENTATION_SEPARATOR_I18N =
29        'wikibaselexeme-formidformatter-separator-multiple-representation';
30    private const GRAMMATICAL_FEATURES_SEPARATOR_I18N =
31        'wikibaselexeme-formidformatter-separator-grammatical-features';
32
33    private EntityRevisionLookup $revisionLookup;
34    private EntityTitleLookup $titleLookup;
35    private NonExistingEntityIdHtmlFormatter $nonExistingIdFormatter;
36    private LocalizedTextProvider $localizedTextProvider;
37    private RedirectedLexemeSubEntityIdHtmlFormatter $redirectedLexemeSubEntityIdHtmlFormatter;
38    private LabelDescriptionLookup $labelDescriptionLookup;
39    private LanguageFactory $languageFactory;
40
41    public function __construct(
42        EntityRevisionLookup $revisionLookup,
43        LabelDescriptionLookup $labelDescriptionLookup,
44        EntityTitleLookup $titleLookup,
45        LocalizedTextProvider $localizedTextProvider,
46        RedirectedLexemeSubEntityIdHtmlFormatter $redirectedLexemeSubEntityIdHtmlFormatter,
47        LanguageFactory $languageFactory
48    ) {
49        $this->revisionLookup = $revisionLookup;
50        $this->labelDescriptionLookup = $labelDescriptionLookup;
51        $this->titleLookup = $titleLookup;
52        $this->localizedTextProvider = $localizedTextProvider;
53        $this->redirectedLexemeSubEntityIdHtmlFormatter = $redirectedLexemeSubEntityIdHtmlFormatter;
54        $this->nonExistingIdFormatter = new NonExistingEntityIdHtmlFormatter(
55            'wikibaselexeme-deletedentity-'
56        );
57        $this->languageFactory = $languageFactory;
58    }
59
60    public function formatEntityId( EntityId $formId ): string {
61        try {
62            $formRevision = $this->revisionLookup->getEntityRevision( $formId );
63            $title = $this->titleLookup->getTitleForId( $formId );
64        } catch ( UnresolvedEntityRedirectException $exception ) {
65            return $this->redirectedLexemeSubEntityIdHtmlFormatter->formatEntityId( $formId );
66        }
67        if ( !( $formId instanceof FormId ) ) {
68            throw new InvalidArgumentException(
69                'Attemped to format a non-Form entity as a Form: ' . $formId->getSerialization() );
70        }
71
72        if ( $formRevision === null || $title === null ) {
73            return $this->nonExistingIdFormatter->formatEntityId( $formId );
74        }
75
76        /** @var Form $form */
77        $form = $formRevision->getEntity();
78        '@phan-var Form $form';
79
80        $representationMarkup = implode(
81            $this->localizedTextProvider->getEscaped(
82                self::REPRESENTATION_SEPARATOR_I18N
83            ),
84            $this->buildRepresentationMarkupElements( $form->getRepresentations() )
85        );
86
87        return Html::rawElement(
88            'a',
89            [
90                'href'  => $title->isLocal() ? $title->getLinkURL() : $title->getFullURL(),
91                'title' => $this->getLinkTitle( $form ),
92            ],
93            $representationMarkup
94        );
95    }
96
97    private function getLinkTitle( Form $form ): string {
98        $serializedId = $form->getId()->getSerialization();
99        $labels = implode(
100            $this->localizedTextProvider->get( self::GRAMMATICAL_FEATURES_SEPARATOR_I18N ),
101            $this->getLabels( $form )
102        );
103
104        if ( $labels === '' ) {
105            $title = $serializedId;
106        } else {
107            $title = $this->localizedTextProvider->get(
108                'wikibaselexeme-formidformatter-link-title',
109                [ $serializedId, $labels ]
110            );
111        }
112
113        return $title;
114    }
115
116    private function getLabels( Form $form ): array {
117        $labels = [];
118
119        foreach ( $form->getGrammaticalFeatures() as $grammaticalFeaturesId ) {
120            $grammaticalFeatureLabel = $this->labelDescriptionLookup->getLabel( $grammaticalFeaturesId );
121
122            if ( $grammaticalFeatureLabel !== null ) {
123                $labels[] = $grammaticalFeatureLabel->getText();
124            }
125        }
126
127        return $labels;
128    }
129
130    private function buildRepresentationMarkupElements( TermList $representations ): array {
131        return array_map( function ( Term $representation ) {
132            $language = $this->languageFactory->getLanguage( $representation->getLanguageCode() );
133            return Html::element(
134                'span',
135                [
136                    'lang' => $language->getHtmlCode(),
137                    'dir' => $language->getDir(),
138                ],
139                $representation->getText()
140            );
141        }, iterator_to_array( $representations->getIterator() ) );
142    }
143
144}