Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
45.83% covered (danger)
45.83%
22 / 48
50.00% covered (danger)
50.00%
4 / 8
CRAP
0.00% covered (danger)
0.00%
0 / 1
DQ
45.83% covered (danger)
45.83%
22 / 48
50.00% covered (danger)
50.00%
4 / 8
142.86
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 getBase
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getDown
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 render
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 renderMML
84.21% covered (warning)
84.21%
16 / 19
0.00% covered (danger)
0.00%
0 / 1
7.19
 extractIdentifiers
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
72
 extractSubscripts
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
12
 getModIdent
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
30
1<?php
2
3declare( strict_types = 1 );
4
5namespace MediaWiki\Extension\Math\WikiTexVC\Nodes;
6
7use MediaWiki\Extension\Math\WikiTexVC\MMLmappings\BaseParsing;
8use MediaWiki\Extension\Math\WikiTexVC\MMLnodes\MMLmrow;
9use MediaWiki\Extension\Math\WikiTexVC\MMLnodes\MMLmsub;
10use MediaWiki\Extension\Math\WikiTexVC\MMLnodes\MMLmunder;
11use MediaWiki\Extension\Math\WikiTexVC\TexUtil;
12
13class DQ extends TexNode {
14    /** @var TexNode */
15    private $base;
16    /** @var TexNode */
17    private $down;
18
19    public function __construct( TexNode $base, TexNode $down ) {
20        parent::__construct( $base, $down );
21        $this->base = $base;
22        $this->down = $down;
23    }
24
25    /**
26     * @return TexNode
27     */
28    public function getBase(): TexNode {
29        return $this->base;
30    }
31
32    /**
33     * @return TexNode
34     */
35    public function getDown(): TexNode {
36        return $this->down;
37    }
38
39    /** @inheritDoc */
40    public function render() {
41        return $this->base->render() . '_' . $this->down->inCurlies();
42    }
43
44    /** @inheritDoc */
45    public function renderMML( $arguments = [], &$state = [] ) {
46        if ( array_key_exists( "limits", $state ) ) {
47            // A specific DQ case with preceding limits, just invoke the limits parsing manually.
48            return BaseParsing::limits( $this, $arguments, $state, "" );
49        }
50
51        if ( !$this->isEmpty() ) {
52            if ( $this->getBase()->containsFunc( "\underbrace" ) ) {
53                $outer = new MMLmunder();
54            } else {
55                $outer = new MMLmsub();
56                if ( ( $state['styleargs']['displaystle'] ?? 'true' ) === 'true' ) {
57                    $tu = TexUtil::getInstance();
58                    if ( $tu->operator( trim( $this->base->render() ) ) ) {
59                        $outer = new MMLmunder();
60                    }
61                }
62            }
63            // Otherwise use default fallback
64            $mmlMrow = new MMLmrow();
65            $inner_state = [ 'styleargs' => $state['styleargs'] ?? [] ];
66            $baseRendering = $this->base->renderMML( $arguments, $inner_state );
67            // In cases with empty curly preceding like: "{}_pF_q" or _{1}
68            if ( trim( $baseRendering ) === "" ) {
69                $baseRendering = ( new MMLmrow() )->getEmpty();
70            }
71            return $outer->encapsulateRaw(
72                $baseRendering .
73                $mmlMrow->encapsulateRaw( $this->down->renderMML( $arguments, $state ) ) );
74        }
75
76        return "";
77    }
78
79    /** @inheritDoc */
80    public function extractIdentifiers( $args = null ) {
81        $d = $this->down->extractSubscripts();
82        $b = $this->base->extractIdentifiers();
83        if ( is_array( $b ) && count( $b ) > 1 ) {
84            return parent::extractIdentifiers();
85        }
86
87        if ( isset( $b[0] ) && $b[0] === '\'' ) {
88            return array_merge( $b, $d );
89        }
90
91        if ( isset( $d[0] ) && isset( $b[0] ) ) {
92            if ( $b[0] === '\\int' ) {
93                return array_merge( $b, $d );
94            }
95            return [ $b[0] . '_{' . $d[0] . '}' ];
96        }
97
98        return parent::extractIdentifiers();
99    }
100
101    /** @inheritDoc */
102    public function extractSubscripts() {
103        $d = array_merge( [], $this->down->extractSubscripts() );
104        $b = $this->base->extractSubscripts();
105        if ( isset( $b[0] ) && isset( $d[0] ) ) {
106            return [ $b[0] . '_{' . implode( '', $d ) . '}' ];
107        }
108        return parent::extractSubscripts();
109    }
110
111    /** @inheritDoc */
112    public function getModIdent() {
113        $d = $this->down->extractSubscripts();
114        $b = $this->base->getModIdent();
115        if ( isset( $b[0] ) && $b[0] === '\'' ) {
116            return [];
117        }
118        if ( isset( $d[0] ) && isset( $b[0] ) ) {
119            return [ $b[0] . '_{' . $d[0] . '}' ];
120        }
121
122        return parent::getModIdent();
123    }
124
125}