Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
76 / 76
100.00% covered (success)
100.00%
3 / 3
CRAP
100.00% covered (success)
100.00%
1 / 1
MathML
100.00% covered (success)
100.00%
76 / 76
100.00% covered (success)
100.00%
3 / 3
24
100.00% covered (success)
100.00%
1 / 1
 write
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
2
 writeElementItem
100.00% covered (success)
100.00%
43 / 43
100.00% covered (success)
100.00%
1 / 1
12
 getElementTagName
100.00% covered (success)
100.00%
22 / 22
100.00% covered (success)
100.00%
1 / 1
10
1<?php
2
3namespace PhpOffice\Math\Writer;
4
5use PhpOffice\Math\Element;
6use PhpOffice\Math\Exception\NotImplementedException;
7use PhpOffice\Math\Math;
8use XMLWriter;
9
10class MathML implements WriterInterface
11{
12    /** @var XMLWriter */
13    private $output;
14
15    /**
16     * @param Math $math
17     *
18     * @return string
19     */
20    public function write(Math $math): string
21    {
22        $this->output = new XMLWriter();
23        $this->output->openMemory();
24        $this->output->startDocument('1.0', 'UTF-8');
25        $this->output->writeDtd('math', '-//W3C//DTD MathML 2.0//EN', 'http://www.w3.org/Math/DTD/mathml2/mathml2.dtd');
26        $this->output->startElement('math');
27        $this->output->writeAttribute('xmlns', 'http://www.w3.org/1998/Math/MathML');
28
29        foreach ($math->getElements() as $element) {
30            $this->writeElementItem($element);
31        }
32
33        $this->output->endElement();
34        $this->output->endDocument();
35
36        return $this->output->outputMemory();
37    }
38
39    protected function writeElementItem(Element\AbstractElement $element): void
40    {
41        $tagName = $this->getElementTagName($element);
42
43        // Element\AbstractGroupElement
44        if ($element instanceof Element\Semantics) {
45            $this->output->startElement($tagName);
46            // Write elements
47            foreach ($element->getElements() as $childElement) {
48                $this->writeElementItem($childElement);
49            }
50
51            // Write annotations
52            foreach ($element->getAnnotations() as $encoding => $annotation) {
53                $this->output->startElement('annotation');
54                $this->output->writeAttribute('encoding', $encoding);
55                $this->output->text($annotation);
56                $this->output->endElement();
57            }
58            $this->output->endElement();
59
60            return;
61        }
62
63        // Element\AbstractGroupElement
64        if ($element instanceof Element\AbstractGroupElement) {
65            $this->output->startElement($tagName);
66            foreach ($element->getElements() as $childElement) {
67                $this->writeElementItem($childElement);
68            }
69            $this->output->endElement();
70
71            return;
72        }
73
74        // Element\Superscript
75        if ($element instanceof Element\Superscript) {
76            $this->output->startElement($tagName);
77            $this->writeElementItem($element->getBase());
78            $this->writeElementItem($element->getSuperscript());
79            $this->output->endElement();
80
81            return;
82        }
83
84        // Element\Subscript
85        if ($element instanceof Element\Subscript) {
86            $this->output->startElement($tagName);
87            $this->writeElementItem($element->getBase());
88            $this->writeElementItem($element->getSubscript());
89            $this->output->endElement();
90
91            return;
92        }
93
94        // Element\Fraction
95        if ($element instanceof Element\Fraction) {
96            $this->output->startElement($tagName);
97            $this->writeElementItem($element->getNumerator());
98            $this->writeElementItem($element->getDenominator());
99            $this->output->endElement();
100
101            return;
102        }
103
104        if ($element instanceof Element\Identifier
105          || $element instanceof Element\Numeric
106          || $element instanceof Element\Operator) {
107            $this->output->startElement($tagName);
108            $this->output->text((string) $element->getValue());
109            $this->output->endElement();
110
111            return;
112        }
113
114        /*
115        throw new NotImplementedException(sprintf(
116            '%s : The class `%s` is not implemented',
117            __METHOD__,
118            get_class($element)
119        ));
120        */
121    }
122
123    protected function getElementTagName(Element\AbstractElement $element): string
124    {
125        // Group
126        if ($element instanceof Element\Row) {
127            return 'mrow';
128        }
129        if ($element instanceof Element\AbstractGroupElement) {
130            /*
131            throw new NotImplementedException(sprintf(
132                '%s : The element of the class `%s` has no tag name',
133                __METHOD__,
134                get_class($element)
135            ));
136            */
137        }
138
139        if ($element instanceof Element\Superscript) {
140            return 'msup';
141        }
142        if ($element instanceof Element\Subscript) {
143            return 'msub';
144        }
145        if ($element instanceof Element\Fraction) {
146            return 'mfrac';
147        }
148        if ($element instanceof Element\Identifier) {
149            return 'mi';
150        }
151        if ($element instanceof Element\Numeric) {
152            return 'mn';
153        }
154        if ($element instanceof Element\Operator) {
155            return 'mo';
156        }
157        if ($element instanceof Element\Semantics) {
158            return 'semantics';
159        }
160
161        throw new NotImplementedException(sprintf(
162            '%s : The element of the class `%s` has no tag name',
163            __METHOD__,
164            get_class($element)
165        ));
166    }
167}