MediaWiki  1.28.0
MssqlInstaller.php
Go to the documentation of this file.
1 <?php
31 
32  protected $globalNames = [
33  'wgDBserver',
34  'wgDBname',
35  'wgDBuser',
36  'wgDBpassword',
37  'wgDBmwschema',
38  'wgDBprefix',
39  'wgDBWindowsAuthentication',
40  ];
41 
42  protected $internalDefaults = [
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 = [
56  'DELETE',
57  'INSERT',
58  'SELECT',
59  'UPDATE',
60  'EXECUTE',
61  ];
62 
66  public function getName() {
67  return 'mssql';
68  }
69 
73  public function isCompiled() {
74  return self::checkExtension( 'sqlsrv' );
75  }
76 
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  [],
91  $this->parent->getHelpBox( 'config-db-host-help' )
92  ) .
93  Html::openElement( 'fieldset' ) .
94  Html::element( 'legend', [], wfMessage( 'config-db-wiki-settings' )->text() ) .
95  $this->getTextBox( 'wgDBname', 'config-db-name', [ 'dir' => 'ltr' ],
96  $this->parent->getHelpBox( 'config-db-name-help' ) ) .
97  $this->getTextBox( 'wgDBmwschema', 'config-db-schema', [ 'dir' => 'ltr' ],
98  $this->parent->getHelpBox( 'config-db-schema-help' ) ) .
99  $this->getTextBox( 'wgDBprefix', 'config-db-prefix', [ 'dir' => 'ltr' ],
100  $this->parent->getHelpBox( 'config-db-prefix-help' ) ) .
101  Html::closeElement( 'fieldset' ) .
102  Html::openElement( 'fieldset' ) .
103  Html::element( 'legend', [], wfMessage( 'config-db-install-account' )->text() ) .
104  $this->getRadioSet( [
105  'var' => '_InstallWindowsAuthentication',
106  'label' => 'config-mssql-auth',
107  'itemLabelPrefix' => 'config-mssql-',
108  'values' => [ 'sqlauth', 'windowsauth' ],
109  'itemAttribs' => [
110  'sqlauth' => [
111  'class' => 'showHideRadio',
112  'rel' => 'dbCredentialBox',
113  ],
114  'windowsauth' => [
115  'class' => 'hideShowRadio',
116  'rel' => 'dbCredentialBox',
117  ]
118  ],
119  'help' => $this->parent->getHelpBox( 'config-mssql-install-auth' )
120  ] ) .
121  Html::openElement( 'div', [ 'id' => 'dbCredentialBox', 'style' => $displayStyle ] ) .
122  $this->getTextBox(
123  '_InstallUser',
124  'config-db-username',
125  [ 'dir' => 'ltr' ],
126  $this->parent->getHelpBox( 'config-db-install-username' )
127  ) .
128  $this->getPasswordBox(
129  '_InstallPassword',
130  'config-db-password',
131  [ '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( [
141  'wgDBserver',
142  'wgDBname',
143  'wgDBmwschema',
144  'wgDBprefix'
145  ] );
146 
147  // Validate them.
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( [
174  '_InstallUser',
175  '_InstallPassword',
176  '_InstallWindowsAuthentication'
177  ] );
178 
179  // Try to connect
180  $status = $this->getConnection();
181  if ( !$status->isOK() ) {
182  return $status;
183  }
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 
201  public function openConnection() {
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 = Database::factory( 'mssql', [
216  'host' => $this->getVar( 'wgDBserver' ),
217  'user' => $user,
218  'password' => $password,
219  'dbname' => false,
220  'flags' => 0,
221  'schema' => $this->getVar( 'wgDBmwschema' ),
222  'tablePrefix' => $this->getVar( 'wgDBprefix' ) ] );
223  $db->prepareStatements( false );
224  $db->scrollableCursor( false );
225  $status->value = $db;
226  } catch ( DBConnectionError $e ) {
227  $status->fatal( 'config-connection-error', $e->getMessage() );
228  }
229 
230  return $status;
231  }
232 
233  public function preUpgrade() {
235 
236  $status = $this->getConnection();
237  if ( !$status->isOK() ) {
238  $this->parent->showStatusError( $status );
239 
240  return;
241  }
245  $conn = $status->value;
246  $conn->selectDB( $this->getVar( 'wgDBname' ) );
247 
248  # Normal user and password are selected after this step, so for now
249  # just copy these two
250  $wgDBuser = $this->getVar( '_InstallUser' );
251  $wgDBpassword = $this->getVar( '_InstallPassword' );
252  }
253 
259  public function canCreateAccounts() {
260  $status = $this->getConnection();
261  if ( !$status->isOK() ) {
262  return false;
263  }
265  $conn = $status->value;
266 
267  // We need the server-level ALTER ANY LOGIN permission to create new accounts
268  $res = $conn->query( "SELECT permission_name FROM sys.fn_my_permissions( NULL, 'SERVER' )" );
269  $serverPrivs = [
270  'ALTER ANY LOGIN' => false,
271  'CONTROL SERVER' => false,
272  ];
273 
274  foreach ( $res as $row ) {
275  $serverPrivs[$row->permission_name] = true;
276  }
277 
278  if ( !$serverPrivs['ALTER ANY LOGIN'] ) {
279  return false;
280  }
281 
282  // Check to ensure we can grant everything needed as well
283  // We can't actually tell if we have WITH GRANT OPTION for a given permission, so we assume we do
284  // and just check for the permission
285  // http://technet.microsoft.com/en-us/library/ms178569.aspx
286  // The following array sets up which permissions imply whatever permissions we specify
287  $implied = [
288  // schema database server
289  'DELETE' => [ 'DELETE', 'CONTROL SERVER' ],
290  'EXECUTE' => [ 'EXECUTE', 'CONTROL SERVER' ],
291  'INSERT' => [ 'INSERT', 'CONTROL SERVER' ],
292  'SELECT' => [ 'SELECT', 'CONTROL SERVER' ],
293  'UPDATE' => [ 'UPDATE', 'CONTROL SERVER' ],
294  ];
295 
296  $grantOptions = array_flip( $this->webUserPrivs );
297 
298  // Check for schema and db-level permissions, but only if the schema/db exists
299  $schemaPrivs = $dbPrivs = [
300  'DELETE' => false,
301  'EXECUTE' => false,
302  'INSERT' => false,
303  'SELECT' => false,
304  'UPDATE' => false,
305  ];
306 
307  $dbPrivs['ALTER ANY USER'] = false;
308 
309  if ( $this->databaseExists( $this->getVar( 'wgDBname' ) ) ) {
310  $conn->selectDB( $this->getVar( 'wgDBname' ) );
311  $res = $conn->query( "SELECT permission_name FROM sys.fn_my_permissions( NULL, 'DATABASE' )" );
312 
313  foreach ( $res as $row ) {
314  $dbPrivs[$row->permission_name] = true;
315  }
316 
317  // If the db exists, we need ALTER ANY USER privs on it to make a new user
318  if ( !$dbPrivs['ALTER ANY USER'] ) {
319  return false;
320  }
321 
322  if ( $this->schemaExists( $this->getVar( 'wgDBmwschema' ) ) ) {
323  // wgDBmwschema is validated to only contain alphanumeric + underscore, so this is safe
324  $res = $conn->query( "SELECT permission_name FROM sys.fn_my_permissions( "
325  . "'{$this->getVar( 'wgDBmwschema' )}', 'SCHEMA' )" );
326 
327  foreach ( $res as $row ) {
328  $schemaPrivs[$row->permission_name] = true;
329  }
330  }
331  }
332 
333  // Now check all the grants we'll need to be doing to see if we can
334  foreach ( $this->webUserPrivs as $permission ) {
335  if ( ( isset( $schemaPrivs[$permission] ) && $schemaPrivs[$permission] )
336  || ( isset( $dbPrivs[$implied[$permission][0]] )
337  && $dbPrivs[$implied[$permission][0]] )
338  || ( isset( $serverPrivs[$implied[$permission][1]] )
339  && $serverPrivs[$implied[$permission][1]] )
340  ) {
341  unset( $grantOptions[$permission] );
342  }
343  }
344 
345  if ( count( $grantOptions ) ) {
346  // Can't grant everything
347  return false;
348  }
349 
350  return true;
351  }
352 
356  public function getSettingsForm() {
357  if ( $this->canCreateAccounts() ) {
358  $noCreateMsg = false;
359  } else {
360  $noCreateMsg = 'config-db-web-no-create-privs';
361  }
362 
363  $wrapperStyle = $this->getVar( '_SameAccount' ) ? 'display: none' : '';
364  $displayStyle = $this->getVar( '_WebWindowsAuthentication' ) == 'windowsauth'
365  ? 'display: none'
366  : '';
367  $s = Html::openElement( 'fieldset' ) .
368  Html::element( 'legend', [], wfMessage( 'config-db-web-account' )->text() ) .
369  $this->getCheckBox(
370  '_SameAccount', 'config-db-web-account-same',
371  [ 'class' => 'hideShowRadio', 'rel' => 'dbOtherAccount' ]
372  ) .
373  Html::openElement( 'div', [ 'id' => 'dbOtherAccount', 'style' => $wrapperStyle ] ) .
374  $this->getRadioSet( [
375  'var' => '_WebWindowsAuthentication',
376  'label' => 'config-mssql-auth',
377  'itemLabelPrefix' => 'config-mssql-',
378  'values' => [ 'sqlauth', 'windowsauth' ],
379  'itemAttribs' => [
380  'sqlauth' => [
381  'class' => 'showHideRadio',
382  'rel' => 'dbCredentialBox',
383  ],
384  'windowsauth' => [
385  'class' => 'hideShowRadio',
386  'rel' => 'dbCredentialBox',
387  ]
388  ],
389  'help' => $this->parent->getHelpBox( 'config-mssql-web-auth' )
390  ] ) .
391  Html::openElement( 'div', [ 'id' => 'dbCredentialBox', 'style' => $displayStyle ] ) .
392  $this->getTextBox( 'wgDBuser', 'config-db-username' ) .
393  $this->getPasswordBox( 'wgDBpassword', 'config-db-password' ) .
394  Html::closeElement( 'div' );
395 
396  if ( $noCreateMsg ) {
397  $s .= $this->parent->getWarningBox( wfMessage( $noCreateMsg )->plain() );
398  } else {
399  $s .= $this->getCheckBox( '_CreateDBAccount', 'config-db-web-create' );
400  }
401 
402  $s .= Html::closeElement( 'div' ) . Html::closeElement( 'fieldset' );
403 
404  return $s;
405  }
406 
410  public function submitSettingsForm() {
411  $this->setVarsFromRequest( [
412  'wgDBuser',
413  'wgDBpassword',
414  '_SameAccount',
415  '_CreateDBAccount',
416  '_WebWindowsAuthentication'
417  ] );
418 
419  if ( $this->getVar( '_SameAccount' ) ) {
420  $this->setVar( '_WebWindowsAuthentication', $this->getVar( '_InstallWindowsAuthentication' ) );
421  $this->setVar( 'wgDBuser', $this->getVar( '_InstallUser' ) );
422  $this->setVar( 'wgDBpassword', $this->getVar( '_InstallPassword' ) );
423  }
424 
425  if ( $this->getVar( '_WebWindowsAuthentication' ) == 'windowsauth' ) {
426  $this->setVar( 'wgDBuser', '' );
427  $this->setVar( 'wgDBpassword', '' );
428  $this->setVar( 'wgDBWindowsAuthentication', true );
429  } else {
430  $this->setVar( 'wgDBWindowsAuthentication', false );
431  }
432 
433  if ( $this->getVar( '_CreateDBAccount' )
434  && $this->getVar( '_WebWindowsAuthentication' ) == 'sqlauth'
435  && strval( $this->getVar( 'wgDBpassword' ) ) == ''
436  ) {
437  return Status::newFatal( 'config-db-password-empty', $this->getVar( 'wgDBuser' ) );
438  }
439 
440  // Validate the create checkbox
441  $canCreate = $this->canCreateAccounts();
442  if ( !$canCreate ) {
443  $this->setVar( '_CreateDBAccount', false );
444  $create = false;
445  } else {
446  $create = $this->getVar( '_CreateDBAccount' );
447  }
448 
449  if ( !$create ) {
450  // Test the web account
451  $user = $this->getVar( 'wgDBuser' );
452  $password = $this->getVar( 'wgDBpassword' );
453 
454  if ( $this->getVar( '_WebWindowsAuthentication' ) == 'windowsauth' ) {
455  $user = 'windowsauth';
456  $password = 'windowsauth';
457  }
458 
459  try {
460  Database::factory( 'mssql', [
461  'host' => $this->getVar( 'wgDBserver' ),
462  'user' => $user,
463  'password' => $password,
464  'dbname' => false,
465  'flags' => 0,
466  'tablePrefix' => $this->getVar( 'wgDBprefix' ),
467  'schema' => $this->getVar( 'wgDBmwschema' ),
468  ] );
469  } catch ( DBConnectionError $e ) {
470  return Status::newFatal( 'config-connection-error', $e->getMessage() );
471  }
472  }
473 
474  return Status::newGood();
475  }
476 
477  public function preInstall() {
478  # Add our user callback to installSteps, right before the tables are created.
479  $callback = [
480  'name' => 'user',
481  'callback' => [ $this, 'setupUser' ],
482  ];
483  $this->parent->addInstallStep( $callback, 'tables' );
484  }
485 
489  public function setupDatabase() {
490  $status = $this->getConnection();
491  if ( !$status->isOK() ) {
492  return $status;
493  }
495  $conn = $status->value;
496  $dbName = $this->getVar( 'wgDBname' );
497  $schemaName = $this->getVar( 'wgDBmwschema' );
498  if ( !$this->databaseExists( $dbName ) ) {
499  $conn->query(
500  "CREATE DATABASE " . $conn->addIdentifierQuotes( $dbName ),
501  __METHOD__
502  );
503  }
504  $conn->selectDB( $dbName );
505  if ( !$this->schemaExists( $schemaName ) ) {
506  $conn->query(
507  "CREATE SCHEMA " . $conn->addIdentifierQuotes( $schemaName ),
508  __METHOD__
509  );
510  }
511  if ( !$this->catalogExists( $schemaName ) ) {
512  $conn->query(
513  "CREATE FULLTEXT CATALOG " . $conn->addIdentifierQuotes( $schemaName ),
514  __METHOD__
515  );
516  }
517  $this->setupSchemaVars();
518 
519  return $status;
520  }
521 
525  public function setupUser() {
526  $dbUser = $this->getVar( 'wgDBuser' );
527  if ( $dbUser == $this->getVar( '_InstallUser' )
528  || ( $this->getVar( '_InstallWindowsAuthentication' ) == 'windowsauth'
529  && $this->getVar( '_WebWindowsAuthentication' ) == 'windowsauth' ) ) {
530  return Status::newGood();
531  }
532  $status = $this->getConnection();
533  if ( !$status->isOK() ) {
534  return $status;
535  }
536 
537  $this->setupSchemaVars();
538  $dbName = $this->getVar( 'wgDBname' );
539  $this->db->selectDB( $dbName );
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 = [];
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 = [
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  public function getGlobalDefaults() {
652  // The default $wgDBmwschema is null, which breaks Postgres and other DBMSes that require
653  // the use of a schema, so we need to set it here
654  return array_merge( parent::getGlobalDefaults(), [
655  'wgDBmwschema' => 'mediawiki',
656  ] );
657  }
658 
664  private function loginExists( $user ) {
665  $res = $this->db->selectField( 'sys.sql_logins', 1, [ 'name' => $user ] );
666  return (bool)$res;
667  }
668 
675  private function userExists( $user ) {
676  $res = $this->db->selectField( 'sys.sysusers', 1, [ 'name' => $user ] );
677  return (bool)$res;
678  }
679 
685  private function databaseExists( $dbName ) {
686  $res = $this->db->selectField( 'sys.databases', 1, [ 'name' => $dbName ] );
687  return (bool)$res;
688  }
689 
696  private function schemaExists( $schemaName ) {
697  $res = $this->db->selectField( 'sys.schemas', 1, [ 'name' => $schemaName ] );
698  return (bool)$res;
699  }
700 
707  private function catalogExists( $catalogName ) {
708  $res = $this->db->selectField( 'sys.fulltext_catalogs', 1, [ 'name' => $catalogName ] );
709  return (bool)$res;
710  }
711 
717  public function getSchemaVars() {
718  return [
719  'wgDBname' => $this->getVar( 'wgDBname' ),
720  'wgDBmwschema' => $this->getVar( 'wgDBmwschema' ),
721  'wgDBuser' => $this->getVar( 'wgDBuser' ),
722  'wgDBpassword' => $this->getVar( 'wgDBpassword' ),
723  ];
724  }
725 
726  public function getLocalSettings() {
727  $schema = LocalSettingsGenerator::escapePhpString( $this->getVar( 'wgDBmwschema' ) );
728  $prefix = LocalSettingsGenerator::escapePhpString( $this->getVar( 'wgDBprefix' ) );
729  $windowsauth = $this->getVar( 'wgDBWindowsAuthentication' ) ? 'true' : 'false';
730 
731  return "# MSSQL specific settings
732 \$wgDBWindowsAuthentication = {$windowsauth};
733 \$wgDBmwschema = \"{$schema}\";
734 \$wgDBprefix = \"{$prefix}\";";
735  }
736 }
static closeElement($element)
Returns "".
Definition: Html.php:305
either a plain
Definition: hooks.txt:1987
schemaExists($schemaName)
Try to see if a given schema exists We assume we already have the appropriate database selected...
static factory($dbType, $p=[])
Construct a Database subclass instance given a database type and parameters.
Definition: Database.php:325
div flags Integer display flags(NO_ACTION_LINK, NO_EXTRA_USER_LINKS) 'LogException'returning false will NOT prevent logging $e
Definition: hooks.txt:2102
static newFatal($message)
Factory function for fatal errors.
Definition: StatusValue.php:63
$wgDBpassword
Database user's password.
static escapePhpString($string)
Returns the escaped version of a string of php code.
$wgDBuser
Database username.
getVar($var, $default=null)
Get a variable, taking local defaults into account.
when a variable name is used in a it is silently declared as a new local masking the global
Definition: design.txt:93
userExists($user)
Try to see if the user account exists We assume we already have the appropriate database selected...
Class for setting up the MediaWiki database using Microsoft SQL Server.
$wgDBWindowsAuthentication
Use Windows Authentication instead of $wgDBuser / $wgDBpassword for MS SQL Server.
canCreateAccounts()
Return true if the install user can create accounts.
getSchemaVars()
Get variables to substitute into tables.sql and the SQL patch files.
getConnection()
Connect to the database using the administrative user/password currently defined in the session...
static openElement($element, $attribs=[])
Identical to rawElement(), but has no third parameter and omits the end tag (and the self-closing '/'...
Definition: Html.php:247
setupSchemaVars()
Set appropriate schema variables in the current database connection.
either a unescaped string or a HtmlArmor object after in associative array form externallinks including delete and has completed for all link tables whether this was an auto creation default is conds Array Extra conditions for the No matching items in log is displayed if loglist is empty msgKey Array If you want a nice box with a set this to the key of the message First element is the message additional optional elements are parameters for the key that are processed with wfMessage() -> params() ->parseAsBlock()-offset Set to overwrite offset parameter in $wgRequest set to ''to unsetoffset-wrap String Wrap the message in html(usually something like"&lt
loginExists($user)
Try to see if the login exists.
$res
Definition: database.txt:21
static newGood($value=null)
Factory function for good results.
Definition: StatusValue.php:76
design txt This is a brief overview of the new design More thorough and up to date information is available on the documentation wiki at etc Handles the details of getting and saving to the user table of the and dealing with sessions and cookies OutputPage Encapsulates the entire HTML page that will be sent in response to any server request It is used by calling its functions to add text
Definition: design.txt:12
This document is intended to provide useful advice for parties seeking to redistribute MediaWiki to end users It s targeted particularly at maintainers for Linux since it s been observed that distribution packages of MediaWiki often break We ve consistently had to recommend that users seeking support use official tarballs instead of their distribution s and this often solves whatever problem the user is having It would be nice if this could such as
Definition: distributors.txt:9
getPasswordBox($var, $label, $attribs=[], $helpData="")
Get a labelled password box to configure a local variable.
please add to it if you re going to add events to the MediaWiki code where normally authentication against an external auth plugin would be creating a local account $user
Definition: hooks.txt:242
setVarsFromRequest($varNames)
Convenience function to set variables based on form data.
catalogExists($catalogName)
Try to see if a given fulltext catalog exists We assume we already have the appropriate database sele...
injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency which acts as the top level factory for services in MediaWiki which can be used to gain access to default instances of various services MediaWikiServices however also allows new services to be defined and default services to be redefined Services are defined or redefined by providing a callback the instantiator that will return a new instance of the service When it will create an instance of MediaWikiServices and populate it with the services defined in the files listed by thereby bootstrapping the DI framework Per $wgServiceWiringFiles lists includes ServiceWiring php
Definition: injection.txt:35
databaseExists($dbName)
Try to see if a given database exists.
Database $db
The database connection.
getTextBox($var, $label, $attribs=[], $helpData="")
Get a labelled text box to configure a local variable.
Base class for DBMS-specific installation helper classes.
getCheckBox($var, $label, $attribs=[], $helpData="")
Get a labelled checkbox to configure a local boolean variable.
this hook is for auditing only RecentChangesLinked and Watchlist RecentChangesLinked and Watchlist e g Watchlist removed from all revisions and log entries to which it was applied This gives extensions a chance to take it off their books as the deletion has already been partly carried out by this point or something similar the user will be unable to create the tag set $status
Definition: hooks.txt:1046
setVar($name, $value)
Convenience alias for $this->parent->setVar()
getRadioSet($params)
Get a set of labelled radio buttons.
static element($element, $attribs=[], $contents= '')
Identical to rawElement(), but HTML-escapes $contents (like Xml::element()).
Definition: Html.php:229
Allows to change the fields on the form that will be generated $name
Definition: hooks.txt:300