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