Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
95.52% covered (success)
95.52%
64 / 67
50.00% covered (danger)
50.00%
1 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
EditCLI
95.52% covered (success)
95.52%
64 / 67
50.00% covered (danger)
50.00%
1 / 2
20
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
18 / 18
100.00% covered (success)
100.00%
1 / 1
1
 execute
93.88% covered (success)
93.88%
46 / 49
0.00% covered (danger)
0.00%
0 / 1
19.08
1<?php
2/**
3 * Make a page edit.
4 *
5 * @license GPL-2.0-or-later
6 * @file
7 * @ingroup Maintenance
8 */
9
10use MediaWiki\CommentStore\CommentStoreComment;
11use MediaWiki\Content\ContentHandler;
12use MediaWiki\Language\RawMessage;
13use MediaWiki\Maintenance\Maintenance;
14use MediaWiki\Revision\SlotRecord;
15use MediaWiki\Title\Title;
16use MediaWiki\User\User;
17
18// @codeCoverageIgnoreStart
19require_once __DIR__ . '/Maintenance.php';
20// @codeCoverageIgnoreEnd
21
22/**
23 * Maintenance script to make a page edit.
24 *
25 * @ingroup Maintenance
26 */
27class EditCLI extends Maintenance {
28    public function __construct() {
29        parent::__construct();
30        $this->addDescription( 'Edit an article from the command line, text is from stdin' );
31        $this->addOption( 'user', 'Username', false, true, 'u' );
32        $this->addOption( 'summary', 'Edit summary', false, true, 's' );
33        $this->addOption( 'remove', 'Remove a slot (requires --slot).', false, false );
34        $this->addOption( 'minor', 'Minor edit', false, false, 'm' );
35        $this->addOption( 'bot', 'Bot edit', false, false, 'b' );
36        $this->addOption( 'autosummary', 'Enable autosummary', false, false, 'a' );
37        $this->addOption( 'no-rc', 'Do not show the change in recent changes', false, false, 'r' );
38        $this->addOption( 'nocreate', 'Don\'t create new pages', false, false );
39        $this->addOption( 'createonly', 'Only create new pages', false, false );
40        $this->addOption( 'slot', 'Slot role name', false, true );
41        $this->addOption(
42            'parse-title',
43            'Parse title input as a message, e.g. "{{int:mainpage}}" or "News_{{CURRENTYEAR}}',
44            false, false, 'p'
45        );
46        $this->addArg( 'title', 'Title of article to edit' );
47    }
48
49    /** @inheritDoc */
50    public function execute() {
51        $userName = $this->getOption( 'user', false );
52        $summary = $this->getOption( 'summary', '' );
53        $remove = $this->hasOption( 'remove' );
54        $minor = $this->hasOption( 'minor' );
55        $bot = $this->hasOption( 'bot' );
56        $autoSummary = $this->hasOption( 'autosummary' );
57        $noRC = $this->hasOption( 'no-rc' );
58        $slot = $this->getOption( 'slot', SlotRecord::MAIN );
59
60        if ( $userName === false ) {
61            $user = User::newSystemUser( User::MAINTENANCE_SCRIPT_USER, [ 'steal' => true ] );
62        } else {
63            $user = User::newFromName( $userName );
64        }
65        if ( !$user ) {
66            $this->fatalError( "Invalid username" );
67        }
68        if ( $user->isAnon() ) {
69            $user->addToDatabase();
70        }
71
72        $titleInput = $this->getArg( 0 );
73
74        if ( $this->hasOption( 'parse-title' ) ) {
75            $titleInput = ( new RawMessage( '$1' ) )->params( $titleInput )->text();
76        }
77
78        $title = Title::newFromText( $titleInput );
79        if ( !$title ) {
80            $this->fatalError( "Invalid title" );
81        }
82
83        if ( $this->hasOption( 'nocreate' ) && !$title->exists() ) {
84            $this->fatalError( "Page does not exist" );
85        } elseif ( $this->hasOption( 'createonly' ) && $title->exists() ) {
86            $this->fatalError( "Page already exists" );
87        }
88
89        $page = $this->getServiceContainer()->getWikiPageFactory()->newFromTitle( $title );
90
91        if ( $remove ) {
92            if ( $slot === SlotRecord::MAIN ) {
93                $this->fatalError( "Cannot remove main slot! Use --slot to specify." );
94            }
95
96            $content = false;
97        } else {
98            # Read the text
99            $text = $this->getStdin( Maintenance::STDIN_ALL );
100            $content = ContentHandler::makeContent( $text, $title );
101        }
102
103        # Do the edit
104        $this->output( "Saving..." );
105        $updater = $page->newPageUpdater( $user );
106
107        $flags = ( $minor ? EDIT_MINOR : 0 ) |
108            ( $bot ? EDIT_FORCE_BOT : 0 ) |
109            ( $autoSummary ? EDIT_AUTOSUMMARY : 0 ) |
110            ( $noRC ? EDIT_SUPPRESS_RC : 0 );
111
112        if ( $content === false ) {
113            $updater->removeSlot( $slot );
114        } else {
115            $updater->setContent( $slot, $content );
116        }
117
118        $updater->saveRevision( CommentStoreComment::newUnsavedComment( $summary ), $flags );
119        $status = $updater->getStatus();
120
121        if ( $status->isOK() ) {
122            $this->output( "done\n" );
123        } else {
124            $this->output( "failed\n" );
125        }
126        if ( !$status->isGood() ) {
127            $this->error( $status );
128        }
129        return $status->isOK();
130    }
131}
132
133// @codeCoverageIgnoreStart
134$maintClass = EditCLI::class;
135require_once RUN_MAINTENANCE_IF_MAIN;
136// @codeCoverageIgnoreEnd