Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 351
0.00% covered (danger)
0.00%
0 / 28
CRAP
0.00% covered (danger)
0.00%
0 / 1
GenerateSampleNotifications
0.00% covered (danger)
0.00%
0 / 345
0.00% covered (danger)
0.00%
0 / 28
4032
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 30
0.00% covered (danger)
0.00%
0 / 1
2
 execute
0.00% covered (danger)
0.00%
0 / 35
0.00% covered (danger)
0.00%
0 / 1
210
 getTimestamp
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
12
 addTimestampToOutput
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 generateEditUserTalk
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 getOptionUser
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
6
 generateRandomString
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 confirm
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
12
 addToUserTalk
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 addToPageContent
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
20
 generateMention
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
2
 generatePageLink
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 generateNewPageTitle
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 generateReverted
0.00% covered (danger)
0.00%
0 / 40
0.00% covered (danger)
0.00%
0 / 1
20
 generateWelcome
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
2
 generateEmail
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
2
 generateUserRights
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
2
 createUserRightsNotification
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
2
 generateContentTranslation
0.00% covered (danger)
0.00%
0 / 23
0.00% covered (danger)
0.00%
0 / 1
12
 generateOnePageLink
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
2
 generateMultiplePageLinks
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
 generateOpenStackManager
0.00% covered (danger)
0.00%
0 / 22
0.00% covered (danger)
0.00%
0 / 1
12
 shouldGenerate
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 generateEditThanks
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 generateOneEditThanks
0.00% covered (danger)
0.00%
0 / 17
0.00% covered (danger)
0.00%
0 / 1
6
 generateMultipleEditThanks
0.00% covered (danger)
0.00%
0 / 28
0.00% covered (danger)
0.00%
0 / 1
6
 generateEducationProgram
0.00% covered (danger)
0.00%
0 / 24
0.00% covered (danger)
0.00%
0 / 1
20
 generateWikibase
