BUG Ensure installer.php works nicely with .env files

Unenjoyable cleanup of internal logic
This commit is contained in:
Damian Mooyman 2017-08-31 18:17:58 +12:00
parent 1f5644d143
commit 806ffb934e
No known key found for this signature in database
GPG Key ID: 78B823A10DE27D1A
11 changed files with 574 additions and 399 deletions

View File

@ -62,9 +62,6 @@ before_script:
- phpenv config-rm xdebug.ini || true
- echo 'memory_limit = 2048M' >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini
# Temporarily update to 1.5.x-dev of composer
- composer self-update --snapshot
# Install composer dependencies
- export PATH=~/.composer/vendor/bin:$PATH
- composer validate

View File

@ -19,6 +19,9 @@
<exclude name="PEAR.Functions.ValidDefaultValue.NotAtEnd" />
</rule>
<!-- include php files only -->
<arg name="extensions" value="php,lib,inc,php5"/>
<!-- PHP-PEG generated file not intended for human consumption -->
<exclude-pattern>*/SSTemplateParser.php$</exclude-pattern>
<exclude-pattern>*/_fakewebroot/*</exclude-pattern>

View File

@ -0,0 +1,245 @@
<?php
namespace SilverStripe\Dev\Install;
/**
* Provides environment settings from the current request + environment
*
* @skipUpgrade
*/
class InstallConfig
{
/**
* List of preferred DB classes in order
*
* @var array
*/
protected $preferredDatabases = [
'MySQLPDODatabase',
'MySQLDatabase',
];
/**
* Get database config from the current environment
*
* @param array $request Request object
* @param array $databaseClasses Supported database config
* @return array
*/
public function getDatabaseConfig($request, $databaseClasses)
{
// Get config from request
if (isset($request['db']['type'])) {
$type = $request['db']['type'];
if (isset($request['db'][$type])) {
return array_merge(
[ 'type' => $type ],
$request['db'][$type]
);
}
}
// Guess database config
return [
'type' => $this->getDatabaseClass($databaseClasses),
'server' => getenv('SS_DATABASE_SERVER') ?: 'localhost',
'username' => getenv('SS_DATABASE_USERNAME') ?: 'root',
'password' => getenv('SS_DATABASE_PASSWORD') ?: '',
'database' => getenv('SS_DATABASE_NAME') ?: 'SS_mysite',
];
}
/**
* Get admin config from the environment
*
* @param array $request
* @return array
*/
public function getAdminConfig($request)
{
if (isset($request['admin'])) {
return $request['admin'];
}
return [
'username' => getenv('SS_DEFAULT_ADMIN_USERNAME') ?: 'admin',
'password' => getenv('SS_DEFAULT_ADMIN_PASSWORD') ?: '',
];
}
/**
* Check if this site has already been installed
*
* @return bool
*/
public function alreadyInstalled()
{
if (file_exists($this->getEnvPath())) {
return true;
}
if (!file_exists($this->getConfigPath())) {
return false;
}
$configContents = file_get_contents($this->getConfigPath());
if (strstr($configContents, '$databaseConfig')) {
return true;
}
if (strstr($configContents, '$database')) {
return true;
}
return false;
}
/**
* @return string
*/
protected function getConfigPath()
{
return BASE_PATH . '/mysite/_config.php';
}
/**
* @return string
*/
protected function getEnvPath()
{
return BASE_PATH . '/.env';
}
/**
* Database configs available for configuration
*
* @param array $databaseClasses
* @return string
*/
protected function getDatabaseClass($databaseClasses)
{
if (getenv('SS_DATABASE_CLASS')) {
return getenv('SS_DATABASE_CLASS');
}
// Check supported versions
foreach ($this->preferredDatabases as $candidate) {
if (!empty($databaseClasses[$candidate]['supported'])) {
return $candidate;
}
}
return null;
}
/**
* Get string representation of the framework version
*
* @return string
*/
public function getFrameworkVersion()
{
$composerLockPath = BASE_PATH . '/composer.lock';
if (!file_exists($composerLockPath)) {
return 'unknown';
}
$lockData = json_decode(file_get_contents($composerLockPath), true);
if (json_last_error() || empty($lockData['packages'])) {
return 'unknown';
}
foreach ($lockData['packages'] as $package) {
if ($package['name'] === 'silverstripe/framework') {
return $package['version'];
}
}
return 'unknown';
}
/**
* Check if stats should be sent
*
* @param array $request
* @return bool
*/
public function canSendStats($request)
{
return !empty($request['stats']);
}
/**
* Get configured locales
*
* @return array
*/
public function getLocales()
{
return [
'af_ZA' => 'Afrikaans (South Africa)',
'ar_EG' => 'Arabic (Egypt)',
'hy_AM' => 'Armenian (Armenia)',
'ast_ES' => 'Asturian (Spain)',
'az_AZ' => 'Azerbaijani (Azerbaijan)',
'bs_BA' => 'Bosnian (Bosnia and Herzegovina)',
'bg_BG' => 'Bulgarian (Bulgaria)',
'ca_ES' => 'Catalan (Spain)',
'zh_CN' => 'Chinese (China)',
'zh_TW' => 'Chinese (Taiwan)',
'hr_HR' => 'Croatian (Croatia)',
'cs_CZ' => 'Czech (Czech Republic)',
'da_DK' => 'Danish (Denmark)',
'nl_NL' => 'Dutch (Netherlands)',
'en_GB' => 'English (United Kingdom)',
'en_US' => 'English (United States)',
'eo_XX' => 'Esperanto',
'et_EE' => 'Estonian (Estonia)',
'fo_FO' => 'Faroese (Faroe Islands)',
'fi_FI' => 'Finnish (Finland)',
'fr_FR' => 'French (France)',
'de_DE' => 'German (Germany)',
'el_GR' => 'Greek (Greece)',
'he_IL' => 'Hebrew (Israel)',
'hu_HU' => 'Hungarian (Hungary)',
'is_IS' => 'Icelandic (Iceland)',
'id_ID' => 'Indonesian (Indonesia)',
'it_IT' => 'Italian (Italy)',
'ja_JP' => 'Japanese (Japan)',
'km_KH' => 'Khmer (Cambodia)',
'lc_XX' => 'LOLCAT',
'lv_LV' => 'Latvian (Latvia)',
'lt_LT' => 'Lithuanian (Lithuania)',
'ms_MY' => 'Malay (Malaysia)',
'mi_NZ' => 'Maori (New Zealand)',
'ne_NP' => 'Nepali (Nepal)',
'nb_NO' => 'Norwegian',
'fa_IR' => 'Persian (Iran)',
'pl_PL' => 'Polish (Poland)',
'pt_BR' => 'Portuguese (Brazil)',
'pa_IN' => 'Punjabi (India)',
'ro_RO' => 'Romanian (Romania)',
'ru_RU' => 'Russian (Russia)',
'sr_RS' => 'Serbian (Serbia)',
'si_LK' => 'Sinhalese (Sri Lanka)',
'sk_SK' => 'Slovak (Slovakia)',
'sl_SI' => 'Slovenian (Slovenia)',
'es_AR' => 'Spanish (Argentina)',
'es_MX' => 'Spanish (Mexico)',
'es_ES' => 'Spanish (Spain)',
'sv_SE' => 'Swedish (Sweden)',
'th_TH' => 'Thai (Thailand)',
'tr_TR' => 'Turkish (Turkey)',
'uk_UA' => 'Ukrainian (Ukraine)',
'uz_UZ' => 'Uzbek (Uzbekistan)',
'vi_VN' => 'Vietnamese (Vietnam)',
];
}
/**
* Get theme selected
*
* @param $request
* @return string
*/
public function getTheme($request)
{
if (isset($request['template'])) {
return $request['template'];
}
// Default theme
return 'simple';
}
}

