Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
27 / 27
100.00% covered (success)
100.00%
8 / 8
CRAP
100.00% covered (success)
100.00%
1 / 1
Warn
100.00% covered (success)
100.00%
27 / 27
100.00% covered (success)
100.00%
8 / 8
10
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%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 shouldDisableOtherConsequences
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getSort
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getMessage
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
1
 shouldBeWarned
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 setWarn
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getWarnKey
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3namespace MediaWiki\Extension\AbuseFilter\Consequences\Consequence;
4
5use MediaWiki\Extension\AbuseFilter\Consequences\ConsequenceNotPrecheckedException;
6use MediaWiki\Extension\AbuseFilter\Consequences\Parameters;
7use MediaWiki\Extension\AbuseFilter\GlobalNameUtils;
8use MediaWiki\Session\Session;
9
10/**
11 * Consequence that warns the user once, allowing the action on the second attempt.
12 */
13class Warn extends Consequence implements HookAborterConsequence, ConsequencesDisablerConsequence {
14    /** @var bool|null */
15    private $shouldWarn;
16
17    public function __construct(
18        Parameters $parameters,
19        private readonly string $message,
20        private Session $session
21    ) {
22        parent::__construct( $parameters );
23    }
24
25    /**
26     * @return bool Whether the user should be warned (i.e. this is the first attempt)
27     * @throws ConsequenceNotPrecheckedException
28     */
29    public function execute(): bool {
30        if ( $this->shouldWarn === null ) {
31            throw new ConsequenceNotPrecheckedException();
32        }
33        $this->setWarn();
34        return $this->shouldWarn;
35    }
36
37    /**
38     * @inheritDoc
39     */
40    public function shouldDisableOtherConsequences(): bool {
41        $this->shouldWarn = $this->shouldBeWarned();
42        return $this->shouldWarn;
43    }
44
45    /**
46     * @inheritDoc
47     */
48    public function getSort(): int {
49        return 5;
50    }
51
52    /**
53     * @inheritDoc
54     */
55    public function getMessage(): array {
56        $filter = $this->parameters->getFilter();
57        return [
58            $this->message,
59            $filter->getName(),
60            GlobalNameUtils::buildGlobalName( $filter->getID(), $this->parameters->getIsGlobalFilter() )
61        ];
62    }
63
64    private function shouldBeWarned(): bool {
65        // Make sure the session is started prior to using it
66        $this->session->persist();
67        $warnKey = $this->getWarnKey();
68        return ( !isset( $this->session[$warnKey] ) || !$this->session[$warnKey] );
69    }
70
71    /**
72     * Sets the parameters needed to warn the user, *without* checking if the user should be warned.
73     */
74    private function setWarn(): void {
75        $warnKey = $this->getWarnKey();
76        $this->session[$warnKey] = $this->shouldWarn;
77    }
78
79    /**
80     * Generate a unique key to determine whether the user has already been warned.
81     * We'll warn again if one of these changes: session, page, triggered filter, or action
82     */
83    private function getWarnKey(): string {
84        $globalFilterName = GlobalNameUtils::buildGlobalName(
85            $this->parameters->getFilter()->getID(),
86            $this->parameters->getIsGlobalFilter()
87        );
88        $target = $this->parameters->getTarget();
89        $titleText = $target->getNamespace() . ':' . $target->getText();
90        return 'abusefilter-warned-' . md5( $titleText ) .
91            '-' . $globalFilterName . '-' . $this->parameters->getAction();
92    }
93}