Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
30 / 30
100.00% covered (success)
100.00%
2 / 2
CRAP
100.00% covered (success)
100.00%
1 / 1
MultilingualTextViolationMessageRenderer
100.00% covered (success)
100.00%
30 / 30
100.00% covered (success)
100.00%
2 / 2
7
100.00% covered (success)
100.00%
1 / 1
 render
100.00% covered (success)
100.00%
22 / 22
100.00% covered (success)
100.00%
1 / 1
4
 renderMultilingualText
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2
3declare( strict_types = 1 );
4
5namespace WikibaseQuality\ConstraintReport\ConstraintCheck\Message;
6
7use DataValues\MultilingualTextValue;
8use MediaWiki\Message\Message;
9use Wikimedia\Message\MessageParam;
10
11/**
12 * Render a {@link ViolationMessage},
13 * which may have a multilingual text as the last argument,
14 * into a localized string.
15 * (For all other messages, this falls back to the base {@link ViolationMessageRenderer}.)
16 *
17 * Note that this is only supported for specific message keys,
18 * where an alternative message key is known
19 * which is used if the text is not available in the user’s language.
20 * Currently, the only such message key is 'wbqc-violation-message-format-clarification'
21 * (falling back to 'wbqc-violation-message-format').
22 *
23 * @license GPL-2.0-or-later
24 */
25class MultilingualTextViolationMessageRenderer extends ViolationMessageRenderer {
26
27    private const ALTERNATIVE_MESSAGE_KEYS = [
28        'wbqc-violation-message-format-clarification' => 'wbqc-violation-message-format',
29    ];
30
31    public function render( ViolationMessage $violationMessage ): string {
32        if ( !array_key_exists( $violationMessage->getMessageKey(), self::ALTERNATIVE_MESSAGE_KEYS ) ) {
33            return parent::render( $violationMessage );
34        }
35
36        $arguments = $violationMessage->getArguments();
37        $multilingualTextArgument = array_pop( $arguments );
38        $multilingualTextParams = $this->renderMultilingualText(
39            // @phan-suppress-next-line PhanTypeArraySuspiciousNullable TODO Ensure this is not an actual issue
40            $multilingualTextArgument['value'],
41            // @phan-suppress-next-line PhanTypeArraySuspiciousNullable
42            $multilingualTextArgument['role']
43        );
44
45        $paramsLists = [ [] ];
46        foreach ( $arguments as $argument ) {
47            $paramsLists[] = $this->renderArgument( $argument );
48        }
49        $regularParams = call_user_func_array( 'array_merge', $paramsLists );
50
51        if ( $multilingualTextParams === null ) {
52            return $this->messageLocalizer
53                ->msg( self::ALTERNATIVE_MESSAGE_KEYS[$violationMessage->getMessageKey()] )
54                ->params( $regularParams )
55                ->escaped();
56        } else {
57            return $this->messageLocalizer
58                ->msg( $violationMessage->getMessageKey() )
59                ->params( $regularParams )
60                ->params( $multilingualTextParams )
61                ->escaped();
62        }
63    }
64
65    /**
66     * @param MultilingualTextValue $text
67     * @param string|null $role one of the Role::* constants
68     * @return MessageParam[]|null list of parameters as accepted by Message::params(),
69     * or null if the text is not available in the user’s language
70     */
71    protected function renderMultilingualText( MultilingualTextValue $text, ?string $role ): ?array {
72        $texts = $text->getTexts();
73        foreach ( $this->languageFallbackChain->getFetchLanguageCodes() as $languageCode ) {
74            if ( array_key_exists( $languageCode, $texts ) ) {
75                return [ Message::rawParam( $this->addRole(
76                    htmlspecialchars( $texts[$languageCode]->getText() ),
77                    $role
78                ) ) ];
79            }
80        }
81
82        return null;
83    }
84
85}