Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 68
0.00% covered (danger)
0.00%
0 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
SpecialMathShowImage
0.00% covered (danger)
0.00%
0 / 68
0.00% covered (danger)
0.00%
0 / 5
506
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
 setHeaders
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
12
 execute
0.00% covered (danger)
0.00%
0 / 41
0.00% covered (danger)
0.00%
0 / 1
240
 printSvgError
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
6
 getGroupName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace MediaWiki\Extension\Math;
4
5use InvalidArgumentException;
6use MediaWiki\Extension\Math\Render\RendererFactory;
7use MediaWiki\MainConfigNames;
8use MediaWiki\SpecialPage\SpecialPage;
9
10/**
11 * Description of SpecialMathShowSVG
12 *
13 * @author Moritz Schubotz (Physikerwelt)
14 */
15class SpecialMathShowImage extends SpecialPage {
16    /** @var bool */
17    private $noRender = false;
18    /** @var MathRenderer|null */
19    private $renderer = null;
20    /** @var string */
21    private $mode = MathConfig::MODE_MATHML;
22
23    /** @var MathConfig */
24    private $mathConfig;
25
26    /** @var RendererFactory */
27    private $rendererFactory;
28
29    /**
30     * @param MathConfig $mathConfig
31     * @param RendererFactory $rendererFactory
32     */
33    public function __construct(
34        MathConfig $mathConfig,
35        RendererFactory $rendererFactory
36    ) {
37        parent::__construct(
38            'MathShowImage',
39            '', // Don't restrict
40            false // Don't show on Special:SpecialPages - it's not useful interactively
41        );
42        $this->mathConfig = $mathConfig;
43        $this->rendererFactory = $rendererFactory;
44    }
45
46    /**
47     * Sets headers - this should be called from the execute() method of all derived classes!
48     * @param bool $success
49     */
50    public function setHeaders( $success = true ) {
51        $out = $this->getOutput();
52        $request = $this->getRequest();
53        $out->setArticleBodyOnly( true );
54        $out->setArticleRelated( false );
55        $out->setRobotPolicy( "noindex,nofollow" );
56        $out->disable();
57        $request->response()->header( "Content-type: image/svg+xml; charset=utf-8" );
58        if ( $success && !( $this->noRender ) ) {
59            $request->response()->header(
60                'Cache-Control: public, s-maxage=604800, max-age=3600'
61            ); // 1 week (server) 1 hour (client)
62            $request->response()->header( 'Vary: User-Agent' );
63        }
64    }
65
66    /** @inheritDoc */
67    public function execute( $par ) {
68        $request = $this->getRequest();
69        $hash = $request->getText( 'hash', '' );
70        $tex = $request->getText( 'tex', '' );
71        if ( $this->getConfig()->get( 'MathEnableExperimentalInputFormats' ) ) {
72            $asciimath = $request->getText( 'asciimath', '' );
73        } else {
74            $asciimath = '';
75        }
76        $this->mode = MathConfig::normalizeRenderingMode( $request->getText( 'mode' ) );
77        if ( !$this->mathConfig->isValidRenderingMode( $this->mode ) ) {
78            // Fallback to the default if an invalid mode was specified
79            $this->mode = MathConfig::MODE_MATHML;
80        }
81        if ( $hash === '' && $tex === '' && $asciimath === '' ) {
82            $this->setHeaders( false );
83            echo $this->printSvgError( 'No Inputhash specified' );
84            return;
85        }
86
87        if ( $tex === '' && $asciimath === '' ) {
88            try {
89                $this->renderer = $this->rendererFactory->getFromHash( $hash );
90            } catch ( InvalidArgumentException $exception ) {
91                $this->setHeaders( false );
92                echo $this->printSvgError( $exception->getMessage() );
93                return;
94            }
95            $this->noRender = $request->getBool( 'noRender', false );
96            $isInDatabase = $this->renderer->readFromCache();
97            if ( $isInDatabase || $this->noRender ) {
98                $success = $isInDatabase;
99            } else {
100                $success = $this->renderer->render();
101            }
102        } elseif ( $asciimath === '' ) {
103            $this->renderer = $this->rendererFactory->getRenderer( $tex, [], $this->mode );
104            $success = $this->renderer->render();
105        } else {
106            $this->renderer = $this->rendererFactory->getRenderer(
107                $asciimath, [ 'type' => 'ascii' ], $this->mode
108            );
109            $success = $this->renderer->render();
110        }
111        if ( $success ) {
112            $output = $this->renderer->getSvg();
113        } else {
114            $output = $this->printSvgError( $this->renderer->getLastError() );
115        }
116        if ( $output == "" ) {
117            $output = $this->printSvgError( 'No Output produced' );
118            $success = false;
119        }
120        $this->setHeaders( $success );
121        echo $output;
122        if ( $success ) {
123            $this->renderer->writeCache();
124        }
125    }
126
127    /**
128     * Prints the specified error message as svg.
129     * @param string $msg error message, HTML escaped
130     * @return string xml svg image with the error message
131     */
132    private function printSvgError( $msg ) {
133        $result = <<<SVG
134<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 4" preserveAspectRatio="xMidYMid meet" >
135<text text-anchor="start" fill="red" y="2">
136$msg
137</text>
138</svg>
139SVG;
140        if ( $this->getConfig()->get( MainConfigNames::DebugComments ) ) {
141            $result .= '<!--' . var_export( $this->renderer, true ) . '-->';
142        }
143        return $result;
144    }
145
146    protected function getGroupName(): string {
147        return 'other';
148    }
149}