Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
58 / 58
100.00% covered (success)
100.00%
4 / 4
CRAP
100.00% covered (success)
100.00%
1 / 1
VariablesFormatter
100.00% covered (success)
100.00%
58 / 58
100.00% covered (success)
100.00%
4 / 4
13
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 setMessageLocalizer
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 buildVarDumpTable
100.00% covered (success)
100.00%
38 / 38
100.00% covered (success)
100.00%
1 / 1
4
 formatVar
100.00% covered (success)
100.00%
16 / 16
100.00% covered (success)
100.00%
1 / 1
7
1<?php
2
3namespace MediaWiki\Extension\AbuseFilter\Variables;
4
5use MediaWiki\Extension\AbuseFilter\KeywordsManager;
6use MediaWiki\Html\Html;
7use MessageLocalizer;
8use Xml;
9
10/**
11 * Pretty-prints the content of a VariableHolder for use e.g. in AbuseLog hit details
12 */
13class VariablesFormatter {
14    public const SERVICE_NAME = 'AbuseFilterVariablesFormatter';
15
16    /** @var KeywordsManager */
17    private $keywordsManager;
18    /** @var VariablesManager */
19    private $varManager;
20    /** @var MessageLocalizer */
21    private $messageLocalizer;
22
23    /**
24     * @param KeywordsManager $keywordsManager
25     * @param VariablesManager $variablesManager
26     * @param MessageLocalizer $messageLocalizer
27     */
28    public function __construct(
29        KeywordsManager $keywordsManager,
30        VariablesManager $variablesManager,
31        MessageLocalizer $messageLocalizer
32    ) {
33        $this->keywordsManager = $keywordsManager;
34        $this->varManager = $variablesManager;
35        $this->messageLocalizer = $messageLocalizer;
36    }
37
38    /**
39     * @param MessageLocalizer $messageLocalizer
40     */
41    public function setMessageLocalizer( MessageLocalizer $messageLocalizer ): void {
42        $this->messageLocalizer = $messageLocalizer;
43    }
44
45    /**
46     * @param VariableHolder $varHolder
47     * @return string
48     */
49    public function buildVarDumpTable( VariableHolder $varHolder ): string {
50        $vars = $this->varManager->exportAllVars( $varHolder );
51
52        $output = '';
53
54        $output .=
55            Xml::openElement( 'table', [ 'class' => 'mw-abuselog-details' ] ) .
56            Xml::openElement( 'tbody' ) .
57            "\n";
58
59        $header =
60            Xml::element( 'th', null, $this->messageLocalizer->msg( 'abusefilter-log-details-var' )->text() ) .
61            Xml::element( 'th', null, $this->messageLocalizer->msg( 'abusefilter-log-details-val' )->text() );
62        $output .= Xml::tags( 'tr', null, $header ) . "\n";
63
64        if ( !count( $vars ) ) {
65            $output .= Xml::closeElement( 'tbody' ) . Xml::closeElement( 'table' );
66
67            return $output;
68        }
69
70        // Now, build the body of the table.
71        foreach ( $vars as $key => $value ) {
72            $key = strtolower( $key );
73
74            $varMsgKey = $this->keywordsManager->getMessageKeyForVar( $key );
75            if ( $varMsgKey ) {
76                $keyDisplay = $this->messageLocalizer->msg( $varMsgKey )->parse() . ' ' .
77                    Html::element(
78                        'code',
79                        [],
80                        $this->messageLocalizer->msg( 'parentheses' )->rawParams( $key )->text()
81                    );
82            } else {
83                $keyDisplay = Html::element( 'code', [], $key );
84            }
85
86            $value = Html::element(
87                'div',
88                [ 'class' => 'mw-abuselog-var-value' ],
89                self::formatVar( $value )
90            );
91
92            $trow =
93                Xml::tags( 'td', [ 'class' => 'mw-abuselog-var' ], $keyDisplay ) .
94                Xml::tags( 'td', [ 'class' => 'mw-abuselog-var-value' ], $value );
95            $output .=
96                Xml::tags( 'tr',
97                    [ 'class' => "mw-abuselog-details-$key mw-abuselog-value" ], $trow
98                ) . "\n";
99        }
100
101        $output .= Xml::closeElement( 'tbody' ) . Xml::closeElement( 'table' );
102
103        return $output;
104    }
105
106    /**
107     * @param mixed $var
108     * @param string $indent
109     * @return string
110     */
111    public static function formatVar( $var, string $indent = '' ): string {
112        if ( $var === [] ) {
113            return '[]';
114        } elseif ( is_array( $var ) ) {
115            $ret = '[';
116            $indent .= "\t";
117            foreach ( $var as $key => $val ) {
118                $ret .= "\n$indent" . self::formatVar( $key, $indent ) .
119                    ' => ' . self::formatVar( $val, $indent ) . ',';
120            }
121            // Strip trailing commas
122            return substr( $ret, 0, -1 ) . "\n" . substr( $indent, 0, -1 ) . ']';
123        } elseif ( is_string( $var ) ) {
124            // Don't escape the string (specifically backslashes) to avoid displaying wrong stuff
125            return "'$var'";
126        } elseif ( $var === null ) {
127            return 'null';
128        } elseif ( is_float( $var ) ) {
129            // Don't let float precision produce weirdness
130            return (string)$var;
131        }
132        return var_export( $var, true );
133    }
134}