Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 30
0.00% covered (danger)
0.00%
0 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
ArticleChangedJob
0.00% covered (danger)
0.00%
0 / 30
0.00% covered (danger)
0.00%
0 / 4
72
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 newSpec
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
2
 run
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
30
 notify
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace MediaWiki\Extension\Wikistories\Jobs;
4
5use MediaWiki\Config\Config;
6use MediaWiki\Extension\Wikistories\Hooks\EchoNotificationsHandlers;
7use MediaWiki\Extension\Wikistories\PageLinksSearch;
8use MediaWiki\Extension\Wikistories\StoryContent;
9use MediaWiki\Extension\Wikistories\StoryContentAnalyzer;
10use MediaWiki\JobQueue\IJobSpecification;
11use MediaWiki\JobQueue\Job;
12use MediaWiki\JobQueue\JobSpecification;
13use MediaWiki\MediaWikiServices;
14use MediaWiki\Notification\RecipientSet;
15use MediaWiki\Notification\Types\WikiNotification;
16use MediaWiki\Page\WikiPageFactory;
17use MediaWiki\Registration\ExtensionRegistry;
18use MediaWiki\Revision\RevisionLookup;
19use MediaWiki\Title\Title;
20use MediaWiki\User\UserIdentity;
21
22class ArticleChangedJob extends Job {
23
24    private const COMMAND = 'ArticleChangedJob';
25
26    public function __construct(
27        string $command,
28        array $params,
29        private readonly RevisionLookup $revisionLookup,
30        private readonly StoryContentAnalyzer $analyzer,
31        private readonly WikiPageFactory $wikiPageFactory,
32        private readonly PageLinksSearch $pageLinksSearch,
33        private readonly Config $config,
34    ) {
35        // Delay to let multiple edits be deduplicated
36        $params[ 'jobReleaseTimestamp' ] = time() + 60;
37        parent::__construct( self::COMMAND, $params );
38    }
39
40    public static function newSpec( int $pageId ): IJobSpecification {
41        return new JobSpecification(
42            self::COMMAND,
43            [ 'article_id' => $pageId ],
44            [ 'removeDuplicates' => true ]
45        );
46    }
47
48    /**
49     * Run the job
50     *
51     * @return bool Success
52     */
53    public function run(): bool {
54        $notify = ExtensionRegistry::getInstance()->isLoaded( 'Echo' ) &&
55            $this->config->get( 'WikistoriesNotifyAboutStoryMaintenance' );
56        $articleId = $this->params[ 'article_id' ];
57        $rev = $this->revisionLookup->getRevisionByPageId( $articleId );
58        $agent = $rev->getUser();
59        $articleTitle = $rev->getPage()->getDBkey();
60        $pageIds = $this->pageLinksSearch->getPageLinks( $articleTitle, 99 );
61        foreach ( $pageIds as $pageId ) {
62            $page = $this->wikiPageFactory->newFromID( $pageId );
63            /** @var StoryContent $story */
64            $story = $page->getContent();
65            '@phan-var StoryContent $story';
66            if ( $notify && $this->analyzer->hasOutdatedText( $story ) ) {
67                $this->notify( $agent, $page->getTitle(), $articleTitle, $rev->getId() );
68            }
69            $page->doPurge();
70        }
71        return true;
72    }
73
74    private function notify( UserIdentity $agent, Title $storyTitle, string $articleTitle, int $revId ): void {
75        MediaWikiServices::getInstance()->getNotificationService()->notify(
76            new WikiNotification( EchoNotificationsHandlers::NOTIFICATION_TYPE, $storyTitle, $agent, [
77                'articleTitle' => $articleTitle,
78                'articleRevId' => $revId,
79                'notifyAgent' => true,
80            ] ),
81            new RecipientSet( [] )
82        );
83    }
84}