0.00% covered (danger)
0.00%
0 / 20
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2// phpcs:disable Generic.Files.LineLength -- Long html test examples
3// @phan-file-suppress PhanUndeclaredClassMethod, PhanUndeclaredClassConstant Other extensions used for testing purposes
4
5use MediaWiki\Extension\Notifications\Model\Event;
6use MediaWiki\Revision\RevisionRecord;
7use MediaWiki\Revision\SlotRecord;
8use MediaWiki\Title\Title;
9use MediaWiki\User\User;
10
11$IP = getenv( 'MW_INSTALL_PATH' );
12if ( $IP === false ) {
13    $IP = __DIR__ . '/../../..';
14}
15require_once "$IP/maintenance/Maintenance.php";
16
17/**
18 * A maintenance script that generates sample notifications for testing purposes.
19 */
20class GenerateSampleNotifications extends Maintenance {
21
22    /** @var string[] */
23    private $supportedNotificationTypes = [
24        'welcome',
25        'edit-user-talk',
26        'mention',
27        'page-linked',
28        'reverted',
29        'email',
30        'user-rights',
31        'cx',
32        'osm',
33        'edit-thanks',
34        'edu',
35        'page-connection',
36    ];
37
38    /** @var int */
39    private $timestampCounter = 5;
40
41    public function __construct() {
42        parent::__construct();
43        $this->addDescription( "Generate sample notifications" );
44
45        $this->addOption(
46            'force',
47            'Bypass confirmation',
48            false, false, 'f' );
49
50        $allTypes = implode( ',', $this->supportedNotificationTypes );
51        $this->addOption(
52            'types',
53            "Comma-separated list of notification types to generate ($allTypes)",
54            false, true, 't' );
55
56        $this->addOption(
57            'user',
58            'Name of the user receiving the notifications',
59            true, true, 'u' );
60
61        $this->addOption(
62            'agent',
63            'Name of the user creating the notifications',
64            true, true, 'a' );
65
66        $this->addOption(
67            'other',
68            'Name of another user involved with the notifications',
69            true, true, 'o' );
70
71        $this->requireExtension( 'Echo' );
72
73        $this->addOption(
74            'timestamp',
75            'Add notification timestamps (Epoch time format). All notifications that are not ' .
76                'related directly to edits will be created with a timestamp starting 5 minutes ' .
77                'before the given timestamp, and increasing by 1 minute per notification.',
78            false, false, 'k' );
79    }
80
81    public function execute() {
82        $user = $this->getOptionUser( 'user' );
83        $agent = $this->getOptionUser( 'agent' );
84        $otherUser = $this->getOptionUser( 'other' );
85        $title = Title::newFromText( 'This is a pretty long page title lets see if it is going to be truncated' );
86
87        $types = $this->getOption( 'types' );
88        if ( $types ) {
89            $types = explode( ',', $types );
90        } else {
91            $types = $this->supportedNotificationTypes;
92        }
93
94        $this->confirm();
95
96        $this->output( "Started processing...\n" );
97
98        if ( $this->shouldGenerate( 'welcome', $types ) ) {
99            $this->generateWelcome( $user );
100        }
101
102        if ( $this->shouldGenerate( 'edit-user-talk', $types ) ) {
103            $this->generateEditUserTalk( $user, $agent );
104        }
105
106        if ( $this->shouldGenerate( 'mention', $types ) ) {
107            $this->generateMention( $user, $agent, $otherUser, $title );
108        }
109
110        if ( $this->shouldGenerate( 'page-linked', $types ) ) {
111            $this->generatePageLink( $user, $agent );
112        }
113
114        if ( $this->shouldGenerate( 'reverted', $types ) ) {
115            $this->generateReverted( $user, $agent );
116        }
117
118        if ( $this->shouldGenerate( 'email', $types ) ) {
119            $this->generateEmail( $user, $agent );
120        }
121
122        if ( $this->shouldGenerate( 'user-rights', $types ) ) {
123            $this->generateUserRights( $user, $agent );
124        }
125
126        if ( $this->shouldGenerate( 'cx', $types ) ) {
127            $this->generateContentTranslation( $user );
128        }
129
130        if ( $this->shouldGenerate( 'osm', $types ) ) {
131            $this->generateOpenStackManager( $user, $agent );
132        }
133
134        if ( $this->shouldGenerate( 'edit-thanks', $types ) ) {
135            $this->generateEditThanks( $user, $agent, $otherUser );
136        }
137
138        if ( $this->shouldGenerate( 'edu', $types ) ) {
139            $this->generateEducationProgram( $user, $agent );
140        }
141
142        if ( $this->shouldGenerate( 'page-connection', $types ) ) {
143            $this->generateWikibase( $user, $agent );
144        }
145
146        $this->output( "Completed \n" );
147    }
148
149    /**
150     * Get the set timestamp of the event
151     *
152     * @param bool $getEpoch Get the epoch value
153     * @return int Timestamp for the operation
154     */
155    private function getTimestamp( $getEpoch = false ) {
156        $startTime = $this->getOption( 'timestamp' ) ?: time();
157
158        // Incrementally decrease X minutes from start time
159        $timestamp = strtotime( '-' . $this->timestampCounter++ . ' minute', $startTime );
160
161        return $getEpoch ? $timestamp : (int)wfTimestamp( TS_UNIX, $timestamp );
162    }
163
164    /**
165     * Add a timestamp string to the output, if a timestamp option was given,
166     * to note the time of the new generated event.
167     *
168     * @param string $output New output message with timestamp
169     * @return string
170     */
171    private function addTimestampToOutput( $output ) {
172        if ( $this->getOption( 'timestamp' ) ) {
173            $output .= ' (Using timestamp: ' . date( 'Y-m-d H:i:s', $this->getTimestamp( true ) ) . ')';
174        }
175        return $output;
176    }
177
178    private function generateEditUserTalk( User $user, User $agent ) {
179        $this->output( "{$agent->getName()} is writing on {$user->getName()}'s user talk page\n" );
180        $editId = $this->generateRandomString();
181        $section = "== section $editId ==\n\nthis is the text $editId\n\n~~~~\n\n";
182        $this->addToUserTalk( $user, $agent, $section );
183    }
184
185    private function getOptionUser( $optionName ) {
186        $username = $this->getOption( $optionName );
187        $user = User::newFromName( $username );
188        if ( !$user->isRegistered() ) {
189            $this->fatalError( "User $username does not seem to exist in this wiki" );
190        }
191        return $user;
192    }
193
194    private function generateRandomString( $length = 10 ) {
195        return substr( str_shuffle( "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" ), 0, $length );
196    }
197
198    protected function confirm() {
199        if ( $this->getOption( 'force', false ) ) {
200            return;
201        }
202        $this->output( "===   WARNING   ===\n" );
203        $this->output( "This script modifies the content of several pages,\n" );
204        $this->output( "including user's talk pages.\n" );
205        $this->output( "ONLY RUN ON TEST WIKIS\n" );
206        $this->output( "Enter 'yes' if you wish to continue or any other key to exit\n" );
207        $confirm = $this->readconsole();
208        if ( $confirm !== 'yes' ) {
209            $this->fatalError( 'Safe decision' );
210        }
211    }
212
213    private function addToUserTalk( User $user, User $agent, $contentText ) {
214        $this->addToPageContent( $user->getTalkPage(), $agent, $contentText );
215    }
216
217    private function addToPageContent( Title $title, User $agent, $contentText ) {
218        $page = $this->getServiceContainer()->getWikiPageFactory()->newFromTitle( $title );
219        $previousContent = "";
220        $page->loadPageData( IDBAccessObject::READ_LATEST );
221        $revision = $page->getRevisionRecord();
222        if ( $revision ) {
223            $content = $revision->getContent( SlotRecord::MAIN, RevisionRecord::FOR_PUBLIC );
224            if ( $content instanceof WikitextContent ) {
225                $previousContent = $content->getText();
226            }
227        }
228        $status = $page->doUserEditContent(
229            new WikitextContent( $contentText . $previousContent ),
230            $agent,
231            'generating sample notifications'
232        );
233
234        if ( !$status->isGood() ) {
235            $this->error( "Failed to edit {$title->getPrefixedText()}{$status->getMessage()->text()}" );
236        }
237
238        return $status->getValue()['revision-record'];
239    }
240
241    private function generateMention( User $user, User $agent, User $otherUser, Title $title ) {
242        $mention = "== section {$this->generateRandomString()} ==\nHello [[User:{$user->getName()}]] \n~~~~\n";
243
244        // article talk
245        $this->output( "{$agent->getName()} is mentioning {$user->getName()} on {$title->getTalkPage()->getPrefixedText()}\n" );
246        $this->addToPageContent( $title->getTalkPage(), $agent, $mention );
247
248        // agent talk
249        $this->output( "{$agent->getName()} is mentioning {$user->getName()} on {$agent->getTalkPage()->getPrefixedText()}\n" );
250        $this->addToPageContent( $agent->getTalkPage(), $agent, $mention );
251
252        // user talk
253        $this->output( "{$agent->getName()} is mentioning {$user->getName()} on {$otherUser->getTalkPage()->getPrefixedText()}\n" );
254        $this->addToPageContent( $otherUser->getTalkPage(), $agent, $mention );
255
256        // any other page
257        $this->output( "{$agent->getName()} is mentioning {$user->getName()} on {$title->getPrefixedText()}\n" );
258        $this->addToPageContent( $title, $agent, $mention );
259    }
260
261    private function generatePageLink( User $user, User $agent ) {
262        $this->generateOnePageLink( $user, $agent );
263        $this->generateMultiplePageLinks( $user, $agent );
264    }
265
266    private function generateNewPageTitle() {
267        return Title::newFromText( $this->generateRandomString() );
268    }
269
270    private function generateReverted( User $user, User $agent ) {
271        $services = $this->getServiceContainer();
272        $services->getUserGroupManager()->addUserToGroup( $agent, 'sysop' );
273
274        // revert (undo)
275        $moai = Title::newFromText( 'Moai' );
276        $page = $services->getWikiPageFactory()->newFromTitle( $moai );
277        $this->output( "{$agent->getName()} is reverting {$user->getName()}'s edit on {$moai->getPrefixedText()}\n" );
278        $this->addToPageContent( $moai, $agent, "\ncreating a good revision here\n" );
279        $this->addToPageContent( $moai, $user, "\nadding a line here\n" );
280
281        $undoRev = $page->getRevisionRecord();
282        $previous = $services->getRevisionLookup()
283            ->getPreviousRevision( $undoRev );
284
285        $handler = $services->getContentHandlerFactory()
286            ->getContentHandler(
287                $undoRev->getSlot( SlotRecord::MAIN, RevisionRecord::RAW )
288                    ->getModel()
289            );
290        $undoContent = $undoRev->getContent( SlotRecord::MAIN );
291        $previousContent = $previous->getContent( SlotRecord::MAIN );
292
293        if ( !$undoContent ) {
294            $this->error( "Failed to undo {$moai->getPrefixedText()}: undoContent is null." );
295            return;
296        }
297
298        if ( !$previousContent ) {
299            $this->error( "Failed to undo {$moai->getPrefixedText()}: previousContent is null." );
300            return;
301        }
302
303        $content = $handler->getUndoContent(
304            $undoContent,
305            $undoContent,
306            $previousContent,
307            // undoIsLatest
308            true
309        );
310
311        $status = $page->doUserEditContent(
312            $content,
313            $agent,
314            'undo',
315            // $flags
316            0,
317            // $originalRevId
318            false,
319            // $tags
320            [],
321            $undoRev->getId()
322        );
323
324        if ( !$status->isGood() ) {
325            $this->error( "Failed to undo {$moai->getPrefixedText()}{$status->getMessage()->text()}" );
326        }
327    }
328
329    private function generateWelcome( User $user ) {
330        $this->output( "Welcoming {$user->getName()}\n" );
331        Event::create( [
332            'type' => 'welcome',
333            'agent' => $user,
334            'timestamp' => $this->getTimestamp(),
335        ] );
336    }
337
338    private function generateEmail( User $user, User $agent ) {
339        $output = $this->addTimestampToOutput( "{$agent->getName()} is emailing {$user->getName()}" );
340        $this->output( "$output\n" );
341        Event::create( [
342            'type' => 'emailuser',
343            'extra' => [
344                'to-user-id' => $user->getId(),
345                'subject' => 'Long time no see',
346            ],
347            'agent' => $agent,
348            'timestamp' => $this->getTimestamp(),
349        ] );
350    }
351
352    private function generateUserRights( User $user, User $agent ) {
353        $output = $this->addTimestampToOutput( "{$agent->getName()} is changing {$user->getName()}'s rights" );
354        $this->output( "$output\n" );
355        $this->createUserRightsNotification( $user, $agent, [ 'OnlyAdd-1' ], null );
356        $this->createUserRightsNotification( $user, $agent, null, [ 'JustRemove-1', 'JustRemove-2' ] );
357        $this->createUserRightsNotification( $user, $agent, [ 'Add-1', 'Add-2' ], [ 'Remove-1', 'Remove-2' ] );
358    }
359
360    private function createUserRightsNotification( User $user, User $agent, $add, $remove ) {
361        Event::create(
362            [
363                'type' => 'user-rights',
364                'extra' => [
365                    'user' => $user->getId(),
366                    'add' => $add,
367                    'remove' => $remove,
368                    'reason' => 'This is the [[reason]] for changing your user rights.',
369                ],
370                'agent' => $agent,
371                'timestamp' => $this->getTimestamp(),
372            ]
373        );
374    }
375
376    private function generateContentTranslation( User $user ) {
377        if ( !ExtensionRegistry::getInstance()->isLoaded( 'ContentTranslation' ) ) {
378            return;
379        }
380
381        $this->output( "Generating CX notifications\n" );
382        foreach ( [ 'cx-first-translation', 'cx-tenth-translation', 'cx-hundredth-translation' ] as $eventType ) {
383            Event::create(
384                [
385                    'type' => $eventType,
386                    'extra' => [
387                        'recipient' => $user->getId(),
388                    ],
389                    'timestamp' => $this->getTimestamp(),
390                ]
391            );
392        }
393
394        Event::create(
395            [
396                'type' => 'cx-suggestions-available',
397                'extra' => [
398                    'recipient' => $user->getId(),
399                    'lastTranslationTitle' => 'History of the People\'s Republic of China'
400                ],
401                'timestamp' => $this->getTimestamp(),
402            ]
403        );
404    }
405
406    private function generateOnePageLink( User $user, User $agent ) {
407        $pageBeingLinked = $this->generateNewPageTitle();
408        $this->addToPageContent( $pageBeingLinked, $user, "this is a new page" );
409
410        $pageLinking = $this->generateNewPageTitle();
411        $content = "checkout [[{$pageBeingLinked->getPrefixedText()}]]!";
412        $this->output( "{$agent->getName()} is linking to {$pageBeingLinked->getPrefixedText()} from {$pageLinking->getPrefixedText()}\n" );
413        $this->addToPageContent( $pageLinking, $agent, $content );
414    }
415
416    private function generateMultiplePageLinks( User $user, User $agent ) {
417        $pageBeingLinked = $this->generateNewPageTitle();
418        $this->addToPageContent( $pageBeingLinked, $user, "this is a new page" );
419
420        $content = "checkout [[{$pageBeingLinked->getPrefixedText()}]]!";
421        $this->output( "{$agent->getName()} is linking to {$pageBeingLinked->getPrefixedText()} from multiple pages\n" );
422        $this->addToPageContent( $this->generateNewPageTitle(), $agent, $content );
423        // @phan-suppress-next-line PhanPluginDuplicateAdjacentStatement
424        $this->addToPageContent( $this->generateNewPageTitle(), $agent, $content );
425        // @phan-suppress-next-line PhanPluginDuplicateAdjacentStatement
426        $this->addToPageContent( $this->generateNewPageTitle(), $agent, $content );
427    }
428
429    private function generateOpenStackManager( User $user, User $agent ) {
430        if ( !ExtensionRegistry::getInstance()->isLoaded( 'OpenStackManager' ) ) {
431            return;
432        }
433
434        $this->output( "Generating OpenStackManager notifications\n" );
435
436        foreach ( [ 'build-completed', 'reboot-completed', 'deleted' ] as $action ) {
437            Event::create( [
438                'type' => "osm-instance-$action",
439                'title' => Title::newFromText( "Moai" ),
440                'agent' => $user,
441                'extra' => [
442                    'instanceName' => 'instance1',
443                    'projectName' => 'TheProject',
444                    'notifyAgent' => true,
445                ],
446                'timestamp' => $this->getTimestamp(),
447            ] );
448        }
449
450        Event::create( [
451            'type' => 'osm-projectmembers-add',
452            'title' => Title::newFromText( "Moai" ),
453            'agent' => $agent,
454            'extra' => [ 'userAdded' => $user->getId() ],
455            'timestamp' => $this->getTimestamp(),
456        ] );
457    }
458
459    private function shouldGenerate( $type, array $types ) {
460        return in_array( $type, $types );
461    }
462
463    private function generateEditThanks( User $user, User $agent, User $otherUser ) {
464        $this->generateOneEditThanks( $user, $agent );
465        $this->generateMultipleEditThanks( $user, $agent, $otherUser );
466    }
467
468    private function generateOneEditThanks( User $user, User $agent ) {
469        if ( !ExtensionRegistry::getInstance()->isLoaded( 'Thanks' ) ) {
470            return;
471        }
472        // make an edit, thank it once
473        $title = $this->generateNewPageTitle();
474        $revisionRecord = $this->addToPageContent( $title, $user, "an awesome edit! ~~~~" );
475        Event::create( [
476            'type' => 'edit-thank',
477            'title' => $title,
478            'extra' => [
479                'revid' => $revisionRecord->getId(),
480                'thanked-user-id' => $user->getId(),
481                'source' => 'generateSampleNotifications.php',
482            ],
483            'agent' => $agent,
484            'timestamp' => $this->getTimestamp(),
485        ] );
486        $output = $this->addTimestampToOutput( "{$agent->getName()} is thanking {$user->getName()} for edit {$revisionRecord->getId()} on {$title->getPrefixedText()}" );
487        $this->output( "$output\n" );
488    }
489
490    private function generateMultipleEditThanks( User $user, User $agent, User $otherUser ) {
491        if ( !ExtensionRegistry::getInstance()->isLoaded( 'Thanks' ) ) {
492            return;
493        }
494        // make an edit, thank it twice
495        $title = $this->generateNewPageTitle();
496        $revisionRecord = $this->addToPageContent( $title, $user, "an even better edit! ~~~~" );
497        Event::create( [
498            'type' => 'edit-thank',
499            'title' => $title,
500            'extra' => [
501                'revid' => $revisionRecord->getId(),
502                'thanked-user-id' => $user->getId(),
503                'source' => 'generateSampleNotifications.php',
504            ],
505            'agent' => $agent,
506            'timestamp' => $this->getTimestamp(),
507        ] );
508        Event::create( [
509            'type' => 'edit-thank',
510            'title' => $title,
511            'extra' => [
512                'revid' => $revisionRecord->getId(),
513                'thanked-user-id' => $user->getId(),
514                'source' => 'generateSampleNotifications.php',
515            ],
516            'agent' => $otherUser,
517            'timestamp' => $this->getTimestamp(),
518        ] );
519        $output = $this->addTimestampToOutput( "{$agent->getName()} and {$otherUser->getName()} are thanking {$user->getName()} for edit {$revisionRecord->getId()} on {$title->getPrefixedText()}" );
520        $this->output( "$output\n" );
521    }
522
523    private function generateEducationProgram( User $user, User $agent ) {
524        if ( !ExtensionRegistry::getInstance()->isLoaded( 'EducationProgram' ) ) {
525            $this->output( "Skipping EducationProgram. Extension not installed.\n" );
526            return;
527        }
528
529        $chem101 = Title::newFromText( 'School/Chemistry101' );
530        if ( !$chem101->exists() ) {
531            $this->addToPageContent( $chem101, $agent, "\nThis is the main page for the Chemistry 101 course\n" );
532        }
533
534        $notificationManager = EducationProgram\Extension::globalInstance()->getNotificationsManager();
535
536        $output = $this->addTimestampToOutput( "{$agent->getName()} is adding {$user->getName()} to {$chem101->getPrefixedText()} as instructor, student, campus volunteer and online volunteer" );
537        $this->output( "$output\n" );
538
539        $types = [
540            'ep-instructor-add-notification',
541            'ep-online-add-notification',
542            'ep-campus-add-notification',
543            'ep-student-add-notification',
544        ];
545        foreach ( $types as $type ) {
546            $notificationManager->trigger(
547                $type,
548                [
549                    'role-add-title' => $chem101,
550                    'agent' => $agent,
551                    'users' => [ $user->getId() ],
552                ]
553            );
554        }
555
556        // NOTE: Not generating 'ep-course-talk-notification' for now
557        // as it requires a full setup to actually work (institution, course, instructors, students).
558    }
559
560    private function generateWikibase( User $user, User $agent ) {
561        if ( !ExtensionRegistry::getInstance()->isLoaded( 'WikibaseClient' ) ) {
562            $this->output( "Skipping Wikibase. Extension not installed.\n" );
563            return;
564        }
565
566        $title = $this->generateNewPageTitle();
567        $this->addToPageContent( $title, $user, "this is a new page" );
568        $helpPage = Title::newFromText( 'Project:Wikidata' );
569        $this->addToPageContent( $helpPage, $user, "this is the help page" );
570
571        $output = $this->addTimestampToOutput( "{$agent->getName()} is connecting {$user->getName()}'s page {$title->getPrefixedText()} to an item" );
572        $this->output( "$output\n" );
573        Event::create( [
574            'type' => EchoNotificationsHandlers::NOTIFICATION_TYPE,
575            'title' => $title,
576            'extra' => [
577                'url' => Title::newFromText( 'Item:Q1' )->getFullURL(),
578                'repoSiteName' => 'Wikidata',
579                'entity' => 'Q1',
580            ],
581            'agent' => $agent,
582            'timestamp' => $this->getTimestamp(),
583        ] );
584    }
585}
586
587$maintClass = GenerateSampleNotifications::class;
588require_once RUN_MAINTENANCE_IF_MAIN;