setHeaders();
// Security and validity checks
if ( !$this->userCanExecute( $this->getUser() ) ) {
$this->displayRestrictionError();
return;
}
if ( !$this->getRequest()->wasPosted() ) {
$this->outputForm();
return;
}
if ( !$this->getUser()->matchEditToken( $this->getRequest()->getVal( 'token' ) ) ) {
$this->getOutput()->addWikiMsg( 'session_fail_preview' );
$this->outputForm();
return;
}
if ( $this->getRequest()->getCheck( 'process' ) ) {
$data = $this->getCachedData();
if ( !$data ) {
$this->getOutput()->addWikiMsg( 'session_fail_preview' );
$this->outputForm();
return;
}
} else {
/**
* Proceed to loading and parsing if possible
* @todo: use a Status object instead?
*/
$file = null;
$msg = $this->loadFile( $file );
if ( $this->checkError( $msg ) ) {
return;
}
$msg = $this->parseFile( $file );
if ( $this->checkError( $msg ) ) {
return;
}
$data = $msg[1];
$this->setCachedData( $data );
}
$messages = $data['MESSAGES'];
$group = $data['METADATA']['group'];
$code = $data['METADATA']['code'];
if ( !MessageGroups::exists( $group ) ) {
$errorWrap = "
\n$1\n
";
$this->getOutput()->wrapWikiMsg( $errorWrap, 'translate-import-err-stale-group' );
return;
}
$importer = new MessageWebImporter( $this->getPageTitle(), $group, $code );
$alldone = $importer->execute( $messages );
if ( $alldone ) {
$this->deleteCachedData();
}
}
/**
* Checks for error state from the return value of loadFile and parseFile
* functions. Prints the error and the form and returns true if there is an
* error. Returns false and does nothing if there is no error.
* @param array $msg
* @return bool
*/
protected function checkError( $msg ) {
// Give grep a chance to find the usages:
// translate-import-err-dl-failed, translate-import-err-ul-failed,
// translate-import-err-invalid-title, translate-import-err-no-such-file,
// translate-import-err-stale-group, translate-import-err-no-headers,
// translate-import-err-warnings
if ( $msg[0] !== 'ok' ) {
$errorWrap = "\n$1\n
";
$msg[0] = 'translate-import-err-' . $msg[0];
$this->getOutput()->wrapWikiMsg( $errorWrap, $msg );
$this->outputForm();
return true;
}
return false;
}
/**
* Constructs and outputs file input form with supported methods.
*/
protected function outputForm() {
$this->getOutput()->addModules( 'ext.translate.special.importtranslations' );
$this->getOutput()->addHelpLink( 'Help:Extension:Translate/Off-line_translation' );
/**
* Ugly but necessary form building ahead, ohoy
*/
$this->getOutput()->addHTML(
Xml::openElement( 'form', [
'action' => $this->getPageTitle()->getLocalURL(),
'method' => 'post',
'enctype' => 'multipart/form-data',
'id' => 'mw-translate-import',
] ) .
Html::hidden( 'token', $this->getUser()->getEditToken() ) .
Html::hidden( 'title', $this->getPageTitle()->getPrefixedText() ) .
Xml::inputLabel(
$this->msg( 'translate-import-from-local' )->text(),
'upload-local', // name
'mw-translate-up-local-input', // id
50, // size
$this->getRequest()->getText( 'upload-local' ),
[ 'type' => 'file' ]
) .
Xml::submitButton( $this->msg( 'translate-import-load' )->text() ) .
Xml::closeElement( 'form' )
);
}
/**
* Try to get the file data from any of the supported methods.
* @param string &$filedata
* @return array
*/
protected function loadFile( &$filedata ) {
$filename = $this->getRequest()->getFileTempname( 'upload-local' );
if ( !is_uploaded_file( $filename ) ) {
return [ 'ul-failed' ];
}
$filedata = file_get_contents( $filename );
return [ 'ok' ];
}
/**
* Try parsing file.
* @param string $data
* @return array
*/
protected function parseFile( $data ) {
/** Construct a dummy group for us...
* @todo Time to rethink the interface again?
* @var FileBasedMessageGroup $group
*/
$group = MessageGroupBase::factory( [
'FILES' => [
'class' => 'GettextFFS',
'CtxtAsKey' => true,
],
'BASIC' => [
'class' => 'FileBasedMessageGroup',
'namespace' => -1,
]
] );
$ffs = new GettextFFS( $group );
$data = $ffs->readFromVariable( $data );
/**
* Special data added by GettextFFS
*/
$metadata = $data['METADATA'];
/**
* This should catch everything that is not a gettext file exported from us
*/
if ( !isset( $metadata['code'] ) || !isset( $metadata['group'] ) ) {
return [ 'no-headers' ];
}
/**
* And check for stupid editors that drop msgctxt which
* unfortunately breaks submission.
*/
if ( isset( $metadata['warnings'] ) ) {
return [ 'warnings', $this->getLanguage()->commaList( $metadata['warnings'] ) ];
}
return [ 'ok', $data ];
}
protected function setCachedData( $data ) {
$key = wfMemcKey( 'translate', 'webimport', $this->getUser()->getId() );
wfGetCache( CACHE_DB )->set( $key, $data, 60 * 30 );
}
protected function getCachedData() {
$key = wfMemcKey( 'translate', 'webimport', $this->getUser()->getId() );
return wfGetCache( CACHE_DB )->get( $key );
}
protected function deleteCachedData() {
$key = wfMemcKey( 'translate', 'webimport', $this->getUser()->getId() );
return wfGetCache( CACHE_DB )->delete( $key );
}
}