Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 32
0.00% covered (danger)
0.00%
0 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
TranslatableBundleExporter
0.00% covered (danger)
0.00%
0 / 32
0.00% covered (danger)
0.00%
0 / 4
90
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
2
 export
0.00% covered (danger)
0.00%
0 / 22
0.00% covered (danger)
0.00%
0 / 1
20
 setExportPageCallback
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 exportPages
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
12
1<?php
2declare( strict_types = 1 );
3
4namespace MediaWiki\Extension\Translate\MessageGroupProcessing;
5
6use Closure;
7use DumpStringOutput;
8use MediaWiki\Export\WikiExporterFactory;
9use MediaWiki\Title\Title;
10use WikiExporter;
11use Wikimedia\Rdbms\IConnectionProvider;
12
13/**
14 * Service to export a translatable bundle into XML. Uses WikiExporter from MediaWiki core.
15 * @since 2023.05
16 * @license GPL-2.0-or-later
17 * @author Abijeet Patro
18 */
19class TranslatableBundleExporter {
20    private WikiExporter $wikiExporter;
21    private SubpageListBuilder $subpageListBuilder;
22    private ?Closure $exportPageCallback;
23
24    public function __construct(
25        SubpageListBuilder $subpageListBuilder,
26        WikiExporterFactory $wikiExporterFactory,
27        IConnectionProvider $dbProvider
28    ) {
29        $this->subpageListBuilder = $subpageListBuilder;
30        $this->wikiExporter = $wikiExporterFactory->getWikiExporter(
31            $dbProvider->getReplicaDatabase(),
32            WikiExporter::FULL
33        );
34    }
35
36    public function export( TranslatableBundle $bundle, bool $includeTalkPages, bool $includeSubPages ): string {
37        $classifiedSubpages = $this->subpageListBuilder->getSubpagesPerType( $bundle, $includeTalkPages );
38
39        $sink = new DumpStringOutput();
40        $this->wikiExporter->setOutputSink( $sink );
41        $this->wikiExporter->openStream();
42
43        // Add all the pages to be exported
44        $this->exportPages( [ $bundle->getTitle() ], 'translatable bundle' );
45        $this->exportPages( $classifiedSubpages[ 'translationPages' ], 'translation' );
46        $this->exportPages( $classifiedSubpages[ 'translationUnitPages' ], 'translation unit' );
47
48        // Filter out null values. Null values mean that there is no corresponding talk page
49        $talkPages = $includeTalkPages ? $classifiedSubpages[ 'talkPages' ] : [];
50        $talkPages = array_filter( $talkPages, static function ( $val ) {
51            return $val !== null;
52        } );
53        $this->exportPages( $talkPages, 'talk pages' );
54
55        $this->exportPages(
56            $includeTalkPages ? $classifiedSubpages[ 'translatableTalkPages' ] : [],
57            'translatable talk',
58        );
59        $this->exportPages(
60            $includeSubPages ? $classifiedSubpages[ 'normalSubpages' ] : [],
61            'subpage'
62        );
63
64        $this->wikiExporter->closeStream();
65
66        return (string)$sink;
67    }
68
69    public function setExportPageCallback( callable $callable ) {
70        $this->exportPageCallback = Closure::fromCallable( $callable );
71    }
72
73    /**
74     * @param Title[] $pagesForExport
75     * @param string $pageType
76     */
77    private function exportPages( array $pagesForExport, string $pageType ): void {
78        if ( $this->exportPageCallback ) {
79            call_user_func( $this->exportPageCallback, $pagesForExport, $pageType );
80        }
81
82        foreach ( $pagesForExport as $page ) {
83            $this->wikiExporter->pageByTitle( $page );
84        }
85    }
86}