sqlsrv.install in Drupal driver for SQL Server and SQL Azure 3.0.x
Same filename and directory in other branches
Installation file for sqlsrv module.
File
sqlsrv.installView source
<?php
/**
* @file
* Installation file for sqlsrv module.
*/
use Drupal\Core\Database\Database;
use Drupal\Driver\Database\sqlsrv\Connection;
use Drupal\Driver\Database\sqlsrv\Utils;
/**
* Implements hook_uninstall().
*
* Remove cache directory if module is uninstalled.
*/
/**
* Implements hook_requirements().
*/
function sqlsrv_requirements($phase) {
$requirements = [];
if ($phase == 'runtime') {
/** @var \Drupal\Driver\Database\sqlsrv\Connection $connection */
$connection = Database::getConnection();
// Nothing to do if we are not running on MSSQL.
if ($connection
->driver() !== 'sqlsrv') {
return [];
}
$options = $connection
->getConnectionOptions();
/** @var \Drupal\Driver\Database\sqlsrv\Schema $schema */
$schema = $connection
->schema();
$collation = $schema
->getCollation();
$version = $schema
->EngineVersion();
$extensiondata = sqlsrv_extension_data('pdo_sqlsrv');
// Report database engine version.
$uinfo = $schema
->UserOptions();
$inline_function = function ($a, $b) {
$a = strtoupper($a);
$b = strtoupper($b);
return "{$a}={$b}";
};
$uinfo_parts = array_map($inline_function, array_keys($uinfo), $uinfo);
$arguments = [
'@version' => $version['VERSION'],
'@level' => $version['LEVEL'],
'@edition' => $version['EDITION'],
'@name' => $options['database'],
];
$requirements['sqlsrv_edition'] = [
'title' => t('MSSQL Server'),
'severity' => REQUIREMENT_INFO,
'description' => implode(' | ', $uinfo_parts),
'value' => t('@version @level @ @edition | @name', $arguments),
];
// Report database name and size.
$size = $schema
->getSizeInfo();
$size_db = format_size($size->RowSizeMB * 1024 * 1024);
$requirements['sqlsrv_database'] = [
'title' => t('MSSQL Server Database'),
'severity' => REQUIREMENT_OK,
'value' => "{$options['database']} ({$size_db})",
];
// Make sure enough size is set for buffered queries.
$buffer_size = $extensiondata['getINIEntries']['pdo_sqlsrv.client_buffer_max_kb_size'];
$buffer_size_min = 12240 * 2;
$buffer_size_ok = $buffer_size >= $buffer_size_min;
$requirements['sqlsrv_client_buffer_size'] = [
'title' => t('MSSQL Server client buffer size'),
'severity' => $buffer_size_ok ? REQUIREMENT_OK : REQUIREMENT_WARNING,
'value' => "{$buffer_size} Kb",
'description' => "pdo_sqlsrv.client_buffer_max_kb_size setting must be of at least {$buffer_size_min}Kb. Currently {$buffer_size}Kb.",
];
// Is this a windows server?
$is_windows = strncasecmp(PHP_OS, 'WIN', 3) == 0;
if ($is_windows) {
$wincache_module = \Drupal::moduleHandler()
->moduleExists('wincachedrupal');
$requirements['sqlsrv_wincache_extension'] = [
'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 = $schema
->getCollation();
$case_insensitive = stripos($collation, '_CI') !== FALSE;
$requirements['sqlsrv_encoding_database'] = [
'title' => t('MSSQL Server Database encoding'),
'severity' => $case_insensitive ? REQUIREMENT_OK : REQUIREMENT_ERROR,
'description' => $case_insensitive ? NULL : t('Drupal needs a default case insensitive collation database to run on.'),
'value' => t('@collation', [
'@collation' => $collation,
]),
];
// Report PDO version, and require at lest 5.8.0 version.
$version_ok = version_compare($extensiondata['getVersion'], '5.8') >= 0;
$requirements['sqlsrv_pdo'] = [
'title' => t('MSSQL Server PDO extension'),
'severity' => $version_ok ? REQUIREMENT_OK : REQUIREMENT_ERROR,
'value' => t('@level', [
'@level' => $extensiondata['getVersion'],
]),
'description' => t('Use at least the 5.8.0 version of the MSSQL PDO driver.'),
];
// TODO: Report install function availability
// (SUBSTRING, CONCAT, IF, MD5, etc...)
$functions = $schema
->DrupalSpecificFunctions();
$briefing = [];
$error = FALSE;
foreach ($functions as $function) {
$exists = $schema
->functionExists($function);
$error = $exists === FALSE ? TRUE : $error;
$briefing[] = $function . ':' . ($exists === TRUE ? 'YES' : 'NO');
}
$exists = $schema
->CLREnabled();
$error = $exists === FALSE ? TRUE : $error;
$briefing[] = 'CLREnabled:' . ($exists === TRUE ? 'YES' : 'NO');
$requirements['sqlsrv_custom_functions'] = [
'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_ERROR : REQUIREMENT_OK,
'value' => implode(' | ', $briefing),
];
// Redeploy functions.
Utils::DeployCustomFunctions($connection);
// 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...
$deployed_ok = sqlsrv_verify_driver();
$requirements['sqlsrv_deployed_files'] = [
'title' => t('MSSQL Server Deployed Driver'),
'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 Deployed Driver.
*
* Verify that the deployed driver is the same one as the module
* version.
*
* @return bool
* Drivers match.
*/
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.
$path_array = [
'drivers',
'lib',
'drupal',
'driver',
'database',
'sqlsrv',
];
$module_dir = dirname(__FILE__) . DIRECTORY_SEPARATOR . implode(DIRECTORY_SEPARATOR, $path_array);
return sqlsrv_directory_checksum($driver_dir) === sqlsrv_directory_checksum($module_dir);
}
/**
* Directory Checksum.
*
* 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
* Directory.
*
* @return string
* Checksum.
*/
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);
}
/**
* Get some info about extensions...
*
* @param mixed $name
* Extension name.
*
* @return array
* Extension information.
*/
function sqlsrv_extension_data($name) {
$re = new \ReflectionExtension($name);
$_data = [];
$_data['getName'] = $re
->getName() ?: NULL;
$_data['getVersion'] = $re
->getVersion() ?: NULL;
$_data['getClassName'] = PHP_EOL . implode(", ", $re
->getClassNames()) ?: NULL;
foreach ($re
->getConstants() as $key => $value) {
$_data['getConstants'] .= "\n{$key}:={$value}";
}
$_data['getDependencies'] = $re
->getDependencies() ?: NULL;
$_data['getFunctions'] = PHP_EOL . implode(", ", array_keys($re
->getFunctions())) ?: NULL;
$_data['getINIEntries'] = $re
->getINIEntries() ?: NULL;
return $_data;
}
Functions
Name | Description |
---|---|
sqlsrv_directory_checksum | Directory Checksum. |
sqlsrv_extension_data | Get some info about extensions... |
sqlsrv_requirements | Implements hook_requirements(). |
sqlsrv_verify_driver | Verify Deployed Driver. |