Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
43 / 43
100.00% covered (success)
100.00%
4 / 4
CRAP
100.00% covered (success)
100.00%
1 / 1
RendererFactory
100.00% covered (success)
100.00%
43 / 43
100.00% covered (success)
100.00%
4 / 4
19
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 determineMode
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
9
 getRenderer
100.00% covered (success)
100.00%
18 / 18
100.00% covered (success)
100.00%
1 / 1
7
 getFromHash
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3namespace MediaWiki\Extension\Math\Render;
4
5use InvalidArgumentException;
6use MediaWiki\Config\ServiceOptions;
7use MediaWiki\Extension\Math\MathConfig;
8use MediaWiki\Extension\Math\MathLaTeXML;
9use MediaWiki\Extension\Math\MathMathML;
10use MediaWiki\Extension\Math\MathMathMLCli;
11use MediaWiki\Extension\Math\MathNativeMML;
12use MediaWiki\Extension\Math\MathRenderer;
13use MediaWiki\Extension\Math\MathSource;
14use MediaWiki\User\Options\UserOptionsLookup;
15use Psr\Log\LoggerInterface;
16use Wikimedia\ObjectCache\WANObjectCache;
17
18class RendererFactory {
19
20    /** @var string[] */
21    public const CONSTRUCTOR_OPTIONS = [
22        'MathoidCli',
23        'MathEnableExperimentalInputFormats',
24        'MathValidModes',
25    ];
26
27    public function __construct(
28        private readonly ServiceOptions $serviceOptions,
29        private readonly MathConfig $mathConfig,
30        private readonly UserOptionsLookup $userOptionsLookup,
31        private readonly LoggerInterface $logger,
32        private readonly WANObjectCache $cache,
33    ) {
34        $serviceOptions->assertRequiredOptions( self::CONSTRUCTOR_OPTIONS );
35    }
36
37    /**
38     * Determine mode used for rendering of math equation, based on current configuration and tag received
39     *
40     * @param string $mode
41     * @param array $params
42     * @return array Returns one of the predefined MathConfig::MODE_* constants and params changed according to rules
43     */
44    public function determineMode(
45        string $mode = MathConfig::MODE_MATHML,
46        array $params = []
47    ): array {
48        if ( isset( $params['forcemathmode'] ) ) {
49            $mode = $params['forcemathmode'];
50        }
51        if ( !in_array( $mode, $this->mathConfig->getValidRenderingModes(), true ) ) {
52            $mode = $this->userOptionsLookup->getDefaultOption( 'math' );
53        }
54        if ( $this->serviceOptions->get( 'MathEnableExperimentalInputFormats' ) === true &&
55            $mode == MathConfig::MODE_MATHML &&
56            isset( $params['type'] )
57        ) {
58            // Support of MathML input (experimental)
59            // Currently support for mode 'mathml' only
60            if ( !in_array( $params['type'], [ 'pmml', 'ascii' ], true ) ) {
61                unset( $params['type'] );
62            }
63        }
64        if ( isset( $params['chem'] ) ) {
65            $mode = ( $mode == MathConfig::MODE_NATIVE_MML ) ? MathConfig::MODE_NATIVE_MML : MathConfig::MODE_MATHML;
66            $params['type'] = 'chem';
67        }
68        return [ $mode, $params ];
69    }
70
71    /**
72     * Factory method for getting a renderer based on mode
73     *
74     * @param string $tex LaTeX markup
75     * @param array $params HTML attributes
76     * @param string $mode indicating rendering mode, one of MathConfig::MODE_*
77     * @return MathRenderer appropriate renderer for mode
78     */
79    public function getRenderer(
80        string $tex,
81        array $params = [],
82        string $mode = MathConfig::MODE_MATHML
83    ): MathRenderer {
84        [ $mode, $params ] = $this->determineMode( $mode, $params );
85        switch ( $mode ) {
86            case MathConfig::MODE_SOURCE:
87                $renderer = new MathSource( $tex, $params );
88                break;
89            case MathConfig::MODE_NATIVE_MML:
90                $renderer = new MathNativeMML( $tex, $params, $this->cache );
91                break;
92            case MathConfig::MODE_LATEXML:
93                $renderer = new MathLaTeXML( $tex, $params, $this->cache );
94                break;
95            case MathConfig::MODE_MATHML:
96            default:
97                if ( $this->serviceOptions->get( 'MathoidCli' ) ) {
98                    $renderer = new MathMathMLCli( $tex, $params, $this->cache );
99                } else {
100                    $renderer = new MathMathML( $tex, $params, $this->cache );
101                }
102        }
103        $this->logger->debug(
104            'Start rendering "{tex}" in mode {mode}',
105            [
106                'tex' => $tex,
107                'mode' => $mode
108            ]
109        );
110        return $renderer;
111    }
112
113    public function getFromHash( string $inputHash ): MathRenderer {
114        $key = $this->cache->makeGlobalKey(
115            MathRenderer::class,
116            $inputHash
117        );
118        $rpage = $this->cache->get( $key );
119        if ( $rpage === false ) {
120            throw new InvalidArgumentException( 'Cache key is invalid' );
121        }
122        $mode = $rpage['math_mode'];
123        $renderer = $this->getRenderer( '', [], $mode );
124        $renderer->initializeFromCache( $rpage );
125        return $renderer;
126    }
127}