Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 62
0.00% covered (danger)
0.00%
0 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
ConvertAllLqtPages
0.00% covered (danger)
0.00%
0 / 56
0.00% covered (danger)
0.00%
0 / 3
72
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
2
 execute
0.00% covered (danger)
0.00%
0 / 36
0.00% covered (danger)
0.00%
0 / 1
20
 buildIterator
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
12
1<?php
2
3namespace Flow\Maintenance;
4
5use AppendIterator;
6use Flow\Container;
7use Flow\Import\Converter;
8use Flow\Import\LiquidThreadsApi\ConversionStrategy;
9use Flow\Import\LiquidThreadsApi\LocalApiBackend;
10use Flow\Import\SourceStore\FileImportSourceStore;
11use Flow\Import\SourceStore\FlowRevisionsDb;
12use Flow\OccupationController;
13use Flow\Utils\NamespaceIterator;
14use Flow\Utils\PagesWithPropertyIterator;
15use Maintenance;
16use MediaWiki\MediaWikiServices;
17use Psr\Log\AbstractLogger;
18use Psr\Log\LogLevel;
19use Wikimedia\Rdbms\IReadableDatabase;
20
21$IP = getenv( 'MW_INSTALL_PATH' );
22if ( $IP === false ) {
23    $IP = __DIR__ . '/../../..';
24}
25
26require_once "$IP/maintenance/Maintenance.php";
27
28/**
29 * Converts all LiquidThreads pages on a wiki to Flow. When using the logfile
30 * option this process is idempotent.It may be run many times and will only import
31 * one copy of each item.
32 */
33class ConvertAllLqtPages extends Maintenance {
34    public function __construct() {
35        parent::__construct();
36        $this->addDescription( "Converts LiquidThreads data to Flow data" );
37        $this->addOption( 'logfile', 'File to read and store associations between imported items ' .
38            'and their sources. This is required for the import to be idempotent.', false, true );
39        $this->addOption( 'force-recovery-conversion', 'If a previous logfile was lost, this ' .
40            'option can be set to attempt to map threads to topics that have already been ' .
41            'imported to prevent doubles.' );
42        $this->addOption( 'debug', 'Include debug information with progress report' );
43        $this->requireExtension( 'Flow' );
44    }
45
46    public function execute() {
47        $logfile = $this->getOption( 'logfile' );
48        if ( $logfile ) {
49            $sourceStore = new FileImportSourceStore( $logfile );
50        } elseif ( $this->getOption( 'force-recovery-conversion' ) ) {
51            // fallback: if we don't have a sourcestore to go on, at least look
52            // at DB to figure out what's already imported...
53            $dbr = Container::get( 'db.factory' )->getDB( DB_REPLICA );
54            $sourceStore = new FlowRevisionsDb( $dbr );
55        } else {
56            $this->error( 'Param logfile or force-recovery-conversion required!' );
57            $this->maybeHelp( true );
58            die( 1 );
59        }
60
61        $logger = new MaintenanceDebugLogger( $this );
62        if ( $this->getOption( 'debug' ) ) {
63            $logger->setMaximumLevel( LogLevel::DEBUG );
64        } else {
65            $logger->setMaximumLevel( LogLevel::INFO );
66        }
67
68        $importer = Container::get( 'importer' );
69        /** @var OccupationController $occupationController */
70        $occupationController = MediaWikiServices::getInstance()->getService( 'FlowTalkpageManager' );
71        $talkpageManagerUser = $occupationController->getTalkpageManager();
72
73        $dbw = $this->getPrimaryDB();
74        $strategy = new ConversionStrategy(
75            $dbw,
76            $sourceStore,
77            new LocalApiBackend( $talkpageManagerUser ),
78            Container::get( 'url_generator' ),
79            $talkpageManagerUser,
80            Container::get( 'controller.notification' )
81        );
82
83        $converter = new Converter(
84            $dbw,
85            $importer,
86            $logger,
87            $talkpageManagerUser,
88            $strategy
89        );
90
91        $titles = $this->buildIterator( $logger, $dbw );
92
93        $logger->info( "Starting full wiki LQT conversion of all LiquidThreads pages" );
94        $converter->convertAll( $titles );
95        $logger->info( "Finished conversion" );
96    }
97
98    /**
99     * @param AbstractLogger $logger
100     * @param IReadableDatabase $db
101     *
102     * @return AppendIterator
103     */
104    private function buildIterator( $logger, $db ) {
105        global $wgLqtTalkPages;
106
107        $iterator = new AppendIterator();
108
109        $logger->info( "Considering for conversion: pages with the 'use-liquid-threads' property" );
110        $withProperty = new PagesWithPropertyIterator( $db, 'use-liquid-threads' );
111        $iterator->append( $withProperty->getIterator() );
112
113        if ( $wgLqtTalkPages ) {
114            foreach ( $this->getServiceContainer()->getNamespaceInfo()->getTalkNamespaces() as $ns ) {
115                $logger->info( "Considering for conversion: pages in namespace $ns" );
116                $it = new NamespaceIterator( $db, $ns );
117                $iterator->append( $it->getIterator() );
118            }
119        }
120
121        return $iterator;
122    }
123}
124
125$maintClass = ConvertAllLqtPages::class;
126require_once RUN_MAINTENANCE_IF_MAIN;