Merge "TableSorter: Fix column order when collecting headers"
[lhc/web/wiklou.git] / includes / installer / MssqlInstaller.php
1 <?php
2 /**
3 * Microsoft SQL Server-specific installer.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * http://www.gnu.org/copyleft/gpl.html
19 *
20 * @file
21 * @ingroup Deployment
22 */
23
24 /**
25 * Class for setting up the MediaWiki database using Microsoft SQL Server.
26 *
27 * @ingroup Deployment
28 * @since 1.23
29 */
30 class MssqlInstaller extends DatabaseInstaller {
31
32 protected $globalNames = array(
33 'wgDBserver',
34 'wgDBname',
35 'wgDBuser',
36 'wgDBpassword',
37 'wgDBmwschema',
38 'wgDBprefix',
39 'wgDBWindowsAuthentication',
40 );
41
42 protected $internalDefaults = array(
43 '_InstallUser' => 'sa',
44 '_InstallWindowsAuthentication' => 'sqlauth',
45 '_WebWindowsAuthentication' => 'sqlauth',
46 );
47
48 public $minimumVersion = '9.00.1399'; // SQL Server 2005 RTM (TODO: are SQL Express version numbers different?)
49
50 // These are schema-level privs
51 // Note: the web user will be created will full permissions if possible, this permission
52 // list is only used if we are unable to grant full permissions.
53 public $webUserPrivs = array(
54 'DELETE',
55 'INSERT',
56 'SELECT',
57 'UPDATE',
58 'EXECUTE',
59 );
60
61 /**
62 * @return string
63 */
64 public function getName() {
65 return 'mssql';
66 }
67
68 /**
69 * @return Bool
70 */
71 public function isCompiled() {
72 return self::checkExtension( 'sqlsrv' );
73 }
74
75 /**
76 * @return string
77 */
78 public function getConnectForm() {
79 if ( $this->getVar( '_InstallWindowsAuthentication' ) == 'windowsauth' ) {
80 $displayStyle = 'display: none;';
81 } else {
82 $displayStyle = 'display: block;';
83 }
84
85 return $this->getTextBox(
86 'wgDBserver',
87 'config-db-host',
88 array(),
89 $this->parent->getHelpBox( 'config-db-host-help' )
90 ) .
91 Html::openElement( 'fieldset' ) .
92 Html::element( 'legend', array(), wfMessage( 'config-db-wiki-settings' )->text() ) .
93 $this->getTextBox( 'wgDBname', 'config-db-name', array( 'dir' => 'ltr' ),
94 $this->parent->getHelpBox( 'config-db-name-help' ) ) .
95 $this->getTextBox( 'wgDBmwschema', 'config-db-schema', array( 'dir' => 'ltr' ),
96 $this->parent->getHelpBox( 'config-db-schema-help' ) ) .
97 $this->getTextBox( 'wgDBprefix', 'config-db-prefix', array( 'dir' => 'ltr' ),
98 $this->parent->getHelpBox( 'config-db-prefix-help' ) ) .
99 Html::closeElement( 'fieldset' ) .
100 Html::openElement( 'fieldset' ) .
101 Html::element( 'legend', array(), wfMessage( 'config-db-install-account' )->text() ) .
102 $this->getRadioSet( array(
103 'var' => '_InstallWindowsAuthentication',
104 'label' => 'config-mssql-auth',
105 'itemLabelPrefix' => 'config-mssql-',
106 'values' => array( 'sqlauth', 'windowsauth' ),
107 'itemAttribs' => array(
108 'sqlauth' => array(
109 'class' => 'showHideRadio',
110 'rel' => 'dbCredentialBox',
111 ),
112 'windowsauth' => array(
113 'class' => 'hideShowRadio',
114 'rel' => 'dbCredentialBox',
115 )
116 ),
117 'help' => $this->parent->getHelpBox( 'config-mssql-install-auth' )
118 ) ) .
119 Html::openElement( 'div', array( 'id' => 'dbCredentialBox', 'style' => $displayStyle ) ) .
120 $this->getTextBox(
121 '_InstallUser',
122 'config-db-username',
123 array( 'dir' => 'ltr' ),
124 $this->parent->getHelpBox( 'config-db-install-username' )
125 ) .
126 $this->getPasswordBox(
127 '_InstallPassword',
128 'config-db-password',
129 array( 'dir' => 'ltr' ),
130 $this->parent->getHelpBox( 'config-db-install-password' )
131 ) .
132 Html::closeElement( 'div' ) .
133 Html::closeElement( 'fieldset' );
134 }
135
136 public function submitConnectForm() {
137 // Get variables from the request.
138 $newValues = $this->setVarsFromRequest( array( 'wgDBserver', 'wgDBname', 'wgDBmwschema', 'wgDBprefix' ) );
139
140 // Validate them.
141 $status = Status::newGood();
142 if ( !strlen( $newValues['wgDBserver'] ) ) {
143 $status->fatal( 'config-missing-db-host' );
144 }
145 if ( !strlen( $newValues['wgDBname'] ) ) {
146 $status->fatal( 'config-missing-db-name' );
147 } elseif ( !preg_match( '/^[a-z0-9_]+$/i', $newValues['wgDBname'] ) ) {
148 $status->fatal( 'config-invalid-db-name', $newValues['wgDBname'] );
149 }
150 if ( !preg_match( '/^[a-z0-9_]*$/i', $newValues['wgDBmwschema'] ) ) {
151 $status->fatal( 'config-invalid-schema', $newValues['wgDBmwschema'] );
152 }
153 if ( !preg_match( '/^[a-z0-9_]*$/i', $newValues['wgDBprefix'] ) ) {
154 $status->fatal( 'config-invalid-db-prefix', $newValues['wgDBprefix'] );
155 }
156 if ( !$status->isOK() ) {
157 return $status;
158 }
159
160 // Check for blank schema and remap to dbo
161 if ( $newValues['wgDBmwschema'] === '' ) {
162 $this->setVar( 'wgDBmwschema', 'dbo' );
163 }
164
165 // User box
166 $this->setVarsFromRequest( array( '_InstallUser', '_InstallPassword', '_InstallWindowsAuthentication' ) );
167
168 // Try to connect
169 $status = $this->getConnection();
170 if ( !$status->isOK() ) {
171 return $status;
172 }
173 /**
174 * @var $conn DatabaseBase
175 */
176 $conn = $status->value;
177
178 // Check version
179 $version = $conn->getServerVersion();
180 if ( version_compare( $version, $this->minimumVersion ) < 0 ) {
181 return Status::newFatal( 'config-mssql-old', $this->minimumVersion, $version );
182 }
183
184 return $status;
185 }
186
187 /**
188 * @return Status
189 */
190 public function openConnection() {
191 global $wgDBWindowsAuthentication;
192 $status = Status::newGood();
193 $user = $this->getVar( '_InstallUser' );
194 $password = $this->getVar( '_InstallPassword' );
195
196 if ( $this->getVar( '_InstallWindowsAuthentication' ) == 'windowsauth' ) {
197 // Use Windows authentication for this connection
198 $wgDBWindowsAuthentication = true;
199 } else {
200 $wgDBWindowsAuthentication = false;
201 }
202
203 try {
204 $db = DatabaseBase::factory( 'mssql', array(
205 'host' => $this->getVar( 'wgDBserver' ),
206 'user' => $user,
207 'password' => $password,
208 'dbname' => false,
209 'flags' => 0,
210 'tablePrefix' => $this->getVar( 'wgDBprefix' ) ) );
211 $db->prepareStatements( false );
212 $db->scrollableCursor( false );
213 $status->value = $db;
214 } catch ( DBConnectionError $e ) {
215 $status->fatal( 'config-connection-error', $e->getMessage() );
216 }
217
218 return $status;
219 }
220
221 public function preUpgrade() {
222 global $wgDBuser, $wgDBpassword;
223
224 $status = $this->getConnection();
225 if ( !$status->isOK() ) {
226 $this->parent->showStatusError( $status );
227
228 return;
229 }
230 /**
231 * @var $conn DatabaseBase
232 */
233 $conn = $status->value;
234 $conn->selectDB( $this->getVar( 'wgDBname' ) );
235
236 # Normal user and password are selected after this step, so for now
237 # just copy these two
238 $wgDBuser = $this->getVar( '_InstallUser' );
239 $wgDBpassword = $this->getVar( '_InstallPassword' );
240 }
241
242 /**
243 * Return true if the install user can create accounts
244 *
245 * @return bool
246 */
247 public function canCreateAccounts() {
248 $status = $this->getConnection();
249 if ( !$status->isOK() ) {
250 return false;
251 }
252 /** @var $conn DatabaseBase */
253 $conn = $status->value;
254
255 // We need the server-level ALTER ANY LOGIN permission to create new accounts
256 $res = $conn->query( "SELECT permission_name FROM sys.fn_my_permissions( NULL, 'SERVER' )" );
257 $serverPrivs = array(
258 'ALTER ANY LOGIN' => false,
259 'CONTROL SERVER' => false,
260 );
261
262 foreach ( $res as $row ) {
263 $serverPrivs[$row->permission_name] = true;
264 }
265
266 if ( !$serverPrivs['ALTER ANY LOGIN'] ) {
267 return false;
268 }
269
270 // Check to ensure we can grant everything needed as well
271 // We can't actually tell if we have WITH GRANT OPTION for a given permission, so we assume we do
272 // and just check for the permission
273 // http://technet.microsoft.com/en-us/library/ms178569.aspx
274 // The following array sets up which permissions imply whatever permissions we specify
275 $implied = array(
276 // schema database server
277 'DELETE' => array( 'DELETE', 'CONTROL SERVER' ),
278 'EXECUTE' => array( 'EXECUTE', 'CONTROL SERVER' ),
279 'INSERT' => array( 'INSERT', 'CONTROL SERVER' ),
280 'SELECT' => array( 'SELECT', 'CONTROL SERVER' ),
281 'UPDATE' => array( 'UPDATE', 'CONTROL SERVER' ),
282 );
283
284 $grantOptions = array_flip( $this->webUserPrivs );
285
286 // Check for schema and db-level permissions, but only if the schema/db exists
287 $schemaPrivs = $dbPrivs = array(
288 'DELETE' => false,
289 'EXECUTE' => false,
290 'INSERT' => false,
291 'SELECT' => false,
292 'UPDATE' => false,
293 );
294
295 $dbPrivs['ALTER ANY USER'] = false;
296
297 if ( $this->databaseExists( $this->getVar( 'wgDBname' ) ) ) {
298 $conn->selectDB( $this->getVar( 'wgDBname' ) );
299 $res = $conn->query( "SELECT permission_name FROM sys.fn_my_permissions( NULL, 'DATABASE' )" );
300
301 foreach ( $res as $row ) {
302 $dbPrivs[$row->permission_name] = true;
303 }
304
305 // If the db exists, we need ALTER ANY USER privs on it to make a new user
306 if ( !$dbPrivs['ALTER ANY USER'] ) {
307 return false;
308 }
309
310 if ( $this->schemaExists( $this->getVar( 'wgDBmwschema' ) ) ) {
311 // wgDBmwschema is validated to only contain alphanumeric + underscore, so this is safe
312 $res = $conn->query( "SELECT permission_name FROM sys.fn_my_permissions( '{$this->getVar( 'wgDBmwschema' )}', 'SCHEMA' )" );
313
314 foreach ( $res as $row ) {
315 $schemaPrivs[$row->permission_name] = true;
316 }
317 }
318 }
319
320 // Now check all the grants we'll need to be doing to see if we can
321 foreach ( $this->webUserPrivs as $permission ) {
322 if ( ( isset( $schemaPrivs[$permission] ) && $schemaPrivs[$permission] )
323 || ( isset( $dbPrivs[$implied[$permission][0]] ) && $dbPrivs[$implied[$permission][0]] )
324 || ( isset( $serverPrivs[$implied[$permission][1]] ) && $serverPrivs[$implied[$permission][1]] ) ) {
325
326 unset( $grantOptions[$permission] );
327 }
328 }
329
330 if ( count( $grantOptions ) ) {
331 // Can't grant everything
332 return false;
333 }
334
335 return true;
336 }
337
338 /**
339 * @return string
340 */
341 public function getSettingsForm() {
342 if ( $this->canCreateAccounts() ) {
343 $noCreateMsg = false;
344 } else {
345 $noCreateMsg = 'config-db-web-no-create-privs';
346 }
347 $wrapperStyle = $this->getVar( '_SameAccount' ) ? 'display: none' : '';
348 $displayStyle = $this->getVar( '_WebWindowsAuthentication' ) == 'windowsauth' ? 'display: none' : '';
349 $s = Html::openElement( 'fieldset' ) .
350 Html::element( 'legend', array(), wfMessage( 'config-db-web-account' )->text() ) .
351 $this->getCheckBox(
352 '_SameAccount', 'config-db-web-account-same',
353 array( 'class' => 'hideShowRadio', 'rel' => 'dbOtherAccount' )
354 ) .
355 Html::openElement( 'div', array( 'id' => 'dbOtherAccount', 'style' => $wrapperStyle ) ) .
356 $this->getRadioSet( array(
357 'var' => '_WebWindowsAuthentication',
358 'label' => 'config-mssql-auth',
359 'itemLabelPrefix' => 'config-mssql-',
360 'values' => array( 'sqlauth', 'windowsauth' ),
361 'itemAttribs' => array(
362 'sqlauth' => array(
363 'class' => 'showHideRadio',
364 'rel' => 'dbCredentialBox',
365 ),
366 'windowsauth' => array(
367 'class' => 'hideShowRadio',
368 'rel' => 'dbCredentialBox',
369 )
370 ),
371 'help' => $this->parent->getHelpBox( 'config-mssql-web-auth' )
372 ) ) .
373 Html::openElement( 'div', array( 'id' => 'dbCredentialBox', 'style' => $displayStyle ) ) .
374 $this->getTextBox( 'wgDBuser', 'config-db-username' ) .
375 $this->getPasswordBox( 'wgDBpassword', 'config-db-password' ) .
376 Html::closeElement( 'div' );
377
378 if ( $noCreateMsg ) {
379 $s .= $this->parent->getWarningBox( wfMessage( $noCreateMsg )->plain() );
380 } else {
381 $s .= $this->getCheckBox( '_CreateDBAccount', 'config-db-web-create' );
382 }
383
384 $s .= Html::closeElement( 'div' ) . Html::closeElement( 'fieldset' );
385
386 return $s;
387 }
388
389 /**
390 * @return Status
391 */
392 public function submitSettingsForm() {
393 $this->setVarsFromRequest(
394 array( 'wgDBuser', 'wgDBpassword', '_SameAccount', '_CreateDBAccount', '_WebWindowsAuthentication' )
395 );
396
397 if ( $this->getVar( '_SameAccount' ) ) {
398 $this->setVar( '_WebWindowsAuthentication', $this->getVar( '_InstallWindowsAuthentication' ) );
399 $this->setVar( 'wgDBuser', $this->getVar( '_InstallUser' ) );
400 $this->setVar( 'wgDBpassword', $this->getVar( '_InstallPassword' ) );
401 }
402
403 if ( $this->getVar( '_WebWindowsAuthentication' ) == 'windowsauth' ) {
404 $this->setVar( 'wgDBuser', '' );
405 $this->setVar( 'wgDBpassword', '' );
406 $this->setVar( 'wgDBWindowsAuthentication', true );
407 } else {
408 $this->setVar( 'wgDBWindowsAuthentication', false );
409 }
410
411 if ( $this->getVar( '_CreateDBAccount' ) && $this->getVar( '_WebWindowsAuthentication' ) == 'sqlauth' && strval( $this->getVar( 'wgDBpassword' ) ) == '' ) {
412 return Status::newFatal( 'config-db-password-empty', $this->getVar( 'wgDBuser' ) );
413 }
414
415 // Validate the create checkbox
416 $canCreate = $this->canCreateAccounts();
417 if ( !$canCreate ) {
418 $this->setVar( '_CreateDBAccount', false );
419 $create = false;
420 } else {
421 $create = $this->getVar( '_CreateDBAccount' );
422 }
423
424 if ( !$create ) {
425 // Test the web account
426 $user = $this->getVar( 'wgDBuser' );
427 $password = $this->getVar( 'wgDBpassword' );
428
429 if ( $this->getVar( '_WebWindowsAuthentication' ) == 'windowsauth' ) {
430 $user = 'windowsauth';
431 $password = 'windowsauth';
432 }
433
434 try {
435 DatabaseBase::factory( 'mssql', array(
436 'host' => $this->getVar( 'wgDBserver' ),
437 'user' => $user,
438 'password' => $password,
439 'dbname' => false,
440 'flags' => 0,
441 'tablePrefix' => $this->getVar( 'wgDBprefix' ),
442 'schema' => $this->getVar( 'wgDBmwschema' ),
443 ) );
444 } catch ( DBConnectionError $e ) {
445 return Status::newFatal( 'config-connection-error', $e->getMessage() );
446 }
447 }
448
449 return Status::newGood();
450 }
451
452 public function preInstall() {
453 # Add our user callback to installSteps, right before the tables are created.
454 $callback = array(
455 'name' => 'user',
456 'callback' => array( $this, 'setupUser' ),
457 );
458 $this->parent->addInstallStep( $callback, 'tables' );
459 }
460
461 /**
462 * @return Status
463 */
464 public function setupDatabase() {
465 $status = $this->getConnection();
466 if ( !$status->isOK() ) {
467 return $status;
468 }
469 /** @var DatabaseBase $conn */
470 $conn = $status->value;
471 $dbName = $this->getVar( 'wgDBname' );
472 $schemaName = $this->getVar( 'wgDBmwschema' );
473 if ( !$this->databaseExists( $dbName ) ) {
474 $conn->query( "CREATE DATABASE " . $conn->addIdentifierQuotes( $dbName ), __METHOD__ );
475 $conn->selectDB( $dbName );
476 if ( !$this->schemaExists( $schemaName ) ) {
477 $conn->query( "CREATE SCHEMA " . $conn->addIdentifierQuotes( $schemaName ), __METHOD__ );
478 }
479 if ( !$this->catalogExists( $schemaName ) ) {
480 $conn->query( "CREATE FULLTEXT CATALOG " . $conn->addIdentifierQuotes( $schemaName ), __METHOD__ );
481 }
482 }
483 $this->setupSchemaVars();
484
485 return $status;
486 }
487
488 /**
489 * @return Status
490 */
491 public function setupUser() {
492 $dbUser = $this->getVar( 'wgDBuser' );
493 if ( $dbUser == $this->getVar( '_InstallUser' )
494 || ( $this->getVar( '_InstallWindowsAuthentication' ) == 'windowsauth'
495 && $this->getVar( '_WebWindowsAuthentication' ) == 'windowsauth' ) ) {
496 return Status::newGood();
497 }
498 $status = $this->getConnection();
499 if ( !$status->isOK() ) {
500 return $status;
501 }
502
503 $this->setupSchemaVars();
504 $dbName = $this->getVar( 'wgDBname' );
505 $this->db->selectDB( $dbName );
506 $server = $this->getVar( 'wgDBserver' );
507 $password = $this->getVar( 'wgDBpassword' );
508 $schemaName = $this->getVar( 'wgDBmwschema' );
509
510 if ( $this->getVar( '_WebWindowsAuthentication' ) == 'windowsauth' ) {
511 $dbUser = 'windowsauth';
512 $password = 'windowsauth';
513 }
514
515 if ( $this->getVar( '_CreateDBAccount' ) ) {
516 $tryToCreate = true;
517 } else {
518 $tryToCreate = false;
519 }
520
521 $escUser = $this->db->addIdentifierQuotes( $dbUser );
522 $escDb = $this->db->addIdentifierQuotes( $dbName );
523 $escSchema = $this->db->addIdentifierQuotes( $schemaName );
524 $grantableNames = array();
525 if ( $tryToCreate ) {
526 $escPass = $this->db->addQuotes( $password );
527
528 if ( !$this->loginExists( $dbUser ) ) {
529 try {
530 $this->db->begin();
531 $this->db->selectDB( 'master' );
532 $logintype = $this->getVar( '_WebWindowsAuthentication' ) == 'windowsauth' ? 'FROM WINDOWS' : "WITH PASSWORD = $escPass";
533 $this->db->query( "CREATE LOGIN $escUser $logintype" );
534 $this->db->selectDB( $dbName );
535 $this->db->query( "CREATE USER $escUser FOR LOGIN $escUser WITH DEFAULT_SCHEMA = $escSchema" );
536 $this->db->commit();
537 $grantableNames[] = $dbUser;
538 } catch ( DBQueryError $dqe ) {
539 $this->db->rollback();
540 $status->warning( 'config-install-user-create-failed', $dbUser, $dqe->getText() );
541 }
542 } elseif ( !$this->userExists( $dbUser ) ) {
543 try {
544 $this->db->begin();
545 $this->db->selectDB( $dbName );
546 $this->db->query( "CREATE USER $escUser FOR LOGIN $escUser WITH DEFAULT_SCHEMA = $escSchema" );
547 $this->db->commit();
548 $grantableNames[] = $dbUser;
549 } catch ( DBQueryError $dqe ) {
550 $this->db->rollback();
551 $status->warning( 'config-install-user-create-failed', $dbUser, $dqe->getText() );
552 }
553 } else {
554 $status->warning( 'config-install-user-alreadyexists', $dbUser );
555 $grantableNames[] = $dbUser;
556 }
557 }
558
559 // Try to grant to all the users we know exist or we were able to create
560 $this->db->selectDB( $dbName );
561 foreach ( $grantableNames as $name ) {
562 try {
563 // First try to grant full permissions
564 $fullPrivArr = array(
565 'BACKUP DATABASE', 'BACKUP LOG', 'CREATE FUNCTION', 'CREATE PROCEDURE',
566 'CREATE TABLE', 'CREATE VIEW', 'CREATE FULLTEXT CATALOG', 'SHOWPLAN'
567 );
568 $fullPrivList = implode( ', ', $fullPrivArr );
569 $this->db->begin();
570 $this->db->query( "GRANT $fullPrivList ON DATABASE :: $escDb TO $escUser", __METHOD__ );
571 $this->db->query( "GRANT CONTROL ON SCHEMA :: $escSchema TO $escUser", __METHOD__ );
572 $this->db->commit();
573 } catch ( DBQueryError $dqe ) {
574 // If that fails, try to grant the limited subset specified in $this->webUserPrivs
575 try {
576 $privList = implode( ', ', $this->webUserPrivs );
577 $this->db->rollback();
578 $this->db->begin();
579 $this->db->query( "GRANT $privList ON SCHEMA :: $escSchema TO $escUser", __METHOD__ );
580 $this->db->commit();
581 } catch ( DBQueryError $dqe ) {
582 $this->db->rollback();
583 $status->fatal( 'config-install-user-grant-failed', $dbUser, $dqe->getText() );
584 }
585 // Also try to grant SHOWPLAN on the db, but don't fail if we can't
586 // (just makes a couple things in mediawiki run slower since
587 // we have to run SELECT COUNT(*) instead of getting the query plan)
588 try {
589 $this->db->query( "GRANT SHOWPLAN ON DATABASE :: $escDb TO $escUser", __METHOD__ );
590 } catch ( DBQueryError $dqe ) {
591 }
592 }
593 }
594
595 return $status;
596 }
597
598 public function createTables() {
599 $status = parent::createTables();
600
601 // Do last-minute stuff like fulltext indexes (since they can't be inside a transaction)
602 if ( $status->isOk() ) {
603 $searchindex = $this->db->tableName( 'searchindex' );
604 $schema = $this->db->addIdentifierQuotes( $this->getVar( 'wgDBmwschema' ) );
605 try {
606 $this->db->query( "CREATE FULLTEXT INDEX ON $searchindex (si_title, si_text) KEY INDEX si_page ON $schema" );
607 } catch ( DBQueryError $dqe ) {
608 $status->fatal( 'config-install-tables-failed', $dqe->getText() );
609 }
610 }
611
612 return $status;
613 }
614
615 /**
616 * Try to see if the login exists
617 * @param string $user Username to check
618 * @return boolean
619 */
620 private function loginExists( $user ) {
621 $res = $this->db->selectField( 'sys.sql_logins', 1, array( 'name' => $user ) );
622 return (bool)$res;
623 }
624
625 /**
626 * Try to see if the user account exists
627 * We assume we already have the appropriate database selected
628 * @param string $user Username to check
629 * @return boolean
630 */
631 private function userExists( $user ) {
632 $res = $this->db->selectField( 'sys.sysusers', 1, array( 'name' => $user ) );
633 return (bool)$res;
634 }
635
636 /**
637 * Try to see if a given database exists
638 * @param string $dbName Database name to check
639 * @return boolean
640 */
641 private function databaseExists( $dbName ) {
642 $res = $this->db->selectField( 'sys.databases', 1, array( 'name' => $dbName ) );
643 return (bool)$res;
644 }
645
646 /**
647 * Try to see if a given schema exists
648 * We assume we already have the appropriate database selected
649 * @param string $schemaName Schema name to check
650 * @return boolean
651 */
652 private function schemaExists( $schemaName ) {
653 $res = $this->db->selectField( 'sys.schemas', 1, array( 'name' => $schemaName ) );
654 return (bool)$res;
655 }
656
657 /**
658 * Try to see if a given fulltext catalog exists
659 * We assume we already have the appropriate database selected
660 * @param string $schemaName Catalog name to check
661 * @return boolean
662 */
663 private function catalogExists( $catalogName ) {
664 $res = $this->db->selectField( 'sys.fulltext_catalogs', 1, array( 'name' => $catalogName ) );
665 return (bool)$res;
666 }
667
668 /**
669 * Get variables to substitute into tables.sql and the SQL patch files.
670 *
671 * @return array
672 */
673 public function getSchemaVars() {
674 return array(
675 'wgDBname' => $this->getVar( 'wgDBname' ),
676 'wgDBmwschema' => $this->getVar( 'wgDBmwschema' ),
677 'wgDBuser' => $this->getVar( 'wgDBuser' ),
678 'wgDBpassword' => $this->getVar( 'wgDBpassword' ),
679 );
680 }
681
682 public function getLocalSettings() {
683 $schema = LocalSettingsGenerator::escapePhpString( $this->getVar( 'wgDBmwschema' ) );
684 $prefix = LocalSettingsGenerator::escapePhpString( $this->getVar( 'wgDBprefix' ) );
685 $windowsauth = $this->getVar( 'wgDBWindowsAuthentication' ) ? 'true' : 'false';
686
687 return "# MSSQL specific settings
688 \$wgDBWindowsAuthentication = {$windowsauth};
689 \$wgDBmwschema = \"{$schema}\";
690 \$wgDBprefix = \"{$prefix}\";";
691 }
692 }