Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 38
0.00% covered (danger)
0.00%
0 / 8
CRAP
0.00% covered (danger)
0.00%
0 / 1
SqliteInstaller
0.00% covered (danger)
0.00%
0 / 38
0.00% covered (danger)
0.00%
0 / 8
156
0.00% covered (danger)
0.00%
0 / 1
 getName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 isCompiled
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getConnectForm
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getSettingsForm
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 checkPrerequisites
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
6
 getGlobalDefaults
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
6
 openConnection
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
12
 getLocalSettings
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3/**
4 * Sqlite-specific installer.
5 *
6 * @license GPL-2.0-or-later
7 * @file
8 * @ingroup Installer
9 */
10
11namespace MediaWiki\Installer;
12
13use MediaWiki\MediaWikiServices;
14use MediaWiki\Status\Status;
15use Wikimedia\Rdbms\DatabaseSqlite;
16use Wikimedia\Rdbms\DBConnectionError;
17
18/**
19 * Class for setting up the MediaWiki database using SQLLite.
20 *
21 * @ingroup Installer
22 * @since 1.17
23 */
24class SqliteInstaller extends DatabaseInstaller {
25
26    /** @inheritDoc */
27    public static $minimumVersion = '3.31.0';
28    /** @inheritDoc */
29    protected static $notMinimumVersionMessage = 'config-outdated-sqlite';
30
31    /**
32     * @var DatabaseSqlite
33     */
34    public $db;
35
36    /** @inheritDoc */
37    protected $globalNames = [
38        'wgDBname',
39        'wgSQLiteDataDir',
40    ];
41
42    /** @inheritDoc */
43    public function getName() {
44        return 'sqlite';
45    }
46
47    /** @inheritDoc */
48    public function isCompiled() {
49        return self::checkExtension( 'pdo_sqlite' );
50    }
51
52    public function getConnectForm( WebInstaller $webInstaller ): DatabaseConnectForm {
53        return new SqliteConnectForm( $webInstaller, $this );
54    }
55
56    public function getSettingsForm( WebInstaller $webInstaller ): DatabaseSettingsForm {
57        return new DatabaseSettingsForm( $webInstaller, $this );
58    }
59
60    /**
61     * @return Status
62     */
63    public function checkPrerequisites() {
64        // Bail out if SQLite is too old
65        $db = DatabaseSqlite::newStandaloneInstance( ':memory:' );
66        $result = static::meetsMinimumRequirement( $db );
67        // Check for FTS3 full-text search module
68        if ( DatabaseSqlite::getFulltextSearchModule() != 'FTS3' ) {
69            $result->warning( 'config-no-fts3' );
70        }
71
72        return $result;
73    }
74
75    /** @inheritDoc */
76    public function getGlobalDefaults() {
77        global $IP;
78        $defaults = parent::getGlobalDefaults();
79        if ( !empty( $_SERVER['DOCUMENT_ROOT'] ) ) {
80            $path = dirname( $_SERVER['DOCUMENT_ROOT'] );
81        } else {
82            // We use $IP when unable to get $_SERVER['DOCUMENT_ROOT']
83            $path = $IP;
84        }
85        $defaults['wgSQLiteDataDir'] = str_replace(
86            [ '/', '\\' ],
87            DIRECTORY_SEPARATOR,
88            $path . '/data'
89        );
90        return $defaults;
91    }
92
93    /**
94     * @param string $type
95     * @return ConnectionStatus
96     */
97    public function openConnection( string $type ) {
98        $status = new ConnectionStatus;
99        $dir = $this->getVar( 'wgSQLiteDataDir' );
100        $dbName = $this->getVar( 'wgDBname' );
101
102        // Don't implicitly create the file
103        $file = DatabaseSqlite::generateFileName( $dir, $dbName );
104        if ( !file_exists( $file ) ) {
105            $status->fatal( 'config-sqlite-connection-error',
106                'file does not exist' );
107            return $status;
108        }
109
110        try {
111            $db = MediaWikiServices::getInstance()->getDatabaseFactory()->create(
112                'sqlite', [ 'dbname' => $dbName, 'dbDirectory' => $dir ]
113            );
114            $status->setDB( $db );
115        } catch ( DBConnectionError $e ) {
116            $status->fatal( 'config-sqlite-connection-error', $e->getMessage() );
117        }
118
119        return $status;
120    }
121
122    /**
123     * @return string
124     */
125    public function getLocalSettings() {
126        $dir = LocalSettingsGenerator::escapePhpString( $this->getVar( 'wgSQLiteDataDir' ) );
127        // These tables have frequent writes and are thus split off from the main one.
128        // Since the code using these tables only uses transactions for writes, then set
129        // them to using BEGIN IMMEDIATE. This avoids frequent lock errors on the first write action.
130        return "# SQLite-specific settings
131\$wgSQLiteDataDir = \"{$dir}\";
132\$wgObjectCaches[CACHE_DB] = [
133    'class' => SqlBagOStuff::class,
134    'loggroup' => 'SQLBagOStuff',
135    'server' => [
136        'type' => 'sqlite',
137        'dbname' => 'wikicache',
138        'tablePrefix' => '',
139        'variables' => [ 'synchronous' => 'NORMAL' ],
140        'dbDirectory' => \$wgSQLiteDataDir,
141        'trxMode' => 'IMMEDIATE',
142        'flags' => 0
143    ]
144];
145\$wgLocalisationCacheConf['storeServer'] = [
146    'type' => 'sqlite',
147    'dbname' => \"{\$wgDBname}_l10n_cache\",
148    'tablePrefix' => '',
149    'variables' => [ 'synchronous' => 'NORMAL' ],
150    'dbDirectory' => \$wgSQLiteDataDir,
151    'trxMode' => 'IMMEDIATE',
152    'flags' => 0
153];
154\$wgJobTypeConf['default'] = [
155    'class' => 'JobQueueDB',
156    'claimTTL' => 3600,
157    'server' => [
158        'type' => 'sqlite',
159        'dbname' => \"{\$wgDBname}_jobqueue\",
160        'tablePrefix' => '',
161        'variables' => [ 'synchronous' => 'NORMAL' ],
162        'dbDirectory' => \$wgSQLiteDataDir,
163        'trxMode' => 'IMMEDIATE',
164        'flags' => 0
165    ]
166];
167";
168    }
169}