MediaWiki
REL1_22
|
00001 <?php 00030 class SqliteInstaller extends DatabaseInstaller { 00031 const MINIMUM_VERSION = '3.3.7'; 00032 00036 public $db; 00037 00038 protected $globalNames = array( 00039 'wgDBname', 00040 'wgSQLiteDataDir', 00041 ); 00042 00043 public function getName() { 00044 return 'sqlite'; 00045 } 00046 00047 public function isCompiled() { 00048 return self::checkExtension( 'pdo_sqlite' ); 00049 } 00050 00055 public function checkPrerequisites() { 00056 $result = Status::newGood(); 00057 // Bail out if SQLite is too old 00058 $db = new DatabaseSqliteStandalone( ':memory:' ); 00059 if ( version_compare( $db->getServerVersion(), self::MINIMUM_VERSION, '<' ) ) { 00060 $result->fatal( 'config-outdated-sqlite', $db->getServerVersion(), self::MINIMUM_VERSION ); 00061 } 00062 // Check for FTS3 full-text search module 00063 if ( DatabaseSqlite::getFulltextSearchModule() != 'FTS3' ) { 00064 $result->warning( 'config-no-fts3' ); 00065 } 00066 00067 return $result; 00068 } 00069 00070 public function getGlobalDefaults() { 00071 if ( isset( $_SERVER['DOCUMENT_ROOT'] ) ) { 00072 $path = str_replace( 00073 array( '/', '\\' ), 00074 DIRECTORY_SEPARATOR, 00075 dirname( $_SERVER['DOCUMENT_ROOT'] ) . '/data' 00076 ); 00077 00078 return array( 'wgSQLiteDataDir' => $path ); 00079 } else { 00080 return array(); 00081 } 00082 } 00083 00084 public function getConnectForm() { 00085 return $this->getTextBox( 00086 'wgSQLiteDataDir', 00087 'config-sqlite-dir', array(), 00088 $this->parent->getHelpBox( 'config-sqlite-dir-help' ) 00089 ) . 00090 $this->getTextBox( 00091 'wgDBname', 00092 'config-db-name', 00093 array(), 00094 $this->parent->getHelpBox( 'config-sqlite-name-help' ) 00095 ); 00096 } 00097 00105 private static function realpath( $path ) { 00106 $result = realpath( $path ); 00107 if ( !$result ) { 00108 return $path; 00109 } 00110 00111 return $result; 00112 } 00113 00117 public function submitConnectForm() { 00118 $this->setVarsFromRequest( array( 'wgSQLiteDataDir', 'wgDBname' ) ); 00119 00120 # Try realpath() if the directory already exists 00121 $dir = self::realpath( $this->getVar( 'wgSQLiteDataDir' ) ); 00122 $result = self::dataDirOKmaybeCreate( $dir, true /* create? */ ); 00123 if ( $result->isOK() ) { 00124 # Try expanding again in case we've just created it 00125 $dir = self::realpath( $dir ); 00126 $this->setVar( 'wgSQLiteDataDir', $dir ); 00127 } 00128 # Table prefix is not used on SQLite, keep it empty 00129 $this->setVar( 'wgDBprefix', '' ); 00130 00131 return $result; 00132 } 00133 00139 private static function dataDirOKmaybeCreate( $dir, $create = false ) { 00140 if ( !is_dir( $dir ) ) { 00141 if ( !is_writable( dirname( $dir ) ) ) { 00142 $webserverGroup = Installer::maybeGetWebserverPrimaryGroup(); 00143 if ( $webserverGroup !== null ) { 00144 return Status::newFatal( 00145 'config-sqlite-parent-unwritable-group', 00146 $dir, dirname( $dir ), basename( $dir ), 00147 $webserverGroup 00148 ); 00149 } else { 00150 return Status::newFatal( 00151 'config-sqlite-parent-unwritable-nogroup', 00152 $dir, dirname( $dir ), basename( $dir ) 00153 ); 00154 } 00155 } 00156 00157 # Called early on in the installer, later we just want to sanity check 00158 # if it's still writable 00159 if ( $create ) { 00160 wfSuppressWarnings(); 00161 $ok = wfMkdirParents( $dir, 0700, __METHOD__ ); 00162 wfRestoreWarnings(); 00163 if ( !$ok ) { 00164 return Status::newFatal( 'config-sqlite-mkdir-error', $dir ); 00165 } 00166 # Put a .htaccess file in in case the user didn't take our advice 00167 file_put_contents( "$dir/.htaccess", "Deny from all\n" ); 00168 } 00169 } 00170 if ( !is_writable( $dir ) ) { 00171 return Status::newFatal( 'config-sqlite-dir-unwritable', $dir ); 00172 } 00173 00174 # We haven't blown up yet, fall through 00175 return Status::newGood(); 00176 } 00177 00181 public function openConnection() { 00182 global $wgSQLiteDataDir; 00183 00184 $status = Status::newGood(); 00185 $dir = $this->getVar( 'wgSQLiteDataDir' ); 00186 $dbName = $this->getVar( 'wgDBname' ); 00187 try { 00188 # @todo FIXME: Need more sensible constructor parameters, e.g. single associative array 00189 # Setting globals kind of sucks 00190 $wgSQLiteDataDir = $dir; 00191 $db = new DatabaseSqlite( false, false, false, $dbName ); 00192 $status->value = $db; 00193 } catch ( DBConnectionError $e ) { 00194 $status->fatal( 'config-sqlite-connection-error', $e->getMessage() ); 00195 } 00196 00197 return $status; 00198 } 00199 00203 public function needsUpgrade() { 00204 $dir = $this->getVar( 'wgSQLiteDataDir' ); 00205 $dbName = $this->getVar( 'wgDBname' ); 00206 // Don't create the data file yet 00207 if ( !file_exists( DatabaseSqlite::generateFileName( $dir, $dbName ) ) ) { 00208 return false; 00209 } 00210 00211 // If the data file exists, look inside it 00212 return parent::needsUpgrade(); 00213 } 00214 00218 public function setupDatabase() { 00219 $dir = $this->getVar( 'wgSQLiteDataDir' ); 00220 00221 # Sanity check. We checked this before but maybe someone deleted the 00222 # data dir between then and now 00223 $dir_status = self::dataDirOKmaybeCreate( $dir, false /* create? */ ); 00224 if ( !$dir_status->isOK() ) { 00225 return $dir_status; 00226 } 00227 00228 $db = $this->getVar( 'wgDBname' ); 00229 $file = DatabaseSqlite::generateFileName( $dir, $db ); 00230 if ( file_exists( $file ) ) { 00231 if ( !is_writable( $file ) ) { 00232 return Status::newFatal( 'config-sqlite-readonly', $file ); 00233 } 00234 } else { 00235 if ( file_put_contents( $file, '' ) === false ) { 00236 return Status::newFatal( 'config-sqlite-cant-create-db', $file ); 00237 } 00238 } 00239 // nuke the unused settings for clarity 00240 $this->setVar( 'wgDBserver', '' ); 00241 $this->setVar( 'wgDBuser', '' ); 00242 $this->setVar( 'wgDBpassword', '' ); 00243 $this->setupSchemaVars(); 00244 00245 return $this->getConnection(); 00246 } 00247 00251 public function createTables() { 00252 $status = parent::createTables(); 00253 00254 return $this->setupSearchIndex( $status ); 00255 } 00256 00261 public function setupSearchIndex( &$status ) { 00262 global $IP; 00263 00264 $module = DatabaseSqlite::getFulltextSearchModule(); 00265 $fts3tTable = $this->db->checkForEnabledSearch(); 00266 if ( $fts3tTable && !$module ) { 00267 $status->warning( 'config-sqlite-fts3-downgrade' ); 00268 $this->db->sourceFile( "$IP/maintenance/sqlite/archives/searchindex-no-fts.sql" ); 00269 } elseif ( !$fts3tTable && $module == 'FTS3' ) { 00270 $this->db->sourceFile( "$IP/maintenance/sqlite/archives/searchindex-fts3.sql" ); 00271 } 00272 00273 return $status; 00274 } 00275 00279 public function getLocalSettings() { 00280 $dir = LocalSettingsGenerator::escapePhpString( $this->getVar( 'wgSQLiteDataDir' ) ); 00281 00282 return "# SQLite-specific settings 00283 \$wgSQLiteDataDir = \"{$dir}\";"; 00284 } 00285 }