MediaWiki  master
importTextFiles.php
Go to the documentation of this file.
1 <?php
26 
27 require_once __DIR__ . '/Maintenance.php';
28 
36  public function __construct() {
37  parent::__construct();
38  $this->addDescription( 'Reads in text files and imports their content to pages of the wiki' );
39  $this->addOption( 'user', 'Username to which edits should be attributed. ' .
40  'Default: "Maintenance script"', false, true, 'u' );
41  $this->addOption( 'summary', 'Specify edit summary for the edits', false, true, 's' );
42  $this->addOption( 'use-timestamp', 'Use the modification date of the text file ' .
43  'as the timestamp for the edit' );
44  $this->addOption( 'overwrite', 'Overwrite existing pages. If --use-timestamp is passed, this ' .
45  'will only overwrite pages if the file has been modified since the page was last modified.' );
46  $this->addOption( 'prefix', 'A string to place in front of the file name', false, true, 'p' );
47  $this->addOption( 'bot', 'Mark edits as bot edits in the recent changes list.' );
48  $this->addOption( 'rc', 'Place revisions in RecentChanges.' );
49  $this->addArg( 'files', 'Files to import' );
50  }
51 
52  public function execute() {
53  $userName = $this->getOption( 'user', false );
54  $summary = $this->getOption( 'summary', 'Imported from text file' );
55  $useTimestamp = $this->hasOption( 'use-timestamp' );
56  $rc = $this->hasOption( 'rc' );
57  $bot = $this->hasOption( 'bot' );
58  $overwrite = $this->hasOption( 'overwrite' );
59  $prefix = $this->getOption( 'prefix', '' );
60 
61  // Get all the arguments. A loop is required since Maintenance doesn't
62  // support an arbitrary number of arguments.
63  $files = [];
64  $i = 0;
65  while ( $arg = $this->getArg( $i++ ) ) {
66  if ( file_exists( $arg ) ) {
67  $files[$arg] = file_get_contents( $arg );
68  } else {
69  // use glob to support the Windows shell, which doesn't automatically
70  // expand wildcards
71  $found = false;
72  foreach ( glob( $arg ) as $filename ) {
73  $found = true;
74  $files[$filename] = file_get_contents( $filename );
75  }
76  if ( !$found ) {
77  $this->fatalError( "Fatal error: The file '$arg' does not exist!" );
78  }
79  }
80  }
81 
82  $count = count( $files );
83  $this->output( "Importing $count pages...\n" );
84 
85  if ( $userName === false ) {
86  $user = User::newSystemUser( 'Maintenance script', [ 'steal' => true ] );
87  } else {
88  $user = User::newFromName( $userName );
89  }
90 
91  if ( !$user ) {
92  $this->fatalError( "Invalid username\n" );
93  }
94  if ( $user->isAnon() ) {
95  $user->addToDatabase();
96  }
97 
98  $exit = 0;
99 
100  $successCount = 0;
101  $failCount = 0;
102  $skipCount = 0;
103 
104  $revLookup = MediaWikiServices::getInstance()->getRevisionLookup();
105  foreach ( $files as $file => $text ) {
106  $pageName = $prefix . pathinfo( $file, PATHINFO_FILENAME );
107  $timestamp = $useTimestamp ? wfTimestamp( TS_UNIX, filemtime( $file ) ) : wfTimestampNow();
108 
109  $title = Title::newFromText( $pageName );
110  // Have to check for # manually, since it gets interpreted as a fragment
111  if ( !$title || $title->hasFragment() ) {
112  $this->error( "Invalid title $pageName. Skipping.\n" );
113  $skipCount++;
114  continue;
115  }
116 
117  $exists = $title->exists();
118  $oldRevID = $title->getLatestRevID();
119  $oldRevRecord = $oldRevID ? $revLookup->getRevisionById( $oldRevID ) : null;
120  $actualTitle = $title->getPrefixedText();
121 
122  if ( $exists ) {
123  $touched = wfTimestamp( TS_UNIX, $title->getTouched() );
124  if ( !$overwrite ) {
125  $this->output( "Title $actualTitle already exists. Skipping.\n" );
126  $skipCount++;
127  continue;
128  } elseif ( $useTimestamp && intval( $touched ) >= intval( $timestamp ) ) {
129  $this->output( "File for title $actualTitle has not been modified since the " .
130  "destination page was touched. Skipping.\n" );
131  $skipCount++;
132  continue;
133  }
134  }
135 
136  $rev = new WikiRevision( MediaWikiServices::getInstance()->getMainConfig() );
137  $rev->setText( rtrim( $text ) );
138  $rev->setTitle( $title );
139  $rev->setUserObj( $user );
140  $rev->setComment( $summary );
141  $rev->setTimestamp( $timestamp );
142 
143  if ( $exists &&
144  $overwrite &&
145  $rev->getContent()->equals( $oldRevRecord->getContent( SlotRecord::MAIN ) )
146  ) {
147  $this->output( "File for title $actualTitle contains no changes from the current " .
148  "revision. Skipping.\n" );
149  $skipCount++;
150  continue;
151  }
152 
153  $status = $rev->importOldRevision();
154  $newId = $title->getLatestRevID();
155 
156  if ( $status ) {
157  $action = $exists ? 'updated' : 'created';
158  $this->output( "Successfully $action $actualTitle\n" );
159  $successCount++;
160  } else {
161  $action = $exists ? 'update' : 'create';
162  $this->output( "Failed to $action $actualTitle\n" );
163  $failCount++;
164  $exit = 1;
165  }
166 
167  // Create the RecentChanges entry if necessary
168  if ( $rc && $status ) {
169  if ( $exists ) {
170  if ( is_object( $oldRevRecord ) ) {
171  $oldContent = $oldRevRecord->getContent( SlotRecord::MAIN );
173  $timestamp,
174  $title,
175  $rev->getMinor(),
176  $user,
177  $summary,
178  $oldRevID,
179  $oldRevRecord->getTimestamp(),
180  $bot,
181  '',
182  $oldContent ? $oldContent->getSize() : 0,
183  $rev->getContent()->getSize(),
184  $newId,
185  // the pages don't need to be patrolled
186  1
187  );
188  }
189  } else {
191  $timestamp,
192  $title,
193  $rev->getMinor(),
194  $user,
195  $summary,
196  $bot,
197  '',
198  $rev->getContent()->getSize(),
199  $newId,
200  1
201  );
202  }
203  }
204  }
205 
206  $this->output( "Done! $successCount succeeded, $skipCount skipped.\n" );
207  if ( $exit ) {
208  $this->fatalError( "Import failed with $failCount failed pages.\n", $exit );
209  }
210  }
211 }
212 
213 $maintClass = ImportTextFiles::class;
214 require_once RUN_MAINTENANCE_IF_MAIN;
$maintClass
$maintClass
Definition: importTextFiles.php:213
RUN_MAINTENANCE_IF_MAIN
const RUN_MAINTENANCE_IF_MAIN
Definition: Maintenance.php:38
Title\newFromText
static newFromText( $text, $defaultNamespace=NS_MAIN)
Create a new Title from text, such as what one would find in a link.
Definition: Title.php:329
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:152
Maintenance\fatalError
fatalError( $msg, $exitCode=1)
Output a message and terminate the current script.
Definition: Maintenance.php:480
Maintenance\addDescription
addDescription( $text)
Set the description text.
Definition: Maintenance.php:323
wfTimestamp
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
Definition: GlobalFunctions.php:1811
$file
if(PHP_SAPI !='cli-server') if(!isset( $_SERVER['SCRIPT_FILENAME'])) $file
Item class for a filearchive table row.
Definition: router.php:42
User\newFromName
static newFromName( $name, $validate='valid')
Static factory method for creation from username.
Definition: User.php:533
Maintenance
Abstract maintenance class for quickly writing and churning out maintenance scripts with minimal effo...
Definition: Maintenance.php:53
User\newSystemUser
static newSystemUser( $name, $options=[])
Static factory method for creation of a "system" user from username.
Definition: User.php:750
ImportTextFiles\__construct
__construct()
Default constructor.
Definition: importTextFiles.php:36
Maintenance\addOption
addOption( $name, $description, $required=false, $withArg=false, $shortName=false, $multiOccurrence=false)
Add a parameter to the script.
Definition: Maintenance.php:241
RecentChange\notifyEdit
static notifyEdit( $timestamp, $title, $minor, $user, $comment, $oldId, $lastTimestamp, $bot, $ip='', $oldSize=0, $newSize=0, $newId=0, $patrol=0, $tags=[])
Makes an entry in the database corresponding to an edit.
Definition: RecentChange.php:643
$title
$title
Definition: testCompression.php:38
wfTimestampNow
wfTimestampNow()
Convenience function; returns MediaWiki timestamp for the present time.
Definition: GlobalFunctions.php:1840
ImportTextFiles
Maintenance script which reads in text files and imports their content to a page of the wiki.
Definition: importTextFiles.php:35
Maintenance\getOption
getOption( $name, $default=null)
Get an option, or return the default.
Definition: Maintenance.php:277
WikiRevision
Represents a revision, log entry or upload during the import process.
Definition: WikiRevision.php:37
RecentChange\notifyNew
static notifyNew( $timestamp, $title, $minor, $user, $comment, $bot, $ip='', $size=0, $newId=0, $patrol=0, $tags=[])
Makes an entry in the database corresponding to page creation Note: the title object must be loaded w...
Definition: RecentChange.php:717
Maintenance\addArg
addArg( $arg, $description, $required=true)
Add some args that are needed.
Definition: Maintenance.php:294
ImportTextFiles\execute
execute()
Do the actual work.
Definition: importTextFiles.php:52
Maintenance\error
error( $err, $die=0)
Throw an error to the user.
Definition: Maintenance.php:457
Maintenance\output
output( $out, $channel=null)
Throw some output to the user.
Definition: Maintenance.php:429
Maintenance\hasOption
hasOption( $name)
Checks to see if a particular option exists.
Definition: Maintenance.php:262
Maintenance\getArg
getArg( $argId=0, $default=null)
Get an argument.
Definition: Maintenance.php:347
Revision\SlotRecord
Value object representing a content slot associated with a page revision.
Definition: SlotRecord.php:39