Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
87.10% covered (warning)
87.10%
27 / 31
50.00% covered (danger)
50.00%
1 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
ApiWikifunctionsHTMLSanitiser
87.10% covered (warning)
87.10%
27 / 31
50.00% covered (danger)
50.00%
1 / 2
8.14
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 run
86.21% covered (warning)
86.21%
25 / 29
0.00% covered (danger)
0.00%
0 / 1
1.00
 mustBePosted
n/a
0 / 0
n/a
0 / 0
1
 isWriteMode
n/a
0 / 0
n/a
0 / 0
1
 needsToken
n/a
0 / 0
n/a
0 / 0
1
 isInternal
n/a
0 / 0
n/a
0 / 0
1
 getAllowedParams
n/a
0 / 0
n/a
0 / 0
1
 getExamplesMessages
n/a
0 / 0
n/a
0 / 0
1
1<?php
2/**
3 * Wikifunctions HTML sanitising API
4 *
5 * @file
6 * @ingroup Extensions
7 * @copyright 2020– Abstract Wikipedia team; see AUTHORS.txt
8 * @license MIT
9 */
10
11namespace MediaWiki\Extension\WikiLambda\ActionAPI;
12
13use MediaWiki\Api\ApiMain;
14use MediaWiki\Extension\WikiLambda\HttpStatus;
15use MediaWiki\Extension\WikiLambda\ParserFunction\WikifunctionsPFragmentSanitiserTokenHandler;
16use MediaWiki\Logger\LoggerFactory;
17use MediaWiki\PoolCounter\PoolCounterWorkViaCallback;
18use Wikimedia\ParamValidator\ParamValidator;
19
20class ApiWikifunctionsHTMLSanitiser extends WikiLambdaApiBase {
21
22    public function __construct( ApiMain $mainModule, string $moduleName ) {
23        parent::__construct( $mainModule, $moduleName );
24
25        $this->setUp();
26    }
27
28    /**
29     * @inheritDoc
30     */
31    protected function run(): void {
32        $userHTMLToClean = $this->getParameter( 'html' );
33
34        $logger = LoggerFactory::getInstance( 'WikiLambda' );
35
36        // Use a pool counter to limit concurrency; this is probably over-kill for simple HTML sanitisation.
37        $work = new PoolCounterWorkViaCallback(
38            'WikifunctionsSanitiseHTMLFragment',
39            $this->getUser()->getName(),
40            [
41                'doWork' => static function () use ( $logger, $userHTMLToClean ) {
42                    return WikifunctionsPFragmentSanitiserTokenHandler::sanitiseHtmlFragment(
43                        $logger,
44                        $userHTMLToClean
45                    );
46                },
47                'error' => function ( \MediaWiki\Status\Status $status ): never {
48                    $this->dieWithError(
49                        [ "apierror-wikifunctions_sanitise_html_fragment-concurrency-limit" ],
50                        null, null, HttpStatus::TOO_MANY_REQUESTS
51                    );
52                }
53            ]
54        );
55        $response = $work->execute();
56
57        $this->getResult()->addValue(
58            null,
59            $this->getModuleName(),
60            [
61                'success' => true,
62                'value' => $response
63            ]
64        );
65    }
66
67    /**
68     * @inheritDoc
69     * @codeCoverageIgnore
70     */
71    public function mustBePosted() {
72        return true;
73    }
74
75    /**
76     * @inheritDoc
77     * @codeCoverageIgnore
78     */
79    public function isWriteMode() {
80        return true;
81    }
82
83    /**
84     * @inheritDoc
85     * @codeCoverageIgnore
86     */
87    public function needsToken(): string {
88        return 'csrf';
89    }
90
91    /**
92     * Mark as internal. This isn't meant to be user-facing, and can change at any time.
93     * @return bool
94     * @codeCoverageIgnore
95     */
96    public function isInternal() {
97        return true;
98    }
99
100    /**
101     * @inheritDoc
102     * @codeCoverageIgnore
103     */
104    protected function getAllowedParams(): array {
105        return [
106            'html' => [
107                ParamValidator::PARAM_TYPE => 'string',
108                ParamValidator::PARAM_DEFAULT => '',
109            ],
110        ];
111    }
112
113    /**
114     * @see ApiBase::getExamplesMessages()
115     * @return array
116     * @codeCoverageIgnore
117     */
118    protected function getExamplesMessages() {
119        return [
120            'action=wikifunctions_html_sanitiser&format=json&html='
121                . urlencode( '<p><b>Hello</b>, <em>world</em>!</p>' )
122                => 'apihelp-wikifunctions_html_sanitiser-example-untouched',
123            'action=wikifunctions_html_sanitiser&format=json&html='
124                . urlencode( '<a href="www.example.com/foo">Naughty and not allowed!</a>' )
125                => 'apihelp-wikifunctions_html_sanitiser-example-prohibited',
126        ];
127    }
128}