Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
21 / 21
100.00% covered (success)
100.00%
3 / 3
CRAP
100.00% covered (success)
100.00%
1 / 1
EvalExpression
100.00% covered (success)
100.00%
21 / 21
100.00% covered (success)
100.00%
3 / 3
9
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
 execute
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
4
 evaluateExpression
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
2
 getAllowedParams
n/a
0 / 0
n/a
0 / 0
1
 getExamplesMessages
n/a
0 / 0
n/a
0 / 0
1
1<?php
2
3namespace MediaWiki\Extension\AbuseFilter\Api;
4
5use MediaWiki\Api\ApiBase;
6use MediaWiki\Api\ApiMain;
7use MediaWiki\Api\ApiResult;
8use MediaWiki\Extension\AbuseFilter\AbuseFilterPermissionManager;
9use MediaWiki\Extension\AbuseFilter\Parser\RuleCheckerFactory;
10use MediaWiki\Extension\AbuseFilter\VariableGenerator\VariableGeneratorFactory;
11use MediaWiki\Extension\AbuseFilter\Variables\VariablesFormatter;
12use MediaWiki\Status\Status;
13use Wikimedia\ParamValidator\ParamValidator;
14
15class EvalExpression extends ApiBase {
16
17    public function __construct(
18        ApiMain $main,
19        string $action,
20        private readonly RuleCheckerFactory $ruleCheckerFactory,
21        private readonly AbuseFilterPermissionManager $afPermManager,
22        private readonly VariableGeneratorFactory $afVariableGeneratorFactory
23    ) {
24        parent::__construct( $main, $action );
25    }
26
27    /**
28     * @inheritDoc
29     */
30    public function execute() {
31        // "Anti-DoS"
32        if ( !$this->afPermManager->canUseTestTools( $this->getAuthority() ) ) {
33            $this->dieWithError( 'apierror-abusefilter-canteval', 'permissiondenied' );
34        }
35
36        $params = $this->extractRequestParams();
37
38        $status = $this->evaluateExpression( $params['expression'] );
39        if ( !$status->isGood() ) {
40            $this->dieStatus( $status );
41        } else {
42            $res = $status->getValue();
43            $res = $params['prettyprint'] ? VariablesFormatter::formatVar( $res ) : $res;
44            $this->getResult()->addValue(
45                null,
46                $this->getModuleName(),
47                ApiResult::addMetadataToResultVars( [ 'result' => $res ] )
48            );
49        }
50    }
51
52    private function evaluateExpression( string $expr ): Status {
53        $ruleChecker = $this->ruleCheckerFactory->newRuleChecker();
54        if ( !$ruleChecker->checkSyntax( $expr )->isValid() ) {
55            return Status::newFatal( 'abusefilter-tools-syntax-error' );
56        }
57
58        // Generic vars are the only ones available
59        $generator = $this->afVariableGeneratorFactory->newGenerator();
60        $vars = $generator->addGenericVars()->getVariableHolder();
61        $ruleChecker->setVariables( $vars );
62
63        return Status::newGood( $ruleChecker->evaluateExpression( $expr ) );
64    }
65
66    /**
67     * @codeCoverageIgnore Merely declarative
68     * @inheritDoc
69     */
70    public function getAllowedParams() {
71        return [
72            'expression' => [
73                ParamValidator::PARAM_REQUIRED => true,
74            ],
75            'prettyprint' => [
76                ParamValidator::PARAM_TYPE => 'boolean'
77            ]
78        ];
79    }
80
81    /**
82     * @codeCoverageIgnore Merely declarative
83     * @inheritDoc
84     */
85    protected function getExamplesMessages() {
86        return [
87            'action=abusefilterevalexpression&expression=lcase("FOO")'
88                => 'apihelp-abusefilterevalexpression-example-1',
89            'action=abusefilterevalexpression&expression=lcase("FOO")&prettyprint=1'
90                => 'apihelp-abusefilterevalexpression-example-2',
91        ];
92    }
93}