[ Index ]

PHP Cross Reference of MediaWiki-1.24.0

title

Body

[close]

/includes/installer/ -> MssqlInstaller.php (source)

   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                  '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() {
 234          global $wgDBuser, $wgDBpassword;
 235  
 236          $status = $this->getConnection();
 237          if ( !$status->isOK() ) {
 238              $this->parent->showStatusError( $status );
 239  
 240              return;
 241          }
 242          /**
 243           * @var $conn DatabaseBase
 244           */
 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  
 254      /**
 255       * Return true if the install user can create accounts
 256       *
 257       * @return bool
 258       */
 259  	public function canCreateAccounts() {
 260          $status = $this->getConnection();
 261          if ( !$status->isOK() ) {
 262              return false;
 263          }
 264          /** @var $conn DatabaseBase */
 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 = array(
 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 = array(
 288              // schema           database  server
 289              'DELETE'  => array( 'DELETE', 'CONTROL SERVER' ),
 290              'EXECUTE' => array( 'EXECUTE', 'CONTROL SERVER' ),
 291              'INSERT'  => array( 'INSERT', 'CONTROL SERVER' ),
 292              'SELECT'  => array( 'SELECT', 'CONTROL SERVER' ),
 293              'UPDATE'  => array( '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 = array(
 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  
 353      /**
 354       * @return string
 355       */
 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', array(), wfMessage( 'config-db-web-account' )->text() ) .
 369              $this->getCheckBox(
 370                  '_SameAccount', 'config-db-web-account-same',
 371                  array( 'class' => 'hideShowRadio', 'rel' => 'dbOtherAccount' )
 372              ) .
 373              Html::openElement( 'div', array( 'id' => 'dbOtherAccount', 'style' => $wrapperStyle ) ) .
 374              $this->getRadioSet( array(
 375                  'var' => '_WebWindowsAuthentication',
 376                  'label' => 'config-mssql-auth',
 377                  'itemLabelPrefix' => 'config-mssql-',
 378                  'values' => array( 'sqlauth', 'windowsauth' ),
 379                  'itemAttribs' => array(
 380                      'sqlauth' => array(
 381                          'class' => 'showHideRadio',
 382                          'rel' => 'dbCredentialBox',
 383                      ),
 384                      'windowsauth' => array(
 385                          'class' => 'hideShowRadio',
 386                          'rel' => 'dbCredentialBox',
 387                      )
 388                  ),
 389                  'help' => $this->parent->getHelpBox( 'config-mssql-web-auth' )
 390              ) ) .
 391              Html::openElement( 'div', array( '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  
 407      /**
 408       * @return Status
 409       */
 410  	public function submitSettingsForm() {
 411          $this->setVarsFromRequest( array(
 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                  DatabaseBase::factory( 'mssql', array(
 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 = array(
 480              'name' => 'user',
 481              'callback' => array( $this, 'setupUser' ),
 482          );
 483          $this->parent->addInstallStep( $callback, 'tables' );
 484      }
 485  
 486      /**
 487       * @return Status
 488       */
 489  	public function setupDatabase() {
 490          $status = $this->getConnection();
 491          if ( !$status->isOK() ) {
 492              return $status;
 493          }
 494          /** @var DatabaseBase $conn */
 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              $conn->selectDB( $dbName );
 504              if ( !$this->schemaExists( $schemaName ) ) {
 505                  $conn->query(
 506                      "CREATE SCHEMA " . $conn->addIdentifierQuotes( $schemaName ),
 507                      __METHOD__
 508                  );
 509              }
 510              if ( !$this->catalogExists( $schemaName ) ) {
 511                  $conn->query(
 512                      "CREATE FULLTEXT CATALOG " . $conn->addIdentifierQuotes( $schemaName ),
 513                      __METHOD__
 514                  );
 515              }
 516          }
 517          $this->setupSchemaVars();
 518  
 519          return $status;
 520      }
 521  
 522      /**
 523       * @return Status
 524       */
 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          $server = $this->getVar( 'wgDBserver' );
 541          $password = $this->getVar( 'wgDBpassword' );
 542          $schemaName = $this->getVar( 'wgDBmwschema' );
 543  
 544          if ( $this->getVar( '_WebWindowsAuthentication' ) == 'windowsauth' ) {
 545              $dbUser = 'windowsauth';
 546              $password = 'windowsauth';
 547          }
 548  
 549          if ( $this->getVar( '_CreateDBAccount' ) ) {
 550              $tryToCreate = true;
 551          } else {
 552              $tryToCreate = false;
 553          }
 554  
 555          $escUser = $this->db->addIdentifierQuotes( $dbUser );
 556          $escDb = $this->db->addIdentifierQuotes( $dbName );
 557          $escSchema = $this->db->addIdentifierQuotes( $schemaName );
 558          $grantableNames = array();
 559          if ( $tryToCreate ) {
 560              $escPass = $this->db->addQuotes( $password );
 561  
 562              if ( !$this->loginExists( $dbUser ) ) {
 563                  try {
 564                      $this->db->begin();
 565                      $this->db->selectDB( 'master' );
 566                      $logintype = $this->getVar( '_WebWindowsAuthentication' ) == 'windowsauth'
 567                          ? 'FROM WINDOWS'
 568                          : "WITH PASSWORD = $escPass";
 569                      $this->db->query( "CREATE LOGIN $escUser $logintype" );
 570                      $this->db->selectDB( $dbName );
 571                      $this->db->query( "CREATE USER $escUser FOR LOGIN $escUser WITH DEFAULT_SCHEMA = $escSchema" );
 572                      $this->db->commit();
 573                      $grantableNames[] = $dbUser;
 574                  } catch ( DBQueryError $dqe ) {
 575                      $this->db->rollback();
 576                      $status->warning( 'config-install-user-create-failed', $dbUser, $dqe->getText() );
 577                  }
 578              } elseif ( !$this->userExists( $dbUser ) ) {
 579                  try {
 580                      $this->db->begin();
 581                      $this->db->selectDB( $dbName );
 582                      $this->db->query( "CREATE USER $escUser FOR LOGIN $escUser WITH DEFAULT_SCHEMA = $escSchema" );
 583                      $this->db->commit();
 584                      $grantableNames[] = $dbUser;
 585                  } catch ( DBQueryError $dqe ) {
 586                      $this->db->rollback();
 587                      $status->warning( 'config-install-user-create-failed', $dbUser, $dqe->getText() );
 588                  }
 589              } else {
 590                  $status->warning( 'config-install-user-alreadyexists', $dbUser );
 591                  $grantableNames[] = $dbUser;
 592              }
 593          }
 594  
 595          // Try to grant to all the users we know exist or we were able to create
 596          $this->db->selectDB( $dbName );
 597          foreach ( $grantableNames as $name ) {
 598              try {
 599                  // First try to grant full permissions
 600                  $fullPrivArr = array(
 601                      'BACKUP DATABASE', 'BACKUP LOG', 'CREATE FUNCTION', 'CREATE PROCEDURE',
 602                      'CREATE TABLE', 'CREATE VIEW', 'CREATE FULLTEXT CATALOG', 'SHOWPLAN'
 603                  );
 604                  $fullPrivList = implode( ', ', $fullPrivArr );
 605                  $this->db->begin();
 606                  $this->db->query( "GRANT $fullPrivList ON DATABASE :: $escDb TO $escUser", __METHOD__ );
 607                  $this->db->query( "GRANT CONTROL ON SCHEMA :: $escSchema TO $escUser", __METHOD__ );
 608                  $this->db->commit();
 609              } catch ( DBQueryError $dqe ) {
 610                  // If that fails, try to grant the limited subset specified in $this->webUserPrivs
 611                  try {
 612                      $privList = implode( ', ', $this->webUserPrivs );
 613                      $this->db->rollback();
 614                      $this->db->begin();
 615                      $this->db->query( "GRANT $privList ON SCHEMA :: $escSchema TO $escUser", __METHOD__ );
 616                      $this->db->commit();
 617                  } catch ( DBQueryError $dqe ) {
 618                      $this->db->rollback();
 619                      $status->fatal( 'config-install-user-grant-failed', $dbUser, $dqe->getText() );
 620                  }
 621                  // Also try to grant SHOWPLAN on the db, but don't fail if we can't
 622                  // (just makes a couple things in mediawiki run slower since
 623                  // we have to run SELECT COUNT(*) instead of getting the query plan)
 624                  try {
 625                      $this->db->query( "GRANT SHOWPLAN ON DATABASE :: $escDb TO $escUser", __METHOD__ );
 626                  } catch ( DBQueryError $dqe ) {
 627                  }
 628              }
 629          }
 630  
 631          return $status;
 632      }
 633  
 634  	public function createTables() {
 635          $status = parent::createTables();
 636  
 637          // Do last-minute stuff like fulltext indexes (since they can't be inside a transaction)
 638          if ( $status->isOk() ) {
 639              $searchindex = $this->db->tableName( 'searchindex' );
 640              $schema = $this->db->addIdentifierQuotes( $this->getVar( 'wgDBmwschema' ) );
 641              try {
 642                  $this->db->query( "CREATE FULLTEXT INDEX ON $searchindex (si_title, si_text) "
 643                      . "KEY INDEX si_page ON $schema" );
 644              } catch ( DBQueryError $dqe ) {
 645                  $status->fatal( 'config-install-tables-failed', $dqe->getText() );
 646              }
 647          }
 648  
 649          return $status;
 650      }
 651  
 652  	public function getGlobalDefaults() {
 653          // The default $wgDBmwschema is null, which breaks Postgres and other DBMSes that require
 654          // the use of a schema, so we need to set it here
 655          return array(
 656              'wgDBmwschema' => 'mediawiki',
 657          );
 658      }
 659  
 660      /**
 661       * Try to see if the login exists
 662       * @param string $user Username to check
 663       * @return bool
 664       */
 665  	private function loginExists( $user ) {
 666          $res = $this->db->selectField( 'sys.sql_logins', 1, array( 'name' => $user ) );
 667          return (bool)$res;
 668      }
 669  
 670      /**
 671       * Try to see if the user account exists
 672       * We assume we already have the appropriate database selected
 673       * @param string $user Username to check
 674       * @return bool
 675       */
 676  	private function userExists( $user ) {
 677          $res = $this->db->selectField( 'sys.sysusers', 1, array( 'name' => $user ) );
 678          return (bool)$res;
 679      }
 680  
 681      /**
 682       * Try to see if a given database exists
 683       * @param string $dbName Database name to check
 684       * @return bool
 685       */
 686  	private function databaseExists( $dbName ) {
 687          $res = $this->db->selectField( 'sys.databases', 1, array( 'name' => $dbName ) );
 688          return (bool)$res;
 689      }
 690  
 691      /**
 692       * Try to see if a given schema exists
 693       * We assume we already have the appropriate database selected
 694       * @param string $schemaName Schema name to check
 695       * @return bool
 696       */
 697  	private function schemaExists( $schemaName ) {
 698          $res = $this->db->selectField( 'sys.schemas', 1, array( 'name' => $schemaName ) );
 699          return (bool)$res;
 700      }
 701  
 702      /**
 703       * Try to see if a given fulltext catalog exists
 704       * We assume we already have the appropriate database selected
 705       * @param string $catalogName Catalog name to check
 706       * @return bool
 707       */
 708  	private function catalogExists( $catalogName ) {
 709          $res = $this->db->selectField( 'sys.fulltext_catalogs', 1, array( 'name' => $catalogName ) );
 710          return (bool)$res;
 711      }
 712  
 713      /**
 714       * Get variables to substitute into tables.sql and the SQL patch files.
 715       *
 716       * @return array
 717       */
 718  	public function getSchemaVars() {
 719          return array(
 720              'wgDBname' => $this->getVar( 'wgDBname' ),
 721              'wgDBmwschema' => $this->getVar( 'wgDBmwschema' ),
 722              'wgDBuser' => $this->getVar( 'wgDBuser' ),
 723              'wgDBpassword' => $this->getVar( 'wgDBpassword' ),
 724          );
 725      }
 726  
 727  	public function getLocalSettings() {
 728          $schema = LocalSettingsGenerator::escapePhpString( $this->getVar( 'wgDBmwschema' ) );
 729          $prefix = LocalSettingsGenerator::escapePhpString( $this->getVar( 'wgDBprefix' ) );
 730          $windowsauth = $this->getVar( 'wgDBWindowsAuthentication' ) ? 'true' : 'false';
 731  
 732          return "# MSSQL specific settings
 733  \$wgDBWindowsAuthentication = {$windowsauth};
 734  \$wgDBmwschema = \"{$schema}\";
 735  \$wgDBprefix = \"{$prefix}\";";
 736      }
 737  }


Generated: Fri Nov 28 14:03:12 2014 Cross-referenced by PHPXref 0.7.1