MediaWiki  master
ImportStreamSource.php
Go to the documentation of this file.
1 <?php
29 use Wikimedia\AtEase\AtEase;
30 
35 class ImportStreamSource implements ImportSource {
37  private $mHandle;
38 
42  public function __construct( $handle ) {
43  $this->mHandle = $handle;
44  }
45 
49  public function atEnd() {
50  return feof( $this->mHandle );
51  }
52 
56  public function readChunk() {
57  return fread( $this->mHandle, 32768 );
58  }
59 
63  public function isSeekable() {
64  return stream_get_meta_data( $this->mHandle )['seekable'] ?? false;
65  }
66 
71  public function seek( int $offset ) {
72  return fseek( $this->mHandle, $offset );
73  }
74 
79  public static function newFromFile( $filename ) {
80  AtEase::suppressWarnings();
81  $file = fopen( $filename, 'rt' );
82  AtEase::restoreWarnings();
83  if ( !$file ) {
84  return Status::newFatal( "importcantopen" );
85  }
86  return Status::newGood( new ImportStreamSource( $file ) );
87  }
88 
93  public static function newFromUpload( $fieldname = "xmlimport" ) {
94  // phpcs:ignore MediaWiki.Usage.SuperGlobalsUsage.SuperGlobals
95  $upload =& $_FILES[$fieldname];
96 
97  if ( $upload === null || !$upload['name'] ) {
98  return Status::newFatal( 'importnofile' );
99  }
100  if ( !empty( $upload['error'] ) ) {
101  switch ( $upload['error'] ) {
102  case UPLOAD_ERR_INI_SIZE:
103  // The uploaded file exceeds the upload_max_filesize directive in php.ini.
104  return Status::newFatal( 'importuploaderrorsize' );
105  case UPLOAD_ERR_FORM_SIZE:
106  // The uploaded file exceeds the MAX_FILE_SIZE directive that
107  // was specified in the HTML form.
108  // FIXME This is probably never used since that directive was removed in 8e91c520?
109  return Status::newFatal( 'importuploaderrorsize' );
110  case UPLOAD_ERR_PARTIAL:
111  // The uploaded file was only partially uploaded
112  return Status::newFatal( 'importuploaderrorpartial' );
113  case UPLOAD_ERR_NO_TMP_DIR:
114  // Missing a temporary folder.
115  return Status::newFatal( 'importuploaderrortemp' );
116  // Other error codes get the generic 'importnofile' error message below
117  }
118 
119  }
120  $fname = $upload['tmp_name'];
121  if ( is_uploaded_file( $fname ) ) {
122  return self::newFromFile( $fname );
123  } else {
124  return Status::newFatal( 'importnofile' );
125  }
126  }
127 
133  public static function newFromURL( $url, $method = 'GET' ) {
134  $httpImportTimeout = MediaWikiServices::getInstance()->getMainConfig()->get(
135  MainConfigNames::HTTPImportTimeout );
136  wfDebug( __METHOD__ . ": opening $url" );
137  # Use the standard HTTP fetch function; it times out
138  # quicker and sorts out user-agent problems which might
139  # otherwise prevent importing from large sites, such
140  # as the Wikimedia cluster, etc.
141  $data = MediaWikiServices::getInstance()->getHttpRequestFactory()->request(
142  $method,
143  $url,
144  [
145  'followRedirects' => true,
146  'timeout' => $httpImportTimeout
147  ],
148  __METHOD__
149  );
150  if ( $data !== null ) {
151  $file = tmpfile();
152  fwrite( $file, $data );
153  fflush( $file );
154  fseek( $file, 0 );
155  return Status::newGood( new ImportStreamSource( $file ) );
156  } else {
157  return Status::newFatal( 'importcantopen' );
158  }
159  }
160 
169  public static function newFromInterwiki( $interwiki, $page, $history = false,
170  $templates = false, $pageLinkDepth = 0
171  ) {
172  if ( $page == '' ) {
173  return Status::newFatal( 'import-noarticle' );
174  }
175 
176  # Look up the first interwiki prefix, and let the foreign site handle
177  # subsequent interwiki prefixes
178  $firstIwPrefix = strtok( $interwiki, ':' );
179  $interwikiLookup = MediaWikiServices::getInstance()->getInterwikiLookup();
180  $firstIw = $interwikiLookup->fetch( $firstIwPrefix );
181  if ( !$firstIw ) {
182  return Status::newFatal( 'importbadinterwiki' );
183  }
184 
185  $additionalIwPrefixes = strtok( '' );
186  if ( $additionalIwPrefixes ) {
187  $additionalIwPrefixes .= ':';
188  }
189  # Have to do a DB-key replacement ourselves; otherwise spaces get
190  # URL-encoded to +, which is wrong in this case. Similar to logic in
191  # Title::getLocalURL
192  $link = $firstIw->getURL( strtr( "{$additionalIwPrefixes}Special:Export/$page",
193  ' ', '_' ) );
194 
195  $params = [];
196  if ( $history ) {
197  $params['history'] = 1;
198  }
199  if ( $templates ) {
200  $params['templates'] = 1;
201  }
202  if ( $pageLinkDepth ) {
203  $params['pagelink-depth'] = $pageLinkDepth;
204  }
205 
206  $url = wfAppendQuery( $link, $params );
207  # For interwikis, use POST to avoid redirects.
208  return self::newFromURL( $url, "POST" );
209  }
210 }
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
wfAppendQuery( $url, $query)
Append a query string to an existing URL, which may or may not already have query string parameters a...
Imports a XML dump from a file (either from file upload, files on disk, or HTTP)
static newFromInterwiki( $interwiki, $page, $history=false, $templates=false, $pageLinkDepth=0)
static newFromFile( $filename)
static newFromUpload( $fieldname="xmlimport")
static newFromURL( $url, $method='GET')
A class containing constants representing the names of configuration variables.
Service locator for MediaWiki core services.
static newFatal( $message,... $parameters)
Factory function for fatal errors.
Definition: StatusValue.php:73
static newGood( $value=null)
Factory function for good results.
Definition: StatusValue.php:85
Source interface for XML import.
if(PHP_SAPI !='cli-server') if(!isset( $_SERVER['SCRIPT_FILENAME'])) $file
Item class for a filearchive table row.
Definition: router.php:42