Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
72.73% covered (warning)
72.73%
48 / 66
40.00% covered (danger)
40.00%
2 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
UpdateTable
80.00% covered (warning)
80.00%
48 / 60
40.00% covered (danger)
40.00%
2 / 5
14.35
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
 normaliseStreamPath
85.71% covered (warning)
85.71%
6 / 7
0.00% covered (danger)
0.00%
0 / 1
3.03
 execute
81.82% covered (warning)
81.82%
18 / 22
0.00% covered (danger)
0.00%
0 / 1
4.10
 createImportContext
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
1
 clearTable
61.11% covered (warning)
61.11%
11 / 18
0.00% covered (danger)
0.00%
0 / 1
4.94
1<?php
2
3namespace PropertySuggester\Maintenance;
4
5use MediaWiki\Maintenance\Maintenance;
6use MediaWiki\MediaWikiServices;
7use PropertySuggester\UpdateTable\ImportContext;
8use PropertySuggester\UpdateTable\Importer\BasicImporter;
9use UnexpectedValueException;
10use Wikimedia\Rdbms\IDatabase;
11use Wikimedia\Rdbms\ILBFactory;
12
13$basePath = getenv( 'MW_INSTALL_PATH' ) !== false
14    ? getenv( 'MW_INSTALL_PATH' )
15    : __DIR__ . '/../../..';
16require_once $basePath . '/maintenance/Maintenance.php';
17
18/**
19 * Maintenance script to load property pair occurrence probability table from given csv file
20 *
21 * @author BP2013N2
22 * @license GPL-2.0-or-later
23 */
24class UpdateTable extends Maintenance {
25
26    public function __construct() {
27        parent::__construct();
28
29        $this->addDescription( "Read CSV Dump and refill probability table" );
30        $this->addOption( 'file', 'CSV table to be loaded (relative path)', true, true );
31        $this->setBatchSize( 10000 );
32        $this->requireExtension( 'PropertySuggester' );
33    }
34
35    /**
36     * If passed a filename, find the absolute path and convert to unix format.
37     *
38     * @param string $uriOrFilePath
39     * @return string
40     * @throws \MediaWiki\Maintenance\MaintenanceFatalError
41     */
42    private function normaliseStreamPath( string $uriOrFilePath ): string {
43        if ( str_contains( $uriOrFilePath, '://' ) ) {
44            // Path is a stream - not attempt to normalise / verify
45            return $uriOrFilePath;
46        }
47        $fullPath = realpath( $uriOrFilePath );
48        $fullPath = str_replace( '\\', '/', $fullPath );
49
50        if ( !file_exists( $fullPath ) ) {
51            $this->fatalError( "Cant find $uriOrFilePath \n" );
52        }
53        return $fullPath;
54    }
55
56    /**
57     * loads property pair occurrence probability table from given csv file
58     */
59    public function execute() {
60        if ( substr( $this->getOption( 'file' ), 0, 2 ) === "--" ) {
61            $this->fatalError( "The --file option requires a file as an argument.\n" );
62        }
63        $path = $this->getOption( 'file' );
64        $fullPath = $this->normaliseStreamPath( $path );
65
66        $tableName = 'wbs_propertypairs';
67
68        $lbFactory = MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
69        $lbFactory->waitForReplication();
70
71        $this->clearTable( $lbFactory, $tableName );
72
73        $this->output( "loading new entries from file\n" );
74
75        $importContext = $this->createImportContext(
76            $lbFactory,
77            $tableName,
78            $fullPath,
79            $this->isQuiet()
80        );
81        $importStrategy = new BasicImporter();
82
83        try {
84            $success = $importStrategy->importFromCsvFileToDb( $importContext );
85        } catch ( UnexpectedValueException $e ) {
86            $this->fatalError( "Import failed: " . $e->getMessage() );
87        }
88
89        if ( !$success ) {
90            $this->fatalError( "Failed to run import to db" );
91        }
92        $this->output( "... Done loading\n" );
93    }
94
95    /**
96     * @param ILBFactory $lbFactory
97     * @param string $tableName
98     * @param string $wholePath
99     * @param bool $quiet
100     * @return ImportContext
101     */
102    private function createImportContext( ILBFactory $lbFactory, $tableName, $wholePath, $quiet ) {
103        $importContext = new ImportContext();
104        $importContext->setLbFactory( $lbFactory );
105        $importContext->setTargetTableName( $tableName );
106        $importContext->setCsvFilePath( $wholePath );
107        $importContext->setCsvDelimiter( ',' );
108        $importContext->setBatchSize( $this->mBatchSize );
109        $importContext->setQuiet( $quiet );
110
111        return $importContext;
112    }
113
114    /**
115     * @param ILBFactory $lbFactory
116     * @param string $tableName
117     */
118    private function clearTable( ILBFactory $lbFactory, $tableName ) {
119        global $wgDBtype;
120
121        $lb = $lbFactory->getMainLB();
122        $db = $lb->getMaintenanceConnectionRef( DB_PRIMARY );
123        if ( !$db->tableExists( $tableName, __METHOD__ ) ) {
124            $this->fatalError( "$tableName table does not exist.\n" .
125                "Executing core/maintenance/update.php may help.\n" );
126        }
127        $this->output( "Removing old entries\n" );
128        if ( $wgDBtype === 'sqlite' || $wgDBtype === 'postgres' ) {
129            $db->newDeleteQueryBuilder()
130                ->deleteFrom( $tableName )
131                ->where( IDatabase::ALL_ROWS )
132                ->caller( __METHOD__ )
133                ->execute();
134        } else {
135            do {
136                $db->commit( __METHOD__, 'flush' );
137                $lbFactory->waitForReplication();
138                $this->output( "Deleting a batch\n" );
139                $table = $db->tableName( $tableName );
140                $db->query( "DELETE FROM $table LIMIT $this->mBatchSize", __METHOD__ );
141            } while ( $db->affectedRows() > 0 );
142        }
143    }
144
145}
146
147$maintClass = UpdateTable::class;
148require_once RUN_MAINTENANCE_IF_MAIN;