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