]> scripts.mit.edu Git - autoinstalls/mediawiki.git/blob - maintenance/importTextFiles.php
MediaWiki 1.30.2
[autoinstalls/mediawiki.git] / maintenance / importTextFiles.php
1 <?php
2 /**
3  * Import pages from text files
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  * http://www.gnu.org/copyleft/gpl.html
19  *
20  * @file
21  * @ingroup Maintenance
22  */
23
24 use MediaWiki\MediaWikiServices;
25
26 require_once __DIR__ . '/Maintenance.php';
27
28 /**
29  * Maintenance script which reads in text files
30  * and imports their content to a page of the wiki.
31  *
32  * @ingroup Maintenance
33  */
34 class ImportTextFiles extends Maintenance {
35         public function __construct() {
36                 parent::__construct();
37                 $this->addDescription( 'Reads in text files and imports their content to pages of the wiki' );
38                 $this->addOption( 'user', 'Username to which edits should be attributed. ' .
39                         'Default: "Maintenance script"', false, true, 'u' );
40                 $this->addOption( 'summary', 'Specify edit summary for the edits', false, true, 's' );
41                 $this->addOption( 'use-timestamp', 'Use the modification date of the text file ' .
42                         'as the timestamp for the edit' );
43                 $this->addOption( 'overwrite', 'Overwrite existing pages. If --use-timestamp is passed, this ' .
44                         'will only overwrite pages if the file has been modified since the page was last modified.' );
45                 $this->addOption( 'prefix', 'A string to place in front of the file name', false, true, 'p' );
46                 $this->addOption( 'bot', 'Mark edits as bot edits in the recent changes list.' );
47                 $this->addOption( 'rc', 'Place revisions in RecentChanges.' );
48                 $this->addArg( 'files', 'Files to import' );
49         }
50
51         public function execute() {
52                 $userName = $this->getOption( 'user', false );
53                 $summary = $this->getOption( 'summary', 'Imported from text file' );
54                 $useTimestamp = $this->hasOption( 'use-timestamp' );
55                 $rc = $this->hasOption( 'rc' );
56                 $bot = $this->hasOption( 'bot' );
57                 $overwrite = $this->hasOption( 'overwrite' );
58                 $prefix = $this->getOption( 'prefix', '' );
59
60                 // Get all the arguments. A loop is required since Maintenance doesn't
61                 // support an arbitrary number of arguments.
62                 $files = [];
63                 $i = 0;
64                 while ( $arg = $this->getArg( $i++ ) ) {
65                         if ( file_exists( $arg ) ) {
66                                 $files[$arg] = file_get_contents( $arg );
67                         } else {
68                                 // use glob to support the Windows shell, which doesn't automatically
69                                 // expand wildcards
70                                 $found = false;
71                                 foreach ( glob( $arg ) as $filename ) {
72                                         $found = true;
73                                         $files[$filename] = file_get_contents( $filename );
74                                 }
75                                 if ( !$found ) {
76                                         $this->error( "Fatal error: The file '$arg' does not exist!", 1 );
77                                 }
78                         }
79                 };
80
81                 $count = count( $files );
82                 $this->output( "Importing $count pages...\n" );
83
84                 if ( $userName === false ) {
85                         $user = User::newSystemUser( 'Maintenance script', [ 'steal' => true ] );
86                 } else {
87                         $user = User::newFromName( $userName );
88                 }
89
90                 if ( !$user ) {
91                         $this->error( "Invalid username\n", true );
92                 }
93                 if ( $user->isAnon() ) {
94                         $user->addToDatabase();
95                 }
96
97                 $exit = 0;
98
99                 $successCount = 0;
100                 $failCount = 0;
101                 $skipCount = 0;
102
103                 foreach ( $files as $file => $text ) {
104                         $pageName = $prefix . pathinfo( $file, PATHINFO_FILENAME );
105                         $timestamp = $useTimestamp ? wfTimestamp( TS_UNIX, filemtime( $file ) ) : wfTimestampNow();
106
107                         $title = Title::newFromText( $pageName );
108                         // Have to check for # manually, since it gets interpreted as a fragment
109                         if ( !$title || $title->hasFragment() ) {
110                                 $this->error( "Invalid title $pageName. Skipping.\n" );
111                                 $skipCount++;
112                                 continue;
113                         }
114
115                         $exists = $title->exists();
116                         $oldRevID = $title->getLatestRevID();
117                         $oldRev = $oldRevID ? Revision::newFromId( $oldRevID ) : null;
118                         $actualTitle = $title->getPrefixedText();
119
120                         if ( $exists ) {
121                                 $touched = wfTimestamp( TS_UNIX, $title->getTouched() );
122                                 if ( !$overwrite ) {
123                                         $this->output( "Title $actualTitle already exists. Skipping.\n" );
124                                         $skipCount++;
125                                         continue;
126                                 } elseif ( $useTimestamp && intval( $touched ) >= intval( $timestamp ) ) {
127                                         $this->output( "File for title $actualTitle has not been modified since the " .
128                                                 "destination page was touched. Skipping.\n" );
129                                         $skipCount++;
130                                         continue;
131                                 }
132                         }
133
134                         $rev = new WikiRevision( MediaWikiServices::getInstance()->getMainConfig() );
135                         $rev->setText( rtrim( $text ) );
136                         $rev->setTitle( $title );
137                         $rev->setUserObj( $user );
138                         $rev->setComment( $summary );
139                         $rev->setTimestamp( $timestamp );
140
141                         if ( $exists && $overwrite && $rev->getContent()->equals( $oldRev->getContent() ) ) {
142                                 $this->output( "File for title $actualTitle contains no changes from the current " .
143                                         "revision. Skipping.\n" );
144                                 $skipCount++;
145                                 continue;
146                         }
147
148                         $status = $rev->importOldRevision();
149                         $newId = $title->getLatestRevID();
150
151                         if ( $status ) {
152                                 $action = $exists ? 'updated' : 'created';
153                                 $this->output( "Successfully $action $actualTitle\n" );
154                                 $successCount++;
155                         } else {
156                                 $action = $exists ? 'update' : 'create';
157                                 $this->output( "Failed to $action $actualTitle\n" );
158                                 $failCount++;
159                                 $exit = 1;
160                         }
161
162                         // Create the RecentChanges entry if necessary
163                         if ( $rc && $status ) {
164                                 if ( $exists ) {
165                                         if ( is_object( $oldRev ) ) {
166                                                 $oldContent = $oldRev->getContent();
167                                                 RecentChange::notifyEdit(
168                                                         $timestamp,
169                                                         $title,
170                                                         $rev->getMinor(),
171                                                         $user,
172                                                         $summary,
173                                                         $oldRevID,
174                                                         $oldRev->getTimestamp(),
175                                                         $bot,
176                                                         '',
177                                                         $oldContent ? $oldContent->getSize() : 0,
178                                                         $rev->getContent()->getSize(),
179                                                         $newId,
180                                                         1 /* the pages don't need to be patrolled */
181                                                 );
182                                         }
183                                 } else {
184                                         RecentChange::notifyNew(
185                                                 $timestamp,
186                                                 $title,
187                                                 $rev->getMinor(),
188                                                 $user,
189                                                 $summary,
190                                                 $bot,
191                                                 '',
192                                                 $rev->getContent()->getSize(),
193                                                 $newId,
194                                                 1
195                                         );
196                                 }
197                         }
198                 }
199
200                 $this->output( "Done! $successCount succeeded, $skipCount skipped.\n" );
201                 if ( $exit ) {
202                         $this->error( "Import failed with $failCount failed pages.\n", $exit );
203                 }
204         }
205 }
206
207 $maintClass = "ImportTextFiles";
208 require_once RUN_MAINTENANCE_IF_MAIN;