You are here

sqlsrv.install in Drupal driver for SQL Server and SQL Azure 8.2

Installation file for sqlsrv module.

File

sqlsrv.install
View source
<?php

/**
 * @file
 * Installation file for sqlsrv module.
 */
use Drupal\Core\Database\Database;
use Drupal\Driver\Database\sqlsrv\Connection;
use Drupal\sqlsrv\Indexes\IndexManager;
use Drupal\Driver\Database\sqlsrv\Install\Tasks as MssqlInstallTasks;

/**
 * Implements hook_uninstall().
 *
 * Remove cache directory if module is uninstalled.
 */
function sqlsrv_uninstall() {
}

/**
 * Implements hook_requirements().
 *
 * @status: Needs global revision.
 */
function sqlsrv_requirements($phase) {
  $requirements = array();
  if ($phase == 'runtime') {

    /** @var Connection $connection */
    $connection = Database::getConnection();

    // Nothing to do if we are not running on MSSQL.
    if ($connection
      ->driver() !== 'sqlsrv') {
      $requirements['sqlsrv_unused'] = array(
        'title' => t('MSSQL Server'),
        'severity' => REQUIREMENT_WARNING,
        'description' => 'Driver module enabled but driver not used.',
        'value' => t('The MSSQL driver module is enabled, but it looks like you are not using the MSSQL database engine driver. Please, disable the MSSQL module.'),
      );
      return $requirements;
    }
    $options = $connection
      ->getConnectionOptions();
    $schema = $connection
      ->schema();
    $version = $connection
      ->Scheme()
      ->EngineVersion();
    $database = $connection
      ->getDatabaseName();
    $requirements = MssqlInstallTasks::InstallRequirements();

    // Report information about the driver....
    $uinfo = $connection
      ->Scheme()
      ->UserOptions()
      ->getSettings();
    if (method_exists($connection
      ->Scheme(), 'getDriverAttributes')) {
      $attrs = $connection
        ->Scheme()
        ->getDriverAttributes();
      $uinfo = array_merge($uinfo, $attrs
        ->getAll());
    }
    $uinfo_parts = array_map(function ($a, $b) {
      return "{$a}={$b}";
    }, array_keys($uinfo), $uinfo);
    $requirements['sqlsrv_edition'] = array(
      'title' => t('MSSQL Server'),
      'severity' => REQUIREMENT_INFO,
      'description' => implode(' | ', $uinfo_parts),
      'value' => t('@version @level @ @edition', array(
        '@version' => $version
          ->Version(),
        '@level' => $version
          ->Level(),
        '@edition' => $version
          ->Edition(),
      )),
    );

    // Report database name and size.
    $size = $connection
      ->Scheme()
      ->getSizeInfo($database);
    $size_db = format_size($size->RowSizeMB * 1024 * 1024);
    $table_count = $size->TableCount;
    $requirements['sqlsrv_database'] = array(
      'title' => t('MSSQL Server Database'),
      'severity' => REQUIREMENT_OK,
      'value' => "{$options['driver']}://{$options['host']}:{$options['port']}/{$options['database']} ({$size_db}, {$table_count} tables)",
    );

    // Wincache module availability.
    $wincache_module = \Drupal::moduleHandler()
      ->moduleExists('wincachedrupal');
    $requirements['sqlsrv_wincache_extension'] = array(
      'title' => t('MSSQL Server Wincache module'),
      'value' => $wincache_module ? phpversion('wincache') : t('Not available'),
      'severity' => $wincache_module ? REQUIREMENT_OK : REQUIREMENT_ERROR,
      'description' => $wincache_module ? NULL : t('Enabling wincache integration can greatly improve system performance. See <a href="https://www.drupal.org/project/wincachedrupal/">Wincache Drupal</a> for more details.'),
    );

    // Report encoding for database.
    $collation = $connection
      ->Scheme()
      ->getCollation($database, $connection
      ->schema()
      ->GetDefaultSchema());
    $case_insensitive = stripos($collation, '_CI') !== FALSE;
    $requirements['sqlsrv_encoding_database'] = array(
      'title' => t('MSSQL Server Database encoding'),
      'severity' => $case_insensitive ? REQUIREMENT_OK : REQUIREMENT_ERROR,
      'description' => $case_insensitive ? t('Default case insensitive collation found.') : t('Drupal needs a default case insensitive collation database to run on.'),
      'value' => t('@collation', array(
        '@collation' => $collation,
      )),
    );

    // TODO: Report install function availability (SUBSTRING, CONCAT, IF, MD5, etc...)
    $functions = $schema
      ->DrupalSpecificFunctions();
    $briefing = array();
    $error = FALSE;
    foreach ($functions as $function) {
      $exists = $connection
        ->Scheme()
        ->functionExists($function);
      $error = $exists === FALSE ? TRUE : $error;
      $briefing[] = $function . ':' . ($exists === TRUE ? 'YES' : 'NO');
    }
    $exists = $connection
      ->Scheme()
      ->CLREnabled();
    $error = $exists === FALSE ? TRUE : $error;
    $briefing[] = 'CLREnabled' . ':' . ($exists === TRUE ? 'YES' : 'NO');
    $requirements['sqlsrv_custom_functions'] = array(
      'title' => t('MSSQL Server Custom Functions'),
      'description' => $error === TRUE ? t('Some custom functions are not available. Make sure you deploy them.') : t('All custom functions available.'),
      'severity' => $error === TRUE ? REQUIREMENT_WARNING : REQUIREMENT_OK,
      'value' => implode(' | ', $briefing),
    );

    // TODO:// Move this to a better place!
    $path = dirname(__FILE__) . '/src/Indexes/Implementations';
    $manager = new IndexManager($connection, $path);
    $manager
      ->DeployNew();

    // Make sure that the module's driver code is the same one as the effectively
    // deployed driver code....
    // TODO:// Nicer than just showing the error,
    // would be to offer the option to autodploy the driver...

    //if ($connection->driver_settings->GetMonitorDriverStatus()){

    //  $deployed_ok = sqlsrv_verify_driver();
    //  $requirements['sqlsrv_deployed_files'] = array(
    //    'title' => t('MSSQL Server Deployed Driver'),
    //    'description' => t('Deployed driver match.'),
    //    'severity' => $deployed_ok === TRUE ? REQUIREMENT_OK : REQUIREMENT_ERROR,
    //    'description' => $deployed_ok === TRUE ? t('Deployed driver matches module version.') : t('The deployed driver files do not match the module driver.'),
    //    );

    //}
  }
  return $requirements;
}

