25use Wikimedia\AtEase\AtEase;
64 $db = DatabaseSqlite::newStandaloneInstance(
':memory:' );
65 $result = static::meetsMinimumRequirement(
$db );
67 if ( DatabaseSqlite::getFulltextSearchModule() !=
'FTS3' ) {
68 $result->warning(
'config-no-fts3' );
76 $defaults = parent::getGlobalDefaults();
77 if ( !empty( $_SERVER[
'DOCUMENT_ROOT'] ) ) {
78 $path = dirname( $_SERVER[
'DOCUMENT_ROOT'] );
83 $defaults[
'wgSQLiteDataDir'] = str_replace(
94 'config-sqlite-dir', [],
95 $this->parent->getHelpBox(
'config-sqlite-dir-help' )
101 $this->parent->getHelpBox(
'config-sqlite-name-help' )
112 private static function realpath(
$path ) {
113 $result = realpath(
$path );
127 # Try realpath() if the directory already exists
128 $dir = self::realpath( $this->
getVar(
'wgSQLiteDataDir' ) );
129 $result = self::checkDataDir( $dir );
130 if ( $result->isOK() ) {
131 # Try expanding again in case we've just created it
132 $dir = self::realpath( $dir );
133 $this->
setVar(
'wgSQLiteDataDir', $dir );
135 # Table prefix is not used on SQLite, keep it empty
136 $this->
setVar(
'wgDBprefix',
'' );
146 private static function checkDataDir( $dir ):
Status {
147 if ( is_dir( $dir ) ) {
148 if ( !is_readable( $dir ) ) {
149 return Status::newFatal(
'config-sqlite-dir-unwritable', $dir );
153 if ( !is_writable( dirname( $dir ) ) ) {
155 if ( $webserverGroup !==
null ) {
157 'config-sqlite-parent-unwritable-group',
158 $dir, dirname( $dir ), basename( $dir ),
163 'config-sqlite-parent-unwritable-nogroup',
164 $dir, dirname( $dir ), basename( $dir )
176 private static function createDataDir( $dir ):
Status {
177 if ( !is_dir( $dir ) ) {
178 AtEase::suppressWarnings();
180 AtEase::restoreWarnings();
185 # Put a .htaccess file in case the user didn't take our advice
186 file_put_contents(
"$dir/.htaccess",
"Require all denied\n" );
194 $status = Status::newGood();
195 $dir = $this->getVar(
'wgSQLiteDataDir' );
196 $dbName = $this->getVar(
'wgDBname' );
198 $db = MediaWikiServices::getInstance()->getDatabaseFactory()->create(
199 'sqlite', [
'dbname' => $dbName,
'dbDirectory' => $dir ]
201 $status->value = $db;
203 $status->fatal(
'config-sqlite-connection-error', $e->getMessage() );
213 $dir = $this->getVar(
'wgSQLiteDataDir' );
214 $dbName = $this->getVar(
'wgDBname' );
216 if ( !file_exists( DatabaseSqlite::generateFileName( $dir, $dbName ) ) ) {
221 return parent::needsUpgrade();
228 $dir = $this->getVar(
'wgSQLiteDataDir' );
230 # Double check (Only available in web installation). We checked this before but maybe someone
231 # deleted the data dir between then and now
232 $dir_status = self::checkDataDir( $dir );
233 if ( $dir_status->isGood() ) {
234 $res = self::createDataDir( $dir );
235 if ( !
$res->isGood() ) {
242 $db = $this->getVar(
'wgDBname' );
244 # Make the main and cache stub DB files
245 $status = Status::newGood();
246 $status->merge( $this->makeStubDBFile( $dir, $db ) );
247 $status->merge( $this->makeStubDBFile( $dir,
"wikicache" ) );
248 $status->merge( $this->makeStubDBFile( $dir,
"{$db}_l10n_cache" ) );
249 $status->merge( $this->makeStubDBFile( $dir,
"{$db}_jobqueue" ) );
250 if ( !$status->isOK() ) {
254 # Nuke the unused settings for clarity
255 $this->setVar(
'wgDBserver',
'' );
256 $this->setVar(
'wgDBuser',
'' );
257 $this->setVar(
'wgDBpassword',
'' );
258 $this->setupSchemaVars();
260 # Create the l10n cache DB
263 'sqlite', [
'dbname' =>
"{$db}_l10n_cache",
'dbDirectory' => $dir ] );
264 # @todo: don't duplicate l10n_cache definition, though it's very simple
267 CREATE TABLE l10n_cache (
268 lc_lang BLOB NOT NULL,
269 lc_key TEXT NOT NULL,
270 lc_value BLOB NOT NULL,
271 PRIMARY KEY (lc_lang, lc_key)
274 $conn->query( $sql, __METHOD__ );
275 $conn->query(
"PRAGMA journal_mode=WAL", __METHOD__ );
276 $conn->close( __METHOD__ );
278 return Status::newFatal(
'config-sqlite-connection-error', $e->getMessage() );
281 # Create the job queue DB
284 'sqlite', [
'dbname' =>
"{$db}_jobqueue",
'dbDirectory' => $dir ] );
285 # @todo: don't duplicate job definition, though it's very static
289 job_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
290 job_cmd BLOB NOT NULL
default '',
291 job_namespace INTEGER NOT NULL,
292 job_title TEXT NOT NULL,
293 job_timestamp BLOB NULL
default NULL,
294 job_params BLOB NOT NULL,
295 job_random integer NOT NULL
default 0,
296 job_attempts integer NOT NULL
default 0,
297 job_token BLOB NOT NULL
default '',
298 job_token_timestamp BLOB NULL
default NULL,
299 job_sha1 BLOB NOT NULL
default ''
301 CREATE INDEX job_sha1 ON job (job_sha1);
302 CREATE INDEX job_cmd_token ON job (job_cmd,job_token,job_random);
303 CREATE INDEX job_cmd_token_id ON job (job_cmd,job_token,job_id);
304 CREATE INDEX job_cmd ON job (job_cmd, job_namespace, job_title, job_params);
305 CREATE INDEX job_timestamp ON job (job_timestamp);
307 $conn->query( $sql, __METHOD__ );
308 $conn->query(
"PRAGMA journal_mode=WAL", __METHOD__ );
309 $conn->close( __METHOD__ );
311 return Status::newFatal(
'config-sqlite-connection-error', $e->getMessage() );
315 return $this->getConnection();
324 $file = DatabaseSqlite::generateFileName( $dir, $db );
326 if ( file_exists(
$file ) ) {
327 if ( !is_writable(
$file ) ) {
328 return Status::newFatal(
'config-sqlite-readonly',
$file );
330 return Status::newGood();
333 $oldMask = umask( 0177 );
334 if ( file_put_contents(
$file,
'' ) ===
false ) {
336 return Status::newFatal(
'config-sqlite-cant-create-db',
$file );
340 return Status::newGood();
347 $status = parent::createTables();
348 if ( $status->isGood() ) {
349 $status = parent::createManualTables();
352 return $this->setupSearchIndex( $status );
357 return Status::newGood();
367 $module = DatabaseSqlite::getFulltextSearchModule();
368 $searchIndexSql = (string)$this->db->selectField(
369 $this->db->addIdentifierQuotes(
'sqlite_master' ),
371 [
'tbl_name' => $this->db->tableName(
'searchindex',
'raw' ) ],
374 $fts3tTable = ( stristr( $searchIndexSql,
'fts' ) !== false );
376 if ( $fts3tTable && !$module ) {
377 $status->warning(
'config-sqlite-fts3-downgrade' );
378 $this->db->sourceFile(
"$IP/maintenance/sqlite/archives/searchindex-no-fts.sql" );
379 } elseif ( !$fts3tTable && $module ==
'FTS3' ) {
380 $this->db->sourceFile(
"$IP/maintenance/sqlite/archives/searchindex-fts3.sql" );
390 $dir = LocalSettingsGenerator::escapePhpString( $this->getVar(
'wgSQLiteDataDir' ) );
394 return "# SQLite-specific settings
395\$wgSQLiteDataDir = \"{$dir}\";
396\$wgObjectCaches[CACHE_DB] = [
397 'class' => SqlBagOStuff::class,
398 'loggroup' => 'SQLBagOStuff',
401 'dbname' => 'wikicache',
403 'variables' => [ 'synchronous' => 'NORMAL' ],
404 'dbDirectory' => \$wgSQLiteDataDir,
405 'trxMode' => 'IMMEDIATE',
409\$wgObjectCaches['db-replicated'] = [
410 'factory' => 'Wikimedia\ObjectFactory\ObjectFactory::getObjectFromSpec',
411 'args' => [ [ 'factory' => 'ObjectCache::getInstance', 'args' => [ CACHE_DB ] ] ]
413\$wgLocalisationCacheConf['storeServer'] = [
415 'dbname' => \"{\$wgDBname}_l10n_cache\",
417 'variables' => [ 'synchronous' => 'NORMAL' ],
418 'dbDirectory' => \$wgSQLiteDataDir,
419 'trxMode' => 'IMMEDIATE',
422\$wgJobTypeConf['default'] = [
423 'class' => 'JobQueueDB',
427 'dbname' => \"{\$wgDBname}_jobqueue\",
429 'variables' => [ 'synchronous' => 'NORMAL' ],
430 'dbDirectory' => \$wgSQLiteDataDir,
431 'trxMode' => 'IMMEDIATE',
435\$wgResourceLoaderUseObjectCacheForDeps = true;";
wfMkdirParents( $dir, $mode=null, $caller=null)
Make directory, and make all parent directories if they don't exist.
if(!defined( 'MEDIAWIKI')) if(ini_get('mbstring.func_overload')) if(!defined( 'MW_ENTRY_POINT')) global $IP
Environment checks.
if(!defined('MW_SETUP_CALLBACK'))
The persistent session ID (if any) loaded at startup.
Base class for DBMS-specific installation helper classes.
static checkExtension( $name)
Convenience function.
setVarsFromRequest( $varNames)
Convenience function to set variables based on form data.
getVar( $var, $default=null)
Get a variable, taking local defaults into account.
getTextBox( $var, $label, $attribs=[], $helpData="")
Get a labelled text box to configure a local variable.
setVar( $name, $value)
Convenience alias for $this->parent->setVar()
static maybeGetWebserverPrimaryGroup()
On POSIX systems return the primary group of the webserver we're running under.
Class for setting up the MediaWiki database using SQLLite.
setupSearchIndex(&$status)
getGlobalDefaults()
Get a name=>value map of MW configuration globals for the default values.
makeStubDBFile( $dir, $db)
getName()
Return the internal name, e.g.
getConnectForm()
Get HTML for a web form that configures this database.
static $notMinimumVersionMessage
createManualTables()
Create database tables from scratch.
static newFatal( $message,... $parameters)
Factory function for fatal errors.
static newGood( $value=null)
Factory function for good results.
Generic operation result class Has warning/error list, boolean status and arbitrary value.
if(PHP_SAPI !='cli-server') if(!isset( $_SERVER['SCRIPT_FILENAME'])) $file
Item class for a filearchive table row.