Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
89.19% covered (warning)
89.19%
33 / 37
83.33% covered (warning)
83.33%
5 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
FQ
89.19% covered (warning)
89.19%
33 / 37
83.33% covered (warning)
83.33%
5 / 6
16.32
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
4 / 4
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
 getUp
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
86.21% covered (warning)
86.21%
25 / 29
0.00% covered (danger)
0.00%
0 / 1
11.32
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\MMLmstyle;
10use MediaWiki\Extension\Math\WikiTexVC\MMLnodes\MMLmsubsup;
11use MediaWiki\Extension\Math\WikiTexVC\MMLnodes\MMLmunderover;
12use MediaWiki\Extension\Math\WikiTexVC\TexUtil;
13
14class FQ extends TexNode {
15
16    /** @var TexNode */
17    private $base;
18    /** @var TexNode */
19    private $up;
20    /** @var TexNode */
21    private $down;
22
23    public function __construct( TexNode $base, TexNode $down, TexNode $up ) {
24        parent::__construct( $base, $down, $up );
25        $this->base = $base;
26        $this->up = $up;
27        $this->down = $down;
28    }
29
30    /**
31     * @return TexNode
32     */
33    public function getBase(): TexNode {
34        return $this->base;
35    }
36
37    /**
38     * @return TexNode
39     */
40    public function getUp(): TexNode {
41        return $this->up;
42    }
43
44    /**
45     * @return TexNode
46     */
47    public function getDown(): TexNode {
48        return $this->down;
49    }
50
51    public function render() {
52        return $this->base->render() . '_' . $this->down->inCurlies() . '^' . $this->up->inCurlies();
53    }
54
55    public function renderMML( $arguments = [], $state = [] ) {
56        if ( array_key_exists( "limits", $state ) ) {
57            // A specific FQ case with preceding limits, just invoke the limits parsing manually.
58            return BaseParsing::limits( $this, $arguments, $state, "" );
59        }
60        $base = $this->getBase();
61
62        if ( $base->getLength() == 0 && !$base->isCurly() ) {
63            // this happens when FQ is located in Sideset (is this a common parsing way?)
64            $mrow = new MMLmrow();
65            return $mrow->encapsulateRaw( $this->getDown()->renderMML( [], $state ) ) .
66                $mrow->encapsulateRaw( $this->getUp()->renderMML( [], $state ) );
67        }
68
69        $melement = new MMLmsubsup();
70        // tbd check for more such cases like TexUtilTest 317
71        if ( $base instanceof Literal ) {
72            $litArg = trim( $base->getArgs()[0] );
73            $tu = TexUtil::getInstance();
74            // "sum", "bigcap", "bigcup", "prod" ... all are nullary macros.
75            if ( $tu->nullary_macro( $litArg ) &&
76                !$tu->is_literal( $litArg ) &&
77                // by default (inline-displaystyle large operators should be used)
78                ( $state['styleargs']['displaystyle'] ?? 'true' ) === 'true'
79            ) {
80                $melement = new MMLmunderover();
81            }
82        }
83
84        $mrow = new MMLmrow();
85        $emptyMrow = "";
86        // In cases with empty curly preceding like: "{}_1^2\!\Omega_3^4"
87        if ( $base->isCurly() && $base->isEmpty() ) {
88            $emptyMrow = $mrow->getEmpty();
89        }
90        // This seems to be the common case
91        $inner = $melement->encapsulateRaw(
92            $emptyMrow .
93            $base->renderMML( [], $state ) .
94            $mrow->encapsulateRaw( $this->getDown()->renderMML( $arguments, $state ) ) .
95            $mrow->encapsulateRaw( $this->getUp()->renderMML( $arguments, $state ) ) );
96
97        if ( $melement instanceof MMLmunderover ) {
98            $args = $state['styleargs'] ?? [ "displaystyle" => "true", "scriptlevel" => 0 ];
99            $style = new MMLmstyle( "", $args );
100            return $style->encapsulateRaw( $inner );
101        }
102
103        return $inner;
104    }
105}