/**
 * Verify that the deployed driver is the same one as the module
 * version.
 *
 * @return bool
 */
function sqlsrv_verify_driver() {

  // Location of the effective driver.
  $class = Connection::class;
  $reflector = new ReflectionClass($class);
  $driver_dir = dirname($reflector
    ->getFileName());

  // Location for the module's driver.
  $module_dir = dirname(__FILE__) . DIRECTORY_SEPARATOR . implode(DIRECTORY_SEPARATOR, array(
    'drivers',
    'lib',
    'drupal',
    'driver',
    'database',
    'sqlsrv',
  ));
  return sqlsrv_directory_checksum($driver_dir) === sqlsrv_directory_checksum($module_dir);
}

/**
 * Calculate a unique identifier for a directory and it's contents
 * based on file sizes and names.
 *
 * TODO:// This thing will not notice files being moved around in directories
 * as long as they keep same name and size.
 *
 * @param string $directory
 * @return string
 */
function sqlsrv_directory_checksum($directory) {
  $files = file_scan_directory($directory, '/\\.*/i');
  $checksum = 0;
  $names = '';
  foreach ($files as $file) {
    $checksum += filesize($file->uri);
    $names .= $file->name;
  }
  return $checksum . '-' . md5($names);
}

Functions

Namesort descending Description
sqlsrv_directory_checksum Calculate a unique identifier for a directory and it's contents based on file sizes and names.
sqlsrv_requirements Implements hook_requirements().
sqlsrv_uninstall Implements hook_uninstall().
sqlsrv_verify_driver Verify that the deployed driver is the same one as the module version.