View File

@ -50,17 +50,22 @@ class InstallRequirements
return false;
}
$path = empty($databaseConfig['path']) ? null : $databaseConfig['path'];
$server = empty($databaseConfig['server']) ? null : $databaseConfig['server'];
// Check if the server is available
$usePath = !empty($databaseConfig['path']) && empty($databaseConfig['server']);
$usePath = $path && empty($server);
if (!$this->requireDatabaseServer(
$databaseConfig,
array(
"Database Configuration",
"Database 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']
? "I couldn't write to path '{$path}'"
: "I couldn't find a database server on '{$server}'",
$usePath
? $path
: $server
)
)
) {

View File

@ -2,6 +2,7 @@
namespace SilverStripe\Dev\Install;
use Dotenv\Dotenv;
use Exception;
use SilverStripe\Control\Cookie;
use SilverStripe\Control\HTTPApplication;
@ -15,7 +16,6 @@ use SilverStripe\Security\DefaultAdminService;
use SilverStripe\Security\Security;
/**
* SilverStripe CMS SilverStripe\Dev\Install\Installer
* This installer doesn't use any of the fancy SilverStripe stuff in case it's unsupported.
*/
class Installer extends InstallRequirements
@ -67,41 +67,17 @@ class Installer extends InstallRequirements
// Render header
$this->installHeader();
$webserver = $this->findWebserver();
$isIIS = $this->isIIS();
$isApache = $this->isApache();
flush();
if (isset($config['stats'])) {
if (file_exists(FRAMEWORK_PATH . '/silverstripe_version')) {
$silverstripe_version = file_get_contents(FRAMEWORK_PATH . '/silverstripe_version');
} else {
$silverstripe_version = "unknown";
}
$phpVersion = urlencode(phpversion());
$encWebserver = urlencode($webserver);
$dbType = $config['db']['type'];
// Try to determine the database version from the helper
$databaseVersion = $config['db']['type'];
$helper = $this->getDatabaseConfigurationHelper($dbType);
if ($helper && method_exists($helper, 'getDatabaseVersion')) {
$versionConfig = $config['db'][$dbType];
$versionConfig['type'] = $dbType;
$databaseVersion = urlencode($dbType . ': ' . $helper->getDatabaseVersion($versionConfig));
}
$url = "http://ss2stat.silverstripe.com/Installation/add?SilverStripe=$silverstripe_version&PHP=$phpVersion&Database=$databaseVersion&WebServer=$encWebserver";
if (isset($_SESSION['StatsID']) && $_SESSION['StatsID']) {
$url .= '&ID=' . $_SESSION['StatsID'];
}
@$_SESSION['StatsID'] = file_get_contents($url);
// Send install stats
if (!empty($config['stats'])) {
$this->sendInstallStats($config);
}
// Cleanup _config.php
if (file_exists('mysite/_config.php')) {
// Truncate the contents of _config instead of deleting it - we can't re-create it because Windows handles permissions slightly
// differently to UNIX based filesystems - it takes the permissions from the parent directory instead of retaining them
@ -109,69 +85,12 @@ class Installer extends InstallRequirements
fclose($fh);
}
// Escape user input for safe insertion into PHP file
$theme = isset($_POST['template']) ? addcslashes($_POST['template'], "\'") : 'simple';
$locale = isset($_POST['locale']) ? addcslashes($_POST['locale'], "\'") : 'en_US';
$type = addcslashes($config['db']['type'], "\'");
$dbConfig = $config['db'][$type];
foreach ($dbConfig as &$configValue) {
$configValue = addcslashes($configValue, "\\\'");
}
if (!isset($dbConfig['path'])) {
$dbConfig['path'] = '';
}
if (!$dbConfig) {
echo "<p style=\"color: red\">Bad config submitted</p><pre>";
print_r($config);
echo "</pre>";
die();
}
// Write the config file
global $usingEnv;
if ($usingEnv) {
$this->statusMessage("Setting up 'mysite/_config.php' for use with environment variables...");
$this->writeToFile("mysite/_config.php", "<?php\n ");
} else {
$this->statusMessage("Setting up 'mysite/_config.php'...");
// Create databaseConfig
$lines = array(
$lines[] = " 'type' => '$type'"
);
foreach ($dbConfig as $key => $value) {
$lines[] = " '{$key}' => '$value'";
}
$databaseConfigContent = implode(",\n", $lines);
$this->writeToFile("mysite/_config.php", <<<PHP
<?php
use SilverStripe\\ORM\\DB;
DB::setConfig([
{$databaseConfigContent}
]);
PHP
);
}
$this->statusMessage("Setting up 'mysite/_config/theme.yml'");
$this->writeToFile("mysite/_config/theme.yml", <<<YML
---
Name: mytheme
---
# YAML configuration for SilverStripe
# See http://doc.silverstripe.org/framework/en/topics/configuration
# Caution: Indentation through two spaces, not tabs
SilverStripe\\View\\SSViewer:
themes:
- '$theme'
- '\$default'
SilverStripe\\i18n\\i18n:
default_locale: '$locale'
YML
);
// Write all files
$this->writeConfigPHP($config);
$this->writeConfigYaml($config);
$this->writeConfigEnv($config);
// Write other stuff
if (!$this->checkModuleExists('cms')) {
$this->writeToFile("mysite/code/RootURLController.php", <<<PHP
<?php
@ -192,10 +111,8 @@ PHP
// Write the appropriate web server configuration file for rewriting support
if ($this->hasRewritingCapability()) {
if ($isApache) {
$this->statusMessage("Setting up '.htaccess' file...");
$this->createHtaccess();
} elseif ($isIIS) {
$this->statusMessage("Setting up 'web.config' file...");
$this->createWebConfig();
}
}
@ -282,18 +199,187 @@ HTML;
return $this->errors;
}
/**
* Write all .env files
*
* @param $config
*/
protected function writeConfigEnv($config)
{
if (!$config['usingEnv']) {
return;
}
$path = $this->getBaseDir() . '.env';
$vars = [];
// Retain existing vars
// Note: vars with # or " in them are discarded
if (file_exists($path)) {
$env = new Dotenv($this->getBaseDir());
foreach ($env->load() as $line) {
if (preg_match('/^(?<key>\w+)\s*=\s*("?)(?<value>[^"#]*)("?)$/', $line, $matches)) {
$vars[$matches['key']] = $matches['value'];
}
}
}
// Set base URL
if (!isset($vars['SS_BASE_URL']) && isset($_SERVER['HTTP_HOST'])) {
$vars['SS_BASE_URL'] = 'http://' . $_SERVER['HTTP_HOST'] . BASE_URL;
}
// Set DB env
if (empty($config['db']['database'])) {
$vars['SS_DATABASE_CHOOSE_NAME'] = true;
} else {
$vars['SS_DATABASE_NAME'] = $config['db']['database'];
}
$vars['SS_DATABASE_CLASS'] = $config['db']['type'];
if (isset($config['db']['server'])) {
$vars['SS_DATABASE_SERVER'] = $config['db']['server'];
}
if (isset($config['db']['username'])) {
$vars['SS_DATABASE_USERNAME'] = $config['db']['username'];
}
if (isset($config['db']['password'])) {
$vars['SS_DATABASE_PASSWORD'] = $config['db']['password'];
}
if (isset($config['db']['path'])) {
$vars['SS_DATABASE_PATH'] = $config['db']['path'];
// sqlite compat
$vars['SS_SQLITE_DATABASE_PATH'] = $config['db']['path'];
}
if (isset($config['db']['key'])) {
$vars['SS_DATABASE_KEY'] = $config['db']['key'];
// sqlite compat
$vars['SS_SQLITE_DATABASE_KEY'] = $config['db']['key'];
}
// Write all env vars
$lines = [
'# Generated by SilverStripe Installer'
];
ksort($vars);
foreach ($vars as $key => $value) {
$lines[] = $key.'="'.addcslashes($value, '"').'"';
}
$this->writeToFile('.env', implode("\n", $lines));
// Re-load env vars for installer access
$path = $this->getBaseDir();
(new Dotenv($path))->load();
}
/**
* Write all *.php files
*
* @param array $config
*/
protected function writeConfigPHP($config)
{
if ($config['usingEnv']) {
$this->writeToFile("mysite/_config.php", "<?php\n ");
return;
}
// Create databaseConfig
$lines = [];
foreach ($config['db'] as $key => $value) {
$lines[] = sprintf(
" '%s' => '%s'",
addslashes($key),
addslashes($value)
);
}
$databaseConfigContent = implode(",\n", $lines);
$this->writeToFile("mysite/_config.php", <<<PHP
<?php
use SilverStripe\\ORM\\DB;
DB::setConfig([
{$databaseConfigContent}
]);
PHP
);
}
/**
* Write yml files
*
* @param array $config
*/
protected function writeConfigYaml($config)
{
// Escape user input for safe insertion into PHP file
$locale = $this->ymlString($config['locale']);
// Set either specified, or no theme
if ($config['theme'] && $config['theme'] !== 'tutorial') {
$theme = $this->ymlString($config['theme']);
$themeYML = <<<YML
- '$theme'
- '\$default'
YML;
} else {
$themeYML = <<<YML
- '\$default'
YML;
}
// Write theme.yml
$this->writeToFile("mysite/_config/theme.yml", <<<YML
---
Name: mytheme
---
SilverStripe\\View\\SSViewer:
themes:
$themeYML
SilverStripe\\i18n\\i18n:
default_locale: '$locale'
YML
);
}
/**
* Escape yml string
*
* @param string $string
* @return mixed
*/
protected function ymlString($string)
{
// just escape single quotes using ''
return str_replace("'", "''", $string);
}
/**
* Write file to given location
*
* @param $filename
* @param $content
* @return bool
*/
public function writeToFile($filename, $content)
{
$base = $this->getBaseDir();
$this->statusMessage("Setting up $base$filename");
if ((@$fh = fopen($base . $filename, 'wb')) && fwrite($fh, $content) && fclose($fh)) {
// Set permissions to writable
@chmod($base . $filename, 0775);
return true;
}
$this->error("Couldn't write to file $base$filename");
return false;
}
/**
* Ensure root .htaccess is setup
*/
public function createHtaccess()
{
$start = "### SILVERSTRIPE START ###\n";
@ -473,18 +559,6 @@ TEXT;
HTML;
}
public function var_export_array_nokeys($array)
{
$retval = "array(\n";
foreach ($array as $item) {
$retval .= "\t'";
$retval .= trim($item);
$retval .= "',\n";
}
$retval .= ")";
return $retval;
}
/**
* Show an installation status message.
* The output differs depending on whether this is CLI or web based
@ -496,4 +570,29 @@ HTML;
echo "<li>$msg</li>\n";
flush();
}
/**
* @param $config
*/
protected function sendInstallStats($config)
{
// Try to determine the database version from the helper
$dbType = $config['db']['type'];
$helper = $this->getDatabaseConfigurationHelper($dbType);
if ($helper) {
$databaseVersion = $dbType . ': ' . $helper->getDatabaseVersion($config['db']);
} else {
$databaseVersion = $dbType;
}
$args = http_build_query(array_filter([
'SilverStripe' => $config['version'],
'PHP' => phpversion(),
'Database' => $databaseVersion,
'WebServer' => $this->findWebserver(),
'ID' => empty($_SESSION['StatsID']) ? null : $_SESSION['StatsID']
]));
$url = "http://ss2stat.silverstripe.com/Installation/add?{$args}";
@$_SESSION['StatsID'] = file_get_contents($url);
}
}

View File

@ -1,59 +1,49 @@
$(document).ready(function () {
/**
* Toggle field readonly modes, if check configuration comes from
* environment variables (values populated on reload).
*/
$('#use_environment').click(function (e) {
if (!$(this).is(':checked')) {
$('.configured-by-env').removeAttr('disabled');
} else {
$('.configured-by-env').attr('disabled', 'disabled');
}
});
/**
* Hide all existing database warnings, and show only current one
*/
$('#database_selection > li > label, #database_selection > li > input:radio').click(function () {
$('.dbfields').hide();
// only show fields if there's no db error
if (!$('.databaseError', $(this).parent()).length) {
$('.dbfields', $(this).parent()).show();
}
$('.databaseError').hide();
$('.databaseError', $(this).parent()).show();
});
/**
* Hide all existing database warnings, and show only current one
*/
$('#database_selection li label, #database_selection input:radio').click(function (e) {
$('.dbfields').hide();
// only show fields if there's no db error
if (!$('.databaseError', $(this).parent()).length) {
$('.dbfields', $(this).parent()).show();
}
$('.databaseError').hide();
$('.databaseError', $(this).parent()).show();
});
// Handle install button
$('#install_button').click(function (e) {
// Confirm on re-install
if (
$(this).hasClass('mustconfirm')
&& !confirm('Are you sure you wish to replace the existing installation config?')
) {
e.preventDefault();
return false;
}
// Select first
$('#database_selection li input:checked').siblings('label').click();
// Process
$('#saving_top').hide();
$(this).val('Installing SilverStripe...');
return true;
});
/**
* Install button
*/
$('#reinstall_confirmation').click(function () {
$('#install_button').attr('disabled', !$(this).is(':checked'));
});
/**
* Show all the requirements
*/
$('h5.requirement a').click(function () {
if ($(this).text() === 'Hide All Requirements') {
// hide the shown requirements
$(this).parents('h5').next('table.testResults').find('.good').hide();
$(this).text('Show All Requirements');
} else {
// show the requirements.
$(this).parents('h5').next('table.testResults').find('.good').show();
$(this).text('Hide All Requirements');
}
$('#install_button').click(function () {
$('#saving_top').hide();
$(this).val('Installing SilverStripe...');
});
/**
* Show all the requirements
*/
$('h5.requirement a').click(function () {
if ($(this).text() == 'Hide All Requirements') {
// hide the shown requirements
$(this).parents('h5').next('table.testResults').find('.good').hide();
$(this).text('Show All Requirements');
} else {
// show the requirements.
$(this).parents('h5').next('table.testResults').find('.good').show();
$(this).text('Hide All Requirements');
}
return false;
});
return false;
});
});

View File

@ -7,8 +7,8 @@
<title>SilverStripe CMS / Framework Installation</title>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<script type="application/javascript" src="//code.jquery.com/jquery-1.7.2.min.js"></script>
<script type="application/javascript" src="<?=FRAMEWORK_NAME; ?>/src/Dev/Install/client/js/install.js"></script>
<link rel="stylesheet" type="text/css" href="<?=FRAMEWORK_NAME; ?>/src/Dev/Install/client/styles/install.css">
<script type="application/javascript" src="<?=$clientPath; ?>/js/install.js"></script>
<link rel="stylesheet" type="text/css" href="<?=$clientPath; ?>/styles/install.css">
<link rel="shortcut icon" href="favicon.ico">
</head>
<body>
@ -41,7 +41,7 @@
<?php if($alreadyInstalled): ?>
<div class="message warning">
<p><strong>Note:</strong> SilverStripe is already installed here.<br>
If you wish to reinstall SilverStripe, please delete the <strong>mysite/_config.php</strong> file first.</p>
If you choose to reinstall SilverStripe, your current settings will be replaced</p>
</div>
<?php elseif($req->hasWarnings()): ?>
<div class="message warning">
@ -94,33 +94,24 @@
<div class="field">
<ul id="database_selection">
<?php
foreach($databaseClasses as $class => $details) {
$checked = ($databaseConfig['type'] == $class || $type == $class) ? ' checked="checked"' : '';
foreach ($databaseClasses as $class => $details) {
$checked = ($databaseConfig['type'] == $class) ? ' checked="checked"' : '';
$disabled = $help = '';
if($usingEnv) {
// All are disabled by default when environment is used
$disabled = 'disabled="disabled"';
// If SS_DATABASE_CLASS is specified, check the database in the list
if(getenv('SS_DATABASE_CLASS') == $class) {
$checked = ' checked="checked"';
}
} else {
$disabled = !$details['supported'] || !$details['hasModule'] ? 'notavailable="true"' : '';
if ($disabled) {
if (!$details['supported'] && !$details['hasModule']) {
$help = 'PHP does not have the required extension, and SilverStripe does not have the correct module installed';
$helpText = '<li style="width:auto">'.$details['missingExtensionText'].'</li>';
$helpText .= '<li style="width:auto">'.$details['missingModuleText'].'</li>';
} else if ($details['supported'] && !$details['hasModule']) {
$help = 'PHP has the required extension, but SilverStripe is missing the module';
$helpText = '<li style="width:auto">'.$details['missingModuleText'].'</li>';
} else if (!$details['supported'] && $details['hasModule']) {
$help = 'SilverStripe has the module installed, but PHP is missing the required extension';
$helpText = '<li style="width:auto">'.$details['missingExtensionText'].'</li>';
}
$help .= "<ul>$helpText</ul>";
}
}
$disabled = !$details['supported'] || !$details['hasModule'] ? 'notavailable="true"' : '';
if ($disabled) {
if (!$details['supported'] && !$details['hasModule']) {
$help = 'PHP does not have the required extension, and SilverStripe does not have the correct module installed';
$helpText = '<li style="width:auto">'.$details['missingExtensionText'].'</li>';
$helpText .= '<li style="width:auto">'.$details['missingModuleText'].'</li>';
} else if ($details['supported'] && !$details['hasModule']) {
$help = 'PHP has the required extension, but SilverStripe is missing the module';
$helpText = '<li style="width:auto">'.$details['missingModuleText'].'</li>';
} else if (!$details['supported'] && $details['hasModule']) {
$help = 'SilverStripe has the module installed, but PHP is missing the required extension';
$helpText = '<li style="width:auto">'.$details['missingExtensionText'].'</li>';
}
$help .= "<ul>$helpText</ul>";
}
echo "<li>";
echo "<input id=\"$class\" class=\"databaseClass\" type=\"radio\" name=\"db[type]\" value=\"$class\"$checked $disabled>";
echo "<label class=\"left\" ".($help || $disabled ? 'style="font-weight:normal;color:grey" ' : 'style="color:green"')."for=\"$class\">{$details['title']}</label>";
@ -129,7 +120,7 @@
}
// generate db-specific config fields
echo '<div class="dbfields">';
echo $checked ? '<div class="dbfields">' : '<div class="dbfields" style="display: none;">';
if(isset($details['fields'])) foreach($details['fields'] as $fieldName => $fieldSpec) {
$fieldTitle = $fieldSpec['title'];
$fieldType = ($fieldName == 'password') ? 'password' : 'text';
@ -149,12 +140,6 @@
'name' => "db[$class][$fieldName]",
'value' => $value,
);
if($usingEnv && isset($fieldSpec['envVar']) && getenv($fieldSpec['envVar'])) {
$attrs['disabled'] = 'disabled';
}
if(isset($fieldSpec['envVar'])) {
$attrs['class'] .= ' configured-by-env';
}
$attrHTML = '';
foreach($attrs as $attrName => $attrValue) $attrHTML .= "$attrName=\"" . htmlspecialchars($attrValue) . '"';
if(isset($fieldSpec['attributes'])) $attrs = array_merge($attrs, $fieldSpec['attributes']);
@ -200,14 +185,14 @@
<div class="field">
<label for="admin_username">Email:</label>
<span class="middleColumn">
<input type="text" class="text configured-by-env" name="admin[username]" id="admin_username" value="<?=htmlspecialchars($adminConfig['username'], ENT_QUOTES, 'UTF-8'); ?>" <?php if($usingEnv && getenv('SS_DEFAULT_ADMIN_USERNAME')) echo 'disabled="disabled"' ?>>
<input type="text" class="text" name="admin[username]" id="admin_username" value="<?=htmlspecialchars($adminConfig['username'], ENT_QUOTES, 'UTF-8'); ?>" <?php if($usingEnv && getenv('SS_DEFAULT_ADMIN_USERNAME')) echo 'disabled="disabled"' ?>>
</span>
</div>
<div class="field">
<label for="admin_password">Password:</label>
<span class="middleColumn">
<input type="password" class="text configured-by-env" name="admin[password]" id="admin_password" value="<?=htmlspecialchars($adminConfig['password'], ENT_QUOTES, 'UTF-8'); ?>" <?php if($usingEnv && getenv('SS_DEFAULT_ADMIN_PASSWORD')) echo 'disabled="disabled"' ?>>
<input type="password" class="text" name="admin[password]" id="admin_password" value="<?=htmlspecialchars($adminConfig['password'], ENT_QUOTES, 'UTF-8'); ?>" <?php if($usingEnv && getenv('SS_DEFAULT_ADMIN_PASSWORD')) echo 'disabled="disabled"' ?>>
</span>
</div>
</div>
@ -226,9 +211,8 @@
<span class="middleColumn">
<select name="locale" id="locale">
<?php
$selectedLocale = isset($_POST['locale']) ? $_POST['locale'] : $defaultLocale;
foreach($locales as $code => $title) {
$selected = $code == $selectedLocale ? ' selected="selected"' : '';
foreach ($locales as $code => $title) {
$selected = ($code === $locale) ? ' selected="selected"' : '';
echo "<option$selected value=\"$code\">{$title}</option>\n";
}
?>
@ -247,8 +231,8 @@
<p class="helpText">You can change the theme or <a href="http://addons.silverstripe.org/add-ons?type=theme">download</a> another from the SilverStripe website after installation.</p>
<ul id="Themes">
<li><input type="radio" name="template" value="simple" id="Simple"
<?php if(!isset($_POST['template']) || $_POST['template'] == 'simple'): ?>checked="checked"<?php endif; ?>><label for="Simple"><a href="https://github.com/silverstripe-themes/silverstripe-simple">Simple</a> - our default theme ready to use, or begin the <a href="http://www.silverstripe.org/learn/lessons" target="_blank">lessons</a>.</label></li>
<li><input type="radio" name="template" value="tutorial" id="EmptyTemplate" <?php if(isset($_POST['template']) && $_POST['template'] == 'tutorial'): ?>checked="checked"<?php endif; ?>><label for="EmptyTemplate">Empty template</label></li>
<?php if($theme === 'simple'): ?>checked="checked"<?php endif; ?>><label for="Simple"><a href="https://github.com/silverstripe-themes/silverstripe-simple">Simple</a> - our default theme ready to use, or begin the <a href="http://www.silverstripe.org/learn/lessons" target="_blank">lessons</a>.</label></li>
<li><input type="radio" name="template" value="tutorial" id="EmptyTemplate" <?php if($theme === 'tutorial'): ?>checked="checked"<?php endif; ?>><label for="EmptyTemplate">Empty template</label></li>
</ul>
<h3 class="sectionHeading" id="install">Confirm Install <small>Step 5 of 5</small></h3>
@ -266,14 +250,14 @@
<p>
<?php if($alreadyInstalled): ?>
<input id="install_button" type="submit" disabled="disabled" class="action" name="go" value="Install SilverStripe">
<input id="install_button" type="submit" class="action mustconfirm" name="reinstall" value="Reinstall SilverStripe">
<?php else: ?>
<input id="install_button" type="submit" class="action" name="go" value="Install SilverStripe">
<?php endif; ?>
<span id="saving_top" style="display: none">
&nbsp;
<img src="<?=FRAMEWORK_NAME; ?>/src/Dev/Install/client/images/network-save.gif" alt="Saving">
<img src="<?=$clientPath; ?>/images/network-save.gif" alt="Saving">
(this will take a minute or so)
</span>
</p>

View File

@ -10,15 +10,13 @@
************************************************************************************/
/**
* PHP version check. Make sure we've got at least PHP 5.5.0 in the most friendly way possible
* PHP version check. Make sure we've got at least PHP 5.6.0 in the most friendly way possible
*/
define('FRAMEWORK_NAME', 'framework');
if (version_compare(phpversion(), '5.5.0', '<')) {
if (version_compare(phpversion(), '5.6.0', '<')) {
header($_SERVER['SERVER_PROTOCOL'] . " 500 Server Error");
echo str_replace(
array('$PHPVersion', 'sapphire'),
array(phpversion(), FRAMEWORK_NAME),
'$PHPVersion',
phpversion(),
file_get_contents(__DIR__ . "/php5-required.html")
);
die();

View File

@ -37,70 +37,12 @@ if (function_exists('session_start') && !session_id()) {
}
// require composers autoloader
require __DIR__ . '/../../includes/autoload.php';
require_once __DIR__ . '/../../includes/autoload.php';
$usingEnv = !empty($_REQUEST['useEnv']);
$usingEnv = empty($_POST) || !empty($_REQUEST['useEnv']);
// Set default locale, but try and sniff from the user agent
$defaultLocale = 'en_US';
$locales = array(
'af_ZA' => 'Afrikaans (South Africa)',
'ar_EG' => 'Arabic (Egypt)',
'hy_AM' => 'Armenian (Armenia)',
'ast_ES' => 'Asturian (Spain)',
'az_AZ' => 'Azerbaijani (Azerbaijan)',
'bs_BA' => 'Bosnian (Bosnia and Herzegovina)',
'bg_BG' => 'Bulgarian (Bulgaria)',
'ca_ES' => 'Catalan (Spain)',
'zh_CN' => 'Chinese (China)',
'zh_TW' => 'Chinese (Taiwan)',
'hr_HR' => 'Croatian (Croatia)',
'cs_CZ' => 'Czech (Czech Republic)',
'da_DK' => 'Danish (Denmark)',
'nl_NL' => 'Dutch (Netherlands)',
'en_GB' => 'English (United Kingdom)',
'en_US' => 'English (United States)',
'eo_XX' => 'Esperanto',
'et_EE' => 'Estonian (Estonia)',
'fo_FO' => 'Faroese (Faroe Islands)',
'fi_FI' => 'Finnish (Finland)',
'fr_FR' => 'French (France)',
'de_DE' => 'German (Germany)',
'el_GR' => 'Greek (Greece)',
'he_IL' => 'Hebrew (Israel)',
'hu_HU' => 'Hungarian (Hungary)',
'is_IS' => 'Icelandic (Iceland)',
'id_ID' => 'Indonesian (Indonesia)',
'it_IT' => 'Italian (Italy)',
'ja_JP' => 'Japanese (Japan)',
'km_KH' => 'Khmer (Cambodia)',
'lc_XX' => 'LOLCAT',
'lv_LV' => 'Latvian (Latvia)',
'lt_LT' => 'Lithuanian (Lithuania)',
'ms_MY' => 'Malay (Malaysia)',
'mi_NZ' => 'Maori (New Zealand)',
'ne_NP' => 'Nepali (Nepal)',
'nb_NO' => 'Norwegian',
'fa_IR' => 'Persian (Iran)',
'pl_PL' => 'Polish (Poland)',
'pt_BR' => 'Portuguese (Brazil)',
'pa_IN' => 'Punjabi (India)',
'ro_RO' => 'Romanian (Romania)',
'ru_RU' => 'Russian (Russia)',
'sr_RS' => 'Serbian (Serbia)',
'si_LK' => 'Sinhalese (Sri Lanka)',
'sk_SK' => 'Slovak (Slovakia)',
'sl_SI' => 'Slovenian (Slovenia)',
'es_AR' => 'Spanish (Argentina)',
'es_MX' => 'Spanish (Mexico)',
'es_ES' => 'Spanish (Spain)',
'sv_SE' => 'Swedish (Sweden)',
'th_TH' => 'Thai (Thailand)',
'tr_TR' => 'Turkish (Turkey)',
'uk_UA' => 'Ukrainian (Ukraine)',
'uz_UZ' => 'Uzbek (Uzbekistan)',
'vi_VN' => 'Vietnamese (Vietnam)',
);
$locale = isset($_POST['locale']) ? $_POST['locale'] : 'en_US';
// Discover which databases are available
DatabaseAdapterRegistry::autodiscover();
@ -112,112 +54,18 @@ foreach ($databaseClasses as $class => $details) {
$databaseClasses[$class]['hasModule'] = !empty($helper);
}
// Load database config
/** @skipUpgrade */
if (isset($_REQUEST['db'])) {
if (isset($_REQUEST['db']['type'])) {
$type = $_REQUEST['db']['type'];
} else {
if ($type = getenv('SS_DATABASE_CLASS')) {
$_REQUEST['db']['type'] = $type;
} elseif ($databaseClasses['MySQLPDODatabase']['supported']) {
$type = $_REQUEST['db']['type'] = 'MySQLPDODatabase';
} elseif ($databaseClasses['MySQLDatabase']['supported']) {
$type = $_REQUEST['db']['type'] = 'MySQLDatabase';
} else {
// handle error
}
}
// Disabled inputs don't submit anything - we need to use the environment (except the database name)
if ($usingEnv) {
$_REQUEST['db'][$type] = $databaseConfig = array(
"type" => getenv('SS_DATABASE_CLASS') ?: $type,
"server" => getenv('SS_DATABASE_SERVER') ?: "localhost",
"username" => getenv('SS_DATABASE_USERNAME') ?: "root",
"password" => getenv('SS_DATABASE_PASSWORD') ?: "",
"database" => $_REQUEST['db'][$type]['database'],
);
// Set SSL parameters if they exist
if (getenv('SS_DATABASE_SSL_KEY') && getenv('SS_DATABASE_SSL_CERT')) {
$databaseConfig['ssl_key'] = getenv('SS_DATABASE_SSL_KEY');
$databaseConfig['ssl_cert'] = getenv('SS_DATABASE_SSL_CERT');
}
if (getenv('SS_DATABASE_SSL_CA')) {
$databaseConfig['ssl_ca'] = getenv('SS_DATABASE_SSL_CA');
}
if (getenv('SS_DATABASE_SSL_CIPHER')) {
$databaseConfig['ssl_ca'] = getenv('SS_DATABASE_SSL_CIPHER');
}
} else {
// Normal behaviour without the environment
$databaseConfig = $_REQUEST['db'][$type];
$databaseConfig['type'] = $type;
}
} else {
if ($type = getenv('SS_DATABASE_CLASS')) {
$_REQUEST['db']['type'] = $type;
} elseif ($databaseClasses['MySQLPDODatabase']['supported']) {
$type = $_REQUEST['db']['type'] = 'MySQLPDODatabase';
} elseif ($databaseClasses['MySQLDatabase']['supported']) {
$type = $_REQUEST['db']['type'] = 'MySQLDatabase';
} else {
// handle error
}
$_REQUEST['db'][$type] = $databaseConfig = array(
"type" => $type,
"server" => getenv('SS_DATABASE_SERVER') ?: "localhost",
"username" => getenv('SS_DATABASE_USERNAME') ?: "root",
"password" => getenv('SS_DATABASE_PASSWORD') ?: "",
"database" => isset($_SERVER['argv'][2]) ? $_SERVER['argv'][2] : "SS_mysite",
);
}
if (isset($_REQUEST['admin'])) {
// Disabled inputs don't submit anything - we need to use the environment (except the database name)
if ($usingEnv) {
$_REQUEST['admin'] = $adminConfig = array(
'username' => getenv('SS_DEFAULT_ADMIN_USERNAME') ?: 'admin',
'password' => getenv('SS_DEFAULT_ADMIN_PASSWORD') ?: '',
);
} else {
$adminConfig = $_REQUEST['admin'];
}
} else {
$_REQUEST['admin'] = $adminConfig = array(
'username' => getenv('SS_DEFAULT_ADMIN_USERNAME') ?: 'admin',
'password' => getenv('SS_DEFAULT_ADMIN_PASSWORD') ?: '',
);
}
$alreadyInstalled = false;
if (file_exists('mysite/_config.php')) {
// 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)) {
eval($parts[0]);
if (!empty($database)) {
$alreadyInstalled = true;
}
// Assume that if $databaseConfig is defined in mysite/_config.php, then a non-environment-based installation has
// already gone ahead
} elseif (preg_match(
"/\\\$databaseConfig\s*=\s*[^\n\r]+[\n\r]/",
file_get_contents("mysite/_config.php"),
$parts
)) {
$alreadyInstalled = true;
}
}
if (file_exists(FRAMEWORK_NAME . '/silverstripe_version')) {
$silverstripe_version = file_get_contents(FRAMEWORK_NAME . '/silverstripe_version');
} else {
$silverstripe_version = "unknown";
}
// Build config from config / environment / request
$config = new InstallConfig();
$databaseConfig = $config->getDatabaseConfig($_REQUEST, $databaseClasses);
$adminConfig = $config->getAdminConfig($_REQUEST);
$alreadyInstalled = $config->alreadyInstalled();
$silverstripe_version = $config->getFrameworkVersion();
$sendStats = $config->canSendStats($_REQUEST);
$locales = $config->getLocales();
$theme = $config->getTheme($_REQUEST);
// Check requirements
$req = new InstallRequirements($originalIni);
$req = new InstallRequirements();
$req->check();
if ($req->isIIS()) {
@ -256,10 +104,18 @@ if ($installFromCli && ($req->hasErrors() || $dbReq->hasErrors())) {
exit(1);
}
// Path to client resources
$clientPath = (FRAMEWORK_DIR ? FRAMEWORK_DIR . '/' : '') . 'src/Dev/Install/client';
// config-form.html vars (placeholder to prevent deletion)
[
$defaultLocale,
$theme,
$clientPath,
$adminConfig,
$usingEnv,
$silverstripe_version,
$locale,
$locales,
$webserverConfigFile,
$hasErrorOtherThanDatabase,
@ -267,28 +123,26 @@ if ($installFromCli && ($req->hasErrors() || $dbReq->hasErrors())) {
$phpIniLocation
];
if ((isset($_REQUEST['go']) || $installFromCli)
// If already installed, ensure the user clicked "reinstall"
$expectedArg = $alreadyInstalled ? 'reinstall' : 'go';
if ((isset($_REQUEST[$expectedArg]) || $installFromCli)
&& !$req->hasErrors()
&& !$dbReq->hasErrors()
&& $adminConfig['username']
&& $adminConfig['password']
) {
// Confirm before reinstalling
if (!$installFromCli && $alreadyInstalled) {
include(__DIR__ . '/config-form.html');
} else {
$inst = new Installer();
if ($_REQUEST) {
$inst->install($_REQUEST);
} else {
$inst->install(array(
'db' => $databaseConfig,
'admin' => $adminConfig,
));
}
}
// Show the config form
$inst = new Installer();
$inst->install([
'usingEnv' => $usingEnv,
'locale' => $locale,
'theme' => $theme,
'version' => $silverstripe_version,
'db' => $databaseConfig,
'admin' => $adminConfig,
'stats' => $sendStats,
]);
// Show the config form
} else {
include(__DIR__ . '/config-form.html');
}

View File

@ -30,7 +30,7 @@
<div id="Footer">
<div class="footerTop"><!-- --></div>
<p><a href="http://silverstripe.org">SilverStripe Open Source CMS</a> | Copyright &copy; 2012 SilverStripe Limited</p>
<p><a href="http://silverstripe.org">SilverStripe Open Source CMS</a> | Copyright &copy; 2017 SilverStripe Limited</p>
</div>
</div>
</body>

View File

@ -223,7 +223,7 @@ class DatabaseAdmin extends Controller
// Assumes database class is like "MySQLDatabase" or "MSSQLDatabase" (suffixed with "Database")
$dbType = substr(get_class($conn), 0, -8);
$dbVersion = $conn->getVersion();
$databaseName = (method_exists($conn, 'currentDatabase')) ? $conn->getSelectedDatabase() : "";
$databaseName = $conn->getSelectedDatabase();
if (Director::is_cli()) {
echo sprintf("\n\nBuilding database %s using %s %s\n\n", $databaseName, $dbType, $dbVersion);