Merge pull request #6167 from open-sausages/pulls/4.0/fix-installer

BUG Fix installer for 4.0
This commit is contained in:
Ingo Schommer 2016-10-21 14:09:38 +13:00 committed by GitHub
commit 423fc060e5
5 changed files with 176 additions and 90 deletions

View File

@ -2,6 +2,8 @@
namespace SilverStripe\Dev\Install; namespace SilverStripe\Dev\Install;
use InvalidArgumentException;
/** /**
* This class keeps track of the available database adapters * This class keeps track of the available database adapters
* and provides a meaning of registering community built * and provides a meaning of registering community built
@ -51,25 +53,46 @@ class DatabaseAdapterRegistry {
/** /**
* Add new adapter to the registry * Add new adapter to the registry
* *
* @param array $config Associative array of configuration details * @param array $config Associative array of configuration details. This must include:
* - title
* - class
* - helperClass
* - supported
* This SHOULD include:
* - fields
* - helperPath (if helperClass can't be autoloaded via psr-4/-0)
* - missingExtensionText
* - module OR missingModuleText
*/ */
public static function register($config) { public static function register($config) {
$missingExtensionText = isset($config['missingExtensionText']) // Validate config
? $config['missingExtensionText'] $missing = array_diff(['title', 'class', 'helperClass', 'supported'], array_keys($config));
: 'The PHP extension is missing, please enable or install it.'; if($missing) {
throw new InvalidArgumentException(
"Missing database helper config keys: '" . implode("', '", $missing) . "'"
);
}
$path = explode('/', $config['helperPath']); // Guess missing module text if not given
$moduleName = array_shift($path); if (empty($config['missingModuleText'])) {
$missingModuleText = isset($config['missingModuleText']) if (empty($config['module'])) {
? $config['missingModuleText'] $moduleText = 'Module for database connector ' . $config['title'] . 'is missing.';
: 'The SilverStripe module, '.$moduleName.', is missing or incomplete.' } else {
. ' Please <a href="http://silverstripe.org/modules">download it</a>.'; $moduleText = "The SilverStripe module '" . $config['module'] . "' is missing.";
}
$config['missingModuleText'] = $moduleText
. ' Please install it via composer or from http://addons.silverstripe.org/.';
}
$config['missingModuleText'] = $missingModuleText; // Set missing text
$config['missingExtensionText'] = $missingExtensionText; if (empty($config['missingExtensionText'])) {
$config['missingExtensionText'] = 'The PHP extension is missing, please enable or install it.';
}
// set default fields if none are defined already // set default fields if none are defined already
if(!isset($config['fields'])) $config['fields'] = self::$default_fields; if(!isset($config['fields'])) {
$config['fields'] = self::$default_fields;
}
self::$adapters[$config['class']] = $config; self::$adapters[$config['class']] = $config;
} }
@ -137,4 +160,26 @@ class DatabaseAdapterRegistry {
return self::$default_fields; return self::$default_fields;
} }
/**
* Build configuration helper for a given class
*
* @param string $databaseClass Name of class
* @return DatabaseConfigurationHelper|null Instance of helper, or null if cannot be loaded
*/
public static function getDatabaseConfigurationHelper($databaseClass) {
$adapters = static::get_adapters();
if(empty($adapters[$databaseClass]) || empty($adapters[$databaseClass]['helperClass'])) {
return null;
}
// Load if path given
if (isset($adapters[$databaseClass]['helperPath'])) {
include_once $adapters[$databaseClass]['helperPath'];
}
// Construct
$class = $adapters[$databaseClass]['helperClass'];
return (class_exists($class)) ? new $class() : null;
}
} }

View File

