Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
30 / 30
100.00% covered (success)
100.00%
5 / 5
CRAP
100.00% covered (success)
100.00%
1 / 1
Block
100.00% covered (success)
100.00%
30 / 30
100.00% covered (success)
100.00%
5 / 5
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%
9 / 9
100.00% covered (success)
100.00%
1 / 1
2
 revert
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
5
 getMessage
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
1
 getExpiry
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3namespace MediaWiki\Extension\AbuseFilter\Consequences\Consequence;
4
5use ManualLogEntry;
6use MediaWiki\Block\BlockUserFactory;
7use MediaWiki\Block\DatabaseBlockStore;
8use MediaWiki\Extension\AbuseFilter\Consequences\Parameters;
9use MediaWiki\Extension\AbuseFilter\FilterUser;
10use MediaWiki\Extension\AbuseFilter\GlobalNameUtils;
11use MediaWiki\Title\TitleValue;
12use MediaWiki\User\UserIdentity;
13use MessageLocalizer;
14use Psr\Log\LoggerInterface;
15
16/**
17 * Consequence that blocks a single user.
18 */
19class Block extends BlockingConsequence implements ReversibleConsequence {
20
21    private bool $preventsTalkEdit;
22    private DatabaseBlockStore $databaseBlockStore;
23
24    /**
25     * @param Parameters $params
26     * @param string $expiry
27     * @param bool $preventTalkEdit
28     * @param BlockUserFactory $blockUserFactory
29     * @param DatabaseBlockStore $databaseBlockStore
30     * @param FilterUser $filterUser
31     * @param MessageLocalizer $messageLocalizer
32     * @param LoggerInterface $logger
33     */
34    public function __construct(
35        Parameters $params,
36        string $expiry,
37        bool $preventTalkEdit,
38        BlockUserFactory $blockUserFactory,
39        DatabaseBlockStore $databaseBlockStore,
40        FilterUser $filterUser,
41        MessageLocalizer $messageLocalizer,
42        LoggerInterface $logger
43    ) {
44        parent::__construct( $params, $expiry, $blockUserFactory, $filterUser, $messageLocalizer, $logger );
45        $this->databaseBlockStore = $databaseBlockStore;
46        $this->preventsTalkEdit = $preventTalkEdit;
47    }
48
49    /**
50     * @inheritDoc
51     */
52    public function execute(): bool {
53        $status = $this->doBlockInternal(
54            $this->parameters->getFilter()->getName(),
55            $this->parameters->getFilter()->getID(),
56            $this->parameters->getUser()->getName(),
57            $this->expiry,
58            $autoblock = true,
59            $this->preventsTalkEdit
60        );
61        // TODO: Should we reblock in case of partial blocks? At that point we could return
62        // the status of doBlockInternal
63        return defined( 'MW_PHPUNIT_TEST' ) ? $status->isOK() : true;
64    }
65
66    /**
67     * @inheritDoc
68     * @todo This could use UnblockUser, but we need to check if the block was performed by the AF user
69     */
70    public function revert( UserIdentity $performer, string $reason ): bool {
71        $block = $this->databaseBlockStore->newFromTarget( $this->parameters->getUser()->getName() );
72        if ( !( $block && $block->getBy() === $this->filterUser->getUserIdentity()->getId() ) ) {
73            // Not blocked by abuse filter
74            return false;
75        }
76        if ( !$this->databaseBlockStore->deleteBlock( $block ) ) {
77            return false;
78        }
79        $logEntry = new ManualLogEntry( 'block', 'unblock' );
80        $logEntry->setTarget( new TitleValue( NS_USER, $this->parameters->getUser()->getName() ) );
81        $logEntry->setComment( $reason );
82        $logEntry->setPerformer( $performer );
83        if ( !defined( 'MW_PHPUNIT_TEST' ) ) {
84            // This has a bazillion of static dependencies all around the place, and a nightmare to deal with in tests
85            // TODO: Remove this check once T253717 is resolved
86            // @codeCoverageIgnoreStart
87            $logEntry->publish( $logEntry->insert() );
88            // @codeCoverageIgnoreEnd
89        }
90        return true;
91    }
92
93    /**
94     * @inheritDoc
95     */
96    public function getMessage(): array {
97        $filter = $this->parameters->getFilter();
98        return [
99            'abusefilter-blocked-display',
100            $filter->getName(),
101            GlobalNameUtils::buildGlobalName( $filter->getID(), $this->parameters->getIsGlobalFilter() )
102        ];
103    }
104
105    /**
106     * @return string
107     * @internal
108     */
109    public function getExpiry(): string {
110        return $this->expiry;
111    }
112}