Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
77.50% covered (warning)
77.50%
62 / 80
50.00% covered (danger)
50.00%
2 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
AutoModeratorSendRevertTalkPageMsgJob
77.50% covered (warning)
77.50%
62 / 80
50.00% covered (danger)
50.00%
2 / 4
14.93
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
1
 run
80.77% covered (warning)
80.77%
42 / 52
0.00% covered (danger)
0.00%
0 / 1
7.35
 setAllowRetries
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 allowRetries
n/a
0 / 0
n/a
0 / 0
1
 ignoreDuplicates
n/a
0 / 0
n/a
0 / 0
1
 createTalkPageMessageContent
50.00% covered (danger)
50.00%
8 / 16
0.00% covered (danger)
0.00%
0 / 1
2.50
1<?php
2/**
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program.  If not, see <http:www.gnu.org/licenses/>.
15 */
16
17namespace AutoModerator\Services;
18
19use AutoModerator\Config\AutoModeratorConfigLoaderStaticTrait;
20use Content;
21use Job;
22use MediaWiki\CommentStore\CommentStoreComment;
23use MediaWiki\Logger\LoggerFactory;
24use MediaWiki\MediaWikiServices;
25use MediaWiki\Revision\SlotRecord;
26use MediaWiki\Title\Title;
27use RuntimeException;
28
29class AutoModeratorSendRevertTalkPageMsgJob extends Job {
30
31    use AutoModeratorConfigLoaderStaticTrait;
32
33    /**
34     * @var bool
35     */
36    private bool $isRetryable = true;
37
38    /**
39     * @var int
40     */
41    private $wikiPageId;
42
43    /**
44     * @var int
45     */
46    private $revId;
47
48    /**
49     * @var int
50     */
51    private int $parentRevId;
52
53    /**
54     * @var ?string
55     */
56    private ?string $pageTitle;
57
58    /**
59     * @var int
60     */
61    private int $autoModeratorUserId;
62
63    /**
64     * @var string
65     */
66    private string $autoModeratorUserName;
67
68    /**
69     * @var string
70     */
71    private string $talkPageMessageHeader;
72
73    /**
74     * @var string
75     */
76    private string $talkPageMessageEditSummary;
77
78    /**
79     * @var string
80     */
81    private string $falsePositiveReportPage;
82
83    /**
84     * @var string
85     */
86    private string $wikiId;
87
88    /**
89     * @var string
90     */
91    private string $NOT_WIKI_TEXT_ERROR_MESSAGE = 'Failed to send AutoModerator revert talk page message
92    due to content model not being wikitext the current content model is: ';
93
94    /**
95     * @var string
96     */
97    private string $NO_USER_TALK_PAGE_ERROR_MESSAGE = "Failed to retrieve user talk page title
98            for sending AutoModerator revert talk page message.";
99
100    /**
101     * @var string
102     */
103    private string $NO_PARENT_REVISION_FOUND = "Failed to retrieve reverted revision from revision store.";
104
105    /**
106     * @var string
107     */
108    private string $NO_CONTENT_TALK_PAGE_ERROR_MESSAGE = "Failed to create AutoModerator revert message
109    content for talk page.";
110
111    /**
112     * @var string
113     */
114    private string $CREATE_TALK_PAGE_ERROR_MESSAGE = "Failed to create message for sending AutoModerator revert
115     talk page message.";
116
117    /**
118     * @param Title $title
119     * @param array $params
120     *    - 'wikiPageId': (int)
121     *    - 'revId': (int)
122     *    - 'parentRevId': (int)
123     *    - 'autoModeratorUserId': (int)
124     *    - 'autoModeratorUserName': (string)
125     *    - 'talkPageMessageHeader': (string)
126     *    - 'talkPageMessageEditSummary': (string)
127     *    - 'falsePositiveReportPage': (string)
128     *    - 'wikiId': (string)
129     */
130    public function __construct( Title $title, array $params ) {
131        parent::__construct( 'AutoModeratorSendRevertTalkPageMsgJob', $title, $params );
132        $this->pageTitle = $title;
133        $this->wikiPageId = $params['wikiPageId'];
134        $this->revId = $params['revId'];
135        $this->parentRevId = $params['parentRevId'];
136        $this->autoModeratorUserId = $params['autoModeratorUserId'];
137        $this->autoModeratorUserName = $params['autoModeratorUserName'];
138        $this->talkPageMessageHeader = $params['talkPageMessageHeader'];
139        $this->talkPageMessageEditSummary = $params['talkPageMessageEditSummary'];
140        $this->falsePositiveReportPage = $params['falsePositiveReportPage'] ?? "";
141        $this->wikiId = $params['wikiId'];
142    }
143
144    public function run(): bool {
145        $logger = LoggerFactory::getInstance( 'AutoModerator' );
146        try {
147            $services = MediaWikiServices::getInstance();
148            $userFactory = $services->getUserFactory();
149            $revisionStore = $services->getRevisionStore();
150            $parentRevision = $revisionStore->getRevisionById( $this->parentRevId );
151            if ( !$parentRevision ) {
152                $this->setLastError( $this->NO_PARENT_REVISION_FOUND );
153                $this->setAllowRetries( false );
154                return false;
155            }
156            $userTalkPageTitle = $services->getTitleFactory()->makeTitleSafe(
157                NS_USER_TALK,
158                $parentRevision->getUser()->getName()
159            );
160            if ( !$userTalkPageTitle ) {
161                $this->setLastError( $this->NO_USER_TALK_PAGE_ERROR_MESSAGE );
162                $this->setAllowRetries( false );
163                return false;
164            }
165            $autoModeratorUser = $userFactory->newFromAnyId(
166                $this->params['autoModeratorUserId'],
167                $this->params['autoModeratorUserName']
168            );
169            $userTalkPage = $services->getWikiPageFactory()->newFromTitle( $userTalkPageTitle );
170            $currentContentModel = $userTalkPage->getContentModel();
171            if ( $currentContentModel !== CONTENT_MODEL_WIKITEXT ) {
172                $logger->error( $this->NOT_WIKI_TEXT_ERROR_MESSAGE . $currentContentModel );
173                $this->setLastError( $this->NOT_WIKI_TEXT_ERROR_MESSAGE . $currentContentModel );
174                $this->setAllowRetries( false );
175                return false;
176            }
177            $updatedContent = $this->createTalkPageMessageContent(
178                $userTalkPage->getContent(),
179                $this->talkPageMessageHeader,
180                wfMessage( 'automoderator-wiki-revert-message' )->params(
181                    $this->autoModeratorUserName,
182                    $this->revId,
183                    $this->pageTitle,
184                    $this->falsePositiveReportPage )->plain(),
185                $userTalkPageTitle,
186                $currentContentModel );
187            if ( !$updatedContent ) {
188                $logger->error( $this->NO_CONTENT_TALK_PAGE_ERROR_MESSAGE );
189                $this->setLastError( $this->NO_CONTENT_TALK_PAGE_ERROR_MESSAGE );
190                return false;
191            }
192            $userTalkPage
193                ->newPageUpdater( $autoModeratorUser )
194                ->setContent( SlotRecord::MAIN, $updatedContent )
195                ->saveRevision( CommentStoreComment::newUnsavedComment( $this->talkPageMessageEditSummary ),
196              $userTalkPage->exists() ? EDIT_UPDATE : EDIT_NEW );
197        } catch ( RuntimeException $e ) {
198            $this->setLastError( $this->CREATE_TALK_PAGE_ERROR_MESSAGE );
199            $logger->error( $this->CREATE_TALK_PAGE_ERROR_MESSAGE );
200            return false;
201        }
202        return true;
203    }
204
205    private function setAllowRetries( bool $isRetryable ) {
206        $this->isRetryable = $isRetryable;
207    }
208
209    /**
210     * @inheritDoc
211     * @codeCoverageIgnore
212     */
213    public function allowRetries(): bool {
214        return $this->isRetryable;
215    }
216
217    /**
218     * @inheritDoc
219     * @codeCoverageIgnore
220     */
221    public function ignoreDuplicates(): bool {
222        return true;
223    }
224
225    /**
226     * @param ?Content $currentContent
227     * @param string $headerRawMessage
228     * @param string $messageContent
229     * @param Title $userTalkPageTitle
230     * @return Content|null
231     */
232    private function createTalkPageMessageContent( ?Content $currentContent,
233                                                   string $headerRawMessage,
234                                                   string $messageContent,
235                                                   Title $userTalkPageTitle,
236                                                   string $contentModel ): ?Content {
237        if ( $currentContent ) {
238            $newLine = "\n";
239            return $currentContent->getContentHandler()->makeContent(
240                $currentContent->getWikitextForTransclusion() . $newLine . $headerRawMessage . $newLine .
241                $messageContent,
242                $userTalkPageTitle,
243                $contentModel
244            );
245        } else {
246            $contentHandler = MediaWikiServices::getInstance()
247                ->getContentHandlerFactory()
248                ->getContentHandler( $contentModel );
249            return $contentHandler->makeContent(
250                $headerRawMessage . $messageContent,
251                $userTalkPageTitle,
252                $contentModel
253            );
254        }
255    }
256}