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