@ -18,6 +18,7 @@ class MySQLDatabaseConfigurationHelper implements DatabaseConfigurationHelper {
/** /**
* Create a connection of the appropriate type * Create a connection of the appropriate type
* *
* @skipUpgrade
* @param array $databaseConfig * @param array $databaseConfig
* @param string $error Error message passed by value * @param string $error Error message passed by value
* @return mixed|null Either the connection object, or null if error * @return mixed|null Either the connection object, or null if error
@ -26,7 +27,7 @@ class MySQLDatabaseConfigurationHelper implements DatabaseConfigurationHelper {
$error = null; $error = null;
try { try {
switch($databaseConfig['type']) { switch($databaseConfig['type']) {
case 'SilverStripe\\ORM\\Connect\\MySQLDatabase': case 'MySQLDatabase':
$conn = @new MySQLi($databaseConfig['server'], $databaseConfig['username'], $conn = @new MySQLi($databaseConfig['server'], $databaseConfig['username'],
$databaseConfig['password']); $databaseConfig['password']);
if($conn && empty($conn->connect_errno)) { if($conn && empty($conn->connect_errno)) {
@ -50,7 +51,7 @@ class MySQLDatabaseConfigurationHelper implements DatabaseConfigurationHelper {
return null; return null;
} }
default: default:
$error = 'Invalid connection type'; $error = 'Invalid connection type: ' . $databaseConfig['type'];
return null; return null;
} }
} catch(Exception $ex) { } catch(Exception $ex) {

View File

@ -6,7 +6,7 @@
<head> <head>
<title>SilverStripe CMS / Framework Installation</title> <title>SilverStripe CMS / Framework Installation</title>
<meta http-equiv="Content-type" content="text/html; charset=utf-8"> <meta http-equiv="Content-type" content="text/html; charset=utf-8">
<script type="application/javascript" src="<?php echo FRAMEWORK_NAME; ?>/thirdparty/jquery/jquery.js"></script> <script type="application/javascript" src="http://code.jquery.com/jquery-1.7.2.min.js"></script>
<script type="application/javascript" src="<?php echo FRAMEWORK_NAME; ?>/Dev/Install/client/dist/js/install.js"></script> <script type="application/javascript" src="<?php echo FRAMEWORK_NAME; ?>/Dev/Install/client/dist/js/install.js"></script>
<link rel="stylesheet" type="text/css" href="<?php echo FRAMEWORK_NAME; ?>/Dev/Install/client/dist/styles/install.css"> <link rel="stylesheet" type="text/css" href="<?php echo FRAMEWORK_NAME; ?>/Dev/Install/client/dist/styles/install.css">
<link rel="shortcut icon" href="favicon.ico"> <link rel="shortcut icon" href="favicon.ico">

View File

@ -8,7 +8,13 @@
** ** ** **
************************************************************************************ ************************************************************************************
************************************************************************************/ ************************************************************************************/
use SilverStripe\Control\Controller;
use SilverStripe\Core\Startup\ParameterConfirmationToken;
use SilverStripe\Dev\Install\DatabaseAdapterRegistry; use SilverStripe\Dev\Install\DatabaseAdapterRegistry;
use SilverStripe\Dev\Install\DatabaseConfigurationHelper;
use SilverStripe\ORM\DatabaseAdmin;
use SilverStripe\ORM\DB;
use SilverStripe\Security\Security;
/** /**
* SilverStripe CMS Installer * SilverStripe CMS Installer
@ -116,14 +122,10 @@ $locales = array(
DatabaseAdapterRegistry::autodiscover(); DatabaseAdapterRegistry::autodiscover();
// Determine which external database modules are USABLE // Determine which external database modules are USABLE
foreach(DatabaseAdapterRegistry::get_adapters() as $class => $details) { $databaseClasses = DatabaseAdapterRegistry::get_adapters();
$databaseClasses[$class] = $details; foreach($databaseClasses as $class => $details) {
if(file_exists($details['helperPath'])) { $helper = DatabaseAdapterRegistry::getDatabaseConfigurationHelper($class);
$databaseClasses[$class]['hasModule'] = true; $databaseClasses[$class]['hasModule'] = !empty($helper);
include_once($details['helperPath']);
} else {
$databaseClasses[$class]['hasModule'] = false;
}
} }
// Load database config // Load database config
@ -182,7 +184,9 @@ if(file_exists('mysite/_config.php')) {
// Find the $database variable in the relevant config file without having to execute the config file // Find the $database variable in the relevant config file without having to execute the config file
if(preg_match("/\\\$database\s*=\s*[^\n\r]+[\n\r]/", file_get_contents("mysite/_config.php"), $parts)) { if(preg_match("/\\\$database\s*=\s*[^\n\r]+[\n\r]/", file_get_contents("mysite/_config.php"), $parts)) {
eval($parts[0]); eval($parts[0]);
if($database) $alreadyInstalled = true; if(!empty($database)) {
$alreadyInstalled = true;
}
// Assume that if $databaseConfig is defined in mysite/_config.php, then a non-environment-based installation has // Assume that if $databaseConfig is defined in mysite/_config.php, then a non-environment-based installation has
// already gone ahead // already gone ahead
} else if(preg_match("/\\\$databaseConfig\s*=\s*[^\n\r]+[\n\r]/", file_get_contents("mysite/_config.php"), $parts)) { } else if(preg_match("/\\\$databaseConfig\s*=\s*[^\n\r]+[\n\r]/", file_get_contents("mysite/_config.php"), $parts)) {
@ -290,7 +294,9 @@ class InstallRequirements {
array( array(
"Database Configuration", "Database Configuration",
"Database server", "Database server",
$usePath ? "I couldn't write to path '$databaseConfig[path]'" : "I couldn't find a database server on '$databaseConfig[server]'", $usePath
? "I couldn't write to path '$databaseConfig[path]'"
: "I couldn't find a database server on '$databaseConfig[server]'",
$usePath ? $databaseConfig['path'] : $databaseConfig['server'] $usePath ? $databaseConfig['path'] : $databaseConfig['server']
) )
)) return false; )) return false;
@ -351,7 +357,9 @@ class InstallRequirements {
/** /**
* Check if the web server is IIS and version greater than the given version. * Check if the web server is IIS and version greater than the given version.
* @return boolean *
* @param int $fromVersion
* @return bool
*/ */
public function isIIS($fromVersion = 7) { public function isIIS($fromVersion = 7) {
if(strpos($this->findWebserver(), 'IIS/') === false) { if(strpos($this->findWebserver(), 'IIS/') === false) {
@ -656,8 +664,7 @@ class InstallRequirements {
} }
if(!in_array($val, $settingValues) && $val != $settingValues) { if(!in_array($val, $settingValues) && $val != $settingValues) {
$testDetails[2] = "$settingName is set to '$val' in php.ini. $testDetails[2]"; $this->warning($testDetails, "$settingName is set to '$val' in php.ini. $testDetails[2]");
$this->warning($testDetails);
} }
} }
@ -666,8 +673,7 @@ class InstallRequirements {
$val = ini_get($settingName); $val = ini_get($settingName);
if(!in_array($val, $settingValues) && $val != $settingValues) { if(!in_array($val, $settingValues) && $val != $settingValues) {
$testDetails[2] = "$settingName is set to '$val' in php.ini. $testDetails[2]"; $this->error($testDetails, "$settingName is set to '$val' in php.ini. $testDetails[2]");
$this->error($testDetails);
} }
} }
@ -709,16 +715,20 @@ class InstallRequirements {
$this->testing($testDetails); $this->testing($testDetails);
if($mem < $min && $mem > 0) { if($mem < $min && $mem > 0) {
$testDetails[2] .= " You only have " . ini_get("memory_limit") . " allocated"; $message = $testDetails[2] . " You only have " . ini_get("memory_limit") . " allocated";
$this->error($testDetails); $this->error($testDetails, $message);
return false;
} else if($mem < $recommended && $mem > 0) { } else if($mem < $recommended && $mem > 0) {
$testDetails[2] .= " You only have " . ini_get("memory_limit") . " allocated"; $message = $testDetails[2] . " You only have " . ini_get("memory_limit") . " allocated";
$this->warning($testDetails); $this->warning($testDetails, $message);
return false;
} elseif($mem == 0) { } elseif($mem == 0) {
$testDetails[2] .= " We can't determine how much memory you have allocated. " $message = $testDetails[2] . " We can't determine how much memory you have allocated. "
. "Install only if you're sure you've allocated at least 20 MB."; . "Install only if you're sure you've allocated at least 20 MB.";
$this->warning($testDetails); $this->warning($testDetails, $message);
return false;
} }
return true;
} }
public function getPHPMemory() { public function getPHPMemory() {
@ -807,35 +817,41 @@ class InstallRequirements {
if(!function_exists($funcName)) { if(!function_exists($funcName)) {
$this->error($testDetails); $this->error($testDetails);
} else { return false;
return true;
} }
return true;
} }
public function requireClass($className, $testDetails) { public function requireClass($className, $testDetails) {
$this->testing($testDetails); $this->testing($testDetails);
if(!class_exists($className)) { if(!class_exists($className)) {
$this->error($testDetails); $this->error($testDetails);
} else {
return false; return false;
} }
return true;
} }
/** /**
* Require that the given class doesn't exist * Require that the given class doesn't exist
*
* @param array $classNames
* @param array $testDetails
* @return bool
*/ */
public function requireNoClasses($classNames, $testDetails) { public function requireNoClasses($classNames, $testDetails) {
$this->testing($testDetails); $this->testing($testDetails);
$badClasses = array(); $badClasses = array();
foreach($classNames as $className) { foreach($classNames as $className) {
if(class_exists($className)) $badClasses[] = $className; if(class_exists($className)) {
$badClasses[] = $className;
}
} }
if($badClasses) { if($badClasses) {
$testDetails[2] .= ". The following classes are at fault: " . implode(', ', $badClasses); $message = $testDetails[2] . ". The following classes are at fault: " . implode(', ', $badClasses);
$this->error($testDetails); $this->error($testDetails, $message);
} else { return false;
return true;
} }
return true;
} }
public function checkApacheVersion($testDetails) { public function checkApacheVersion($testDetails) {
@ -855,20 +871,20 @@ class InstallRequirements {
$installedVersion = phpversion(); $installedVersion = phpversion();
if(version_compare($installedVersion, $requiredVersion, '<')) { if(version_compare($installedVersion, $requiredVersion, '<')) {
$testDetails[2] = "SilverStripe requires PHP version $requiredVersion or later.\n $message = "SilverStripe requires PHP version $requiredVersion or later.\n
PHP version $installedVersion is currently installed.\n PHP version $installedVersion is currently installed.\n
While SilverStripe requires at least PHP version $requiredVersion, upgrading to $recommendedVersion or later is recommended.\n While SilverStripe requires at least PHP version $requiredVersion, upgrading to $recommendedVersion or later is recommended.\n
If you are installing SilverStripe on a shared web server, please ask your web hosting provider to upgrade PHP for you."; If you are installing SilverStripe on a shared web server, please ask your web hosting provider to upgrade PHP for you.";
$this->error($testDetails); $this->error($testDetails, $message);
return; return false;
} }
if(version_compare($installedVersion, $recommendedVersion, '<')) { if(version_compare($installedVersion, $recommendedVersion, '<')) {
$testDetails[2] = "PHP version $installedVersion is currently installed.\n $message = "PHP version $installedVersion is currently installed.\n
Upgrading to at least PHP version $recommendedVersion is recommended.\n Upgrading to at least PHP version $recommendedVersion is recommended.\n
SilverStripe should run, but you may run into issues. Future releases may require a later version of PHP.\n"; SilverStripe should run, but you may run into issues. Future releases may require a later version of PHP.\n";
$this->warning($testDetails); $this->warning($testDetails, $message);
return; return false;
} }
return true; return true;
@ -876,6 +892,9 @@ class InstallRequirements {
/** /**
* Check that a module exists * Check that a module exists
*
* @param string $dirname
* @return bool
*/ */
public function checkModuleExists($dirname) { public function checkModuleExists($dirname) {
$path = $this->getBaseDir() . $dirname; $path = $this->getBaseDir() . $dirname;
@ -885,6 +904,9 @@ class InstallRequirements {
/** /**
* The same as {@link requireFile()} but does additional checks * The same as {@link requireFile()} but does additional checks
* to ensure the module directory is intact. * to ensure the module directory is intact.
*
* @param string $dirname
* @param array $testDetails
*/ */
public function requireModule($dirname, $testDetails) { public function requireModule($dirname, $testDetails) {
$this->testing($testDetails); $this->testing($testDetails);
@ -1041,22 +1063,19 @@ class InstallRequirements {
/** /**
* Get an instance of a helper class for the specific database. * Get an instance of a helper class for the specific database.
*
* @param string $databaseClass e.g. MySQLDatabase or MSSQLDatabase * @param string $databaseClass e.g. MySQLDatabase or MSSQLDatabase
* @return DatabaseConfigurationHelper
*/ */
public function getDatabaseConfigurationHelper($databaseClass) { public function getDatabaseConfigurationHelper($databaseClass) {
$adapters = DatabaseAdapterRegistry::get_adapters(); return DatabaseAdapterRegistry::getDatabaseConfigurationHelper($databaseClass);
if(isset($adapters[$databaseClass])) {
$helperPath = $adapters[$databaseClass]['helperPath'];
$class = str_replace('.php', '', basename($helperPath));
}
return (class_exists($class)) ? new $class() : false;
} }
public function requireDatabaseFunctions($databaseConfig, $testDetails) { public function requireDatabaseFunctions($databaseConfig, $testDetails) {
$this->testing($testDetails); $this->testing($testDetails);
$helper = $this->getDatabaseConfigurationHelper($databaseConfig['type']); $helper = $this->getDatabaseConfigurationHelper($databaseConfig['type']);
if (!$helper) { if (!$helper) {
$this->error("Couldn't load database helper code for ". $databaseConfig['type']); $this->error($testDetails, "Couldn't load database helper code for ". $databaseConfig['type']);
return false; return false;
} }
$result = $helper->requireDatabaseFunctions($databaseConfig); $result = $helper->requireDatabaseFunctions($databaseConfig);
@ -1105,8 +1124,8 @@ class InstallRequirements {
if($result['success']) { if($result['success']) {
return true; return true;
} else { } else {
$testDetails[2] .= ": " . $result['error']; $message = $testDetails[2] . ": " . $result['error'];
$this->error($testDetails); $this->error($testDetails, $message);
return false; return false;
} }
} }
@ -1116,18 +1135,21 @@ class InstallRequirements {
$helper = $this->getDatabaseConfigurationHelper($databaseConfig['type']); $helper = $this->getDatabaseConfigurationHelper($databaseConfig['type']);
$result = $helper->requireDatabaseOrCreatePermissions($databaseConfig); $result = $helper->requireDatabaseOrCreatePermissions($databaseConfig);
if($result['success']) { if($result['success']) {
if($result['alreadyExists']) $testDetails[3] = "Database $databaseConfig[database]"; if($result['alreadyExists']) {
else $testDetails[3] = "Able to create a new database"; $testDetails[3] = "Database $databaseConfig[database]";
} else {
$testDetails[3] = "Able to create a new database";
}
$this->testing($testDetails); $this->testing($testDetails);
return true; return true;
} else { } else {
if(empty($result['cannotCreate'])) { if(empty($result['cannotCreate'])) {
$testDetails[2] .= ". Please create the database manually."; $message = $testDetails[2] . ". Please create the database manually.";
} else { } else {
$testDetails[2] .= " (user '$databaseConfig[username]' doesn't have CREATE DATABASE permissions.)"; $message = $testDetails[2] . " (user '$databaseConfig[username]' doesn't have CREATE DATABASE permissions.)";
} }
$this->error($testDetails); $this->error($testDetails, $message);
return false; return false;
} }
} }
@ -1139,10 +1161,10 @@ class InstallRequirements {
if ($result['success']) { if ($result['success']) {
return true; return true;
} else { } else {
$testDetails[2] = "Silverstripe cannot alter tables. This won't prevent installation, however it may " $message = "Silverstripe cannot alter tables. This won't prevent installation, however it may "
. "cause issues if you try to run a /dev/build once installed."; . "cause issues if you try to run a /dev/build once installed.";
$this->warning($testDetails); $this->warning($testDetails, $message);
return; return false;
} }
} }
@ -1158,10 +1180,11 @@ class InstallRequirements {
if(!$missing) { if(!$missing) {
return true; return true;
} else {
$testDetails[2] .= " (the following PHP variables are missing: " . implode(", ", $missing) . ")";
$this->error($testDetails);
} }
$message = $testDetails[2] . " (the following PHP variables are missing: " . implode(", ", $missing) . ")";
$this->error($testDetails, $message);
return false;
} }
@ -1209,19 +1232,31 @@ class InstallRequirements {
$this->tests[$section][$test] = array("good", $message); $this->tests[$section][$test] = array("good", $message);
} }
public function error($testDetails) { public function error($testDetails, $message = null) {
if (!is_array($testDetails)) {
throw new InvalidArgumentException("Invalid error");
}
$section = $testDetails[0]; $section = $testDetails[0];
$test = $testDetails[1]; $test = $testDetails[1];
if (!$message && isset($testDetails[2])) {
$message = $testDetails[2];
}
$this->tests[$section][$test] = array("error", isset($testDetails[2]) ? $testDetails[2] : null); $this->tests[$section][$test] = array("error", $message);
$this->errors[] = $testDetails; $this->errors[] = $testDetails;
} }
public function warning($testDetails) { public function warning($testDetails, $message = null) {
if (!is_array($testDetails)) {
throw new InvalidArgumentException("Invalid warning");
}
$section = $testDetails[0]; $section = $testDetails[0];
$test = $testDetails[1]; $test = $testDetails[1];
if (!$message && isset($testDetails[2])) {
$message = $testDetails[2];
}
$this->tests[$section][$test] = array("warning", isset($testDetails[2]) ? $testDetails[2] : null); $this->tests[$section][$test] = array("warning", $message);
$this->warnings[] = $testDetails; $this->warnings[] = $testDetails;
} }
@ -1345,9 +1380,6 @@ global \$database;
require_once('conf/ConfigureFromEnv.php'); require_once('conf/ConfigureFromEnv.php');
// Set the site locale
i18n::set_locale('$locale');
PHP PHP
); );
@ -1372,9 +1404,6 @@ global \$databaseConfig;
{$databaseConfigContent} {$databaseConfigContent}
); );
// Set the site locale
i18n::set_locale('$locale');
PHP PHP
); );
} }
@ -1390,8 +1419,12 @@ After:
# YAML configuration for SilverStripe # YAML configuration for SilverStripe
# See http://doc.silverstripe.org/framework/en/topics/configuration # See http://doc.silverstripe.org/framework/en/topics/configuration
# Caution: Indentation through two spaces, not tabs # Caution: Indentation through two spaces, not tabs
SSViewer: SilverStripe\\View\\SSViewer:
theme: '$theme' themes:
- '$theme'
- '\$default'
SilverStripe\\i18n\\i18n:
default_locale: '$locale'
YML YML
); );
@ -1399,6 +1432,8 @@ YML
$this->writeToFile("mysite/code/RootURLController.php", <<<PHP $this->writeToFile("mysite/code/RootURLController.php", <<<PHP
<?php <?php
use SilverStripe\\Control\\Controller;
class RootURLController extends Controller { class RootURLController extends Controller {
public function index() { public function index() {
@ -1442,7 +1477,7 @@ PHP
DB::connect($databaseConfig); DB::connect($databaseConfig);
$dbAdmin = new DatabaseAdmin(); $dbAdmin = new DatabaseAdmin();
$dbAdmin->init(); $dbAdmin->doInit();
$dbAdmin->doBuild(true); $dbAdmin->doBuild(true);
@ -1500,9 +1535,9 @@ HTML;
if((@$fh = fopen($base . $filename, 'wb')) && fwrite($fh, $content) && fclose($fh)) { if((@$fh = fopen($base . $filename, 'wb')) && fwrite($fh, $content) && fclose($fh)) {
return true; return true;
} else {
$this->error("Couldn't write to file $base$filename");
} }
$this->error("Couldn't write to file $base$filename");
return false;
} }
public function createHtaccess() { public function createHtaccess() {
@ -1684,6 +1719,8 @@ HTML;
/** /**
* Show an installation status message. * Show an installation status message.
* The output differs depending on whether this is CLI or web based * The output differs depending on whether this is CLI or web based
*
* @param string $msg
*/ */
public function statusMessage($msg) { public function statusMessage($msg) {
echo "<li>$msg</li>\n"; echo "<li>$msg</li>\n";

View File

@ -2,16 +2,17 @@
// Register the SilverStripe provided databases // Register the SilverStripe provided databases
use SilverStripe\Dev\Install\DatabaseAdapterRegistry; use SilverStripe\Dev\Install\DatabaseAdapterRegistry;
use SilverStripe\Dev\Install\MySQLDatabaseConfigurationHelper;
$frameworkPath = defined('FRAMEWORK_PATH') ? FRAMEWORK_PATH : FRAMEWORK_NAME;
// Use MySQLi as default // Use MySQLi as default
DatabaseAdapterRegistry::register( DatabaseAdapterRegistry::register(
array( array(
/** @skipUpgrade */ /** @skipUpgrade */
'class' => 'MySQLDatabase', 'class' => 'MySQLDatabase',
'module' => 'framework',
'title' => 'MySQL 5.0+ (using MySQLi)', 'title' => 'MySQL 5.0+ (using MySQLi)',
'helperPath' => $frameworkPath . '/dev/install/MySQLDatabaseConfigurationHelper.php', 'helperPath' => __DIR__ . '/dev/install/MySQLDatabaseConfigurationHelper.php',
'helperClass' => MySQLDatabaseConfigurationHelper::class,
'supported' => class_exists('MySQLi'), 'supported' => class_exists('MySQLi'),
'missingExtensionText' => 'missingExtensionText' =>
'The <a href="http://www.php.net/manual/en/book.mysqli.php">MySQLi</a> 'The <a href="http://www.php.net/manual/en/book.mysqli.php">MySQLi</a>
@ -24,8 +25,10 @@ DatabaseAdapterRegistry::register(
array( array(
/** @skipUpgrade */ /** @skipUpgrade */
'class' => 'MySQLPDODatabase', 'class' => 'MySQLPDODatabase',
'module' => 'framework',
'title' => 'MySQL 5.0+ (using PDO)', 'title' => 'MySQL 5.0+ (using PDO)',
'helperPath' => $frameworkPath . '/dev/install/MySQLDatabaseConfigurationHelper.php', 'helperPath' => __DIR__ . '/dev/install/MySQLDatabaseConfigurationHelper.php',
'helperClass' => MySQLDatabaseConfigurationHelper::class,
'supported' => (class_exists('PDO') && in_array('mysql', PDO::getAvailableDrivers())), 'supported' => (class_exists('PDO') && in_array('mysql', PDO::getAvailableDrivers())),
'missingExtensionText' => 'missingExtensionText' =>
'Either the <a href="http://www.php.net/manual/en/book.pdo.php">PDO Extension</a> or 'Either the <a href="http://www.php.net/manual/en/book.pdo.php">PDO Extension</a> or