src/MessageGroupProcessing/TranslatableBundleExporter.php
<?php
declare( strict_types = 1 );
namespace MediaWiki\Extension\Translate\MessageGroupProcessing;
use Closure;
use DumpStringOutput;
use MediaWiki\Export\WikiExporterFactory;
use MediaWiki\Title\Title;
use WikiExporter;
use Wikimedia\Rdbms\IConnectionProvider;
/**
* Service to export a translatable bundle into XML. Uses WikiExporter from MediaWiki core.
* @since 2023.05
* @license GPL-2.0-or-later
* @author Abijeet Patro
*/
class TranslatableBundleExporter {
private WikiExporter $wikiExporter;
private SubpageListBuilder $subpageListBuilder;
private ?Closure $exportPageCallback;
public function __construct(
SubpageListBuilder $subpageListBuilder,
WikiExporterFactory $wikiExporterFactory,
IConnectionProvider $dbProvider
) {
$this->subpageListBuilder = $subpageListBuilder;
$this->wikiExporter = $wikiExporterFactory->getWikiExporter(
$dbProvider->getReplicaDatabase(),
WikiExporter::FULL
);
}
public function export( TranslatableBundle $bundle, bool $includeTalkPages, bool $includeSubPages ): string {
$classifiedSubpages = $this->subpageListBuilder->getSubpagesPerType( $bundle, $includeTalkPages );
$sink = new DumpStringOutput();
$this->wikiExporter->setOutputSink( $sink );
$this->wikiExporter->openStream();
// Add all the pages to be exported
$this->exportPages( [ $bundle->getTitle() ], 'translatable bundle' );
$this->exportPages( $classifiedSubpages[ 'translationPages' ], 'translation' );
$this->exportPages( $classifiedSubpages[ 'translationUnitPages' ], 'translation unit' );
// Filter out null values. Null values mean that there is no corresponding talk page
$talkPages = $includeTalkPages ? $classifiedSubpages[ 'talkPages' ] : [];
$talkPages = array_filter( $talkPages, static function ( $val ) {
return $val !== null;
} );
$this->exportPages( $talkPages, 'talk pages' );
$this->exportPages(
$includeTalkPages ? $classifiedSubpages[ 'translatableTalkPages' ] : [],
'translatable talk',
);
$this->exportPages(
$includeSubPages ? $classifiedSubpages[ 'normalSubpages' ] : [],
'subpage'
);
$this->wikiExporter->closeStream();
return (string)$sink;
}
public function setExportPageCallback( callable $callable ) {
$this->exportPageCallback = Closure::fromCallable( $callable );
}
/**
* @param Title[] $pagesForExport
* @param string $pageType
*/
private function exportPages( array $pagesForExport, string $pageType ): void {
if ( $this->exportPageCallback ) {
call_user_func( $this->exportPageCallback, $pagesForExport, $pageType );
}
foreach ( $pagesForExport as $page ) {
$this->wikiExporter->pageByTitle( $page );
}
}
}