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