mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
NEW: Remove web installer, move to separate package (#9231)
* Remove installer * Remove exposed install files * Replace Dev/Install classes still in use * Update changelog * FIX make the grid field actions consistent to what they look like on pages Resolves https://github.com/silverstripe/silverstripe-admin/issues/904 * Docs changes
This commit is contained in:
parent
75cd9dc944
commit
da6582f593
@ -67,8 +67,7 @@
|
||||
},
|
||||
"expose": [
|
||||
"client/images",
|
||||
"client/styles",
|
||||
"src/Dev/Install/client"
|
||||
"client/styles"
|
||||
]
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -12,7 +12,6 @@ the server to update templates, website logic, and perform upgrades or maintenan
|
||||
* PHP extension for image manipulation: Either `gd` or `imagick`
|
||||
* PHP extension for a database connector (e.g. `pdo` or `mysqli`)
|
||||
|
||||
Our web-based [PHP installer](installation/) can check requirements.
|
||||
Use [phpinfo()](http://php.net/manual/en/function.phpinfo.php) to inspect your configuration.
|
||||
|
||||
## Database
|
||||
|
@ -40,8 +40,7 @@ The CMS login can be accessed at `/admin`.
|
||||
|
||||
## Guided Installation
|
||||
|
||||
If you are unsure on how this all works, or prefer to follow
|
||||
an installer wizard, please jump on our [lessons](https://www.silverstripe.org/learn/lessons/v4/).
|
||||
If you are unsure on how this all works, please jump on our [lessons](https://www.silverstripe.org/learn/lessons/v4/).
|
||||
Webserver setup is covered in
|
||||
[Lesson 4: Setting up a local dev environment](https://www.silverstripe.org/learn/lessons/v4/up-and-running-setting-up-a-local-silverstripe-dev-environment-1)
|
||||
|
||||
|
@ -2,11 +2,29 @@
|
||||
|
||||
## Overview {#overview}
|
||||
|
||||
* [Installer UI has been removed](#installer-ui) and offered as a separate module.
|
||||
* [Generic login form styling](#login-forms)
|
||||
* Removed `use_gzip` option on `HtmlEditorField` which used to compress the rich text editor dependency.
|
||||
No longer required since compression is performed as part of the CMS build automatically.
|
||||
See (#832)(https://github.com/silverstripe/silverstripe-admin/issues/832)
|
||||
|
||||
## Installer UI has been removed
|
||||
|
||||
Until now, core releases of SilverStripe would put drop an `install.php` file in the
|
||||
public root that, when accessed with a browser, would offer an installation
|
||||
UI prompting the user for all the necessary configuration of your project
|
||||
and environment, and validating it before performing the installation.
|
||||
|
||||
While this may be an important part of the onboarding experience for newcomers
|
||||
to SilverStripe, it is an unnecessary artefact and potential security risk
|
||||
for the vast majority of developers who install SilverStripe with composer
|
||||
and their own environment files.
|
||||
|
||||
The installer UI will continue to live on under the name "installer-wizard" in a
|
||||
[separate package](https://github.com/silverstripe/silverstripe-installer-wizard), which
|
||||
can be added incrementally to core recipe installation, using `composer require silverstripe/installer-wizard`.
|
||||
It is no longer a commercially supported module.
|
||||
|
||||
## Generic login form styling {#login-forms}
|
||||
|
||||
Login forms in SilverStripe are traditionally embedded in your page template.
|
||||
|
@ -1,278 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Dev\Install;
|
||||
|
||||
use BadMethodCallException;
|
||||
use SilverStripe\Core\Environment;
|
||||
|
||||
/**
|
||||
* Provides environment settings from the current request + environment
|
||||
*
|
||||
* @skipUpgrade
|
||||
*/
|
||||
class InstallConfig
|
||||
{
|
||||
use InstallEnvironmentAware;
|
||||
|
||||
/**
|
||||
* List of preferred DB classes in order
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $preferredDatabases = [
|
||||
'MySQLDatabase',
|
||||
'MySQLPDODatabase',
|
||||
];
|
||||
|
||||
public function __construct($basePath = null)
|
||||
{
|
||||
$this->initBaseDir($basePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get database config from the current environment
|
||||
*
|
||||
* @param array $request Request object
|
||||
* @param array $databaseClasses Supported database config
|
||||
* @param bool $realPassword Set to true to get the real password. If false, any non-posted
|
||||
* password will be redacted as '********'. Note: Posted passwords are considered disclosed and
|
||||
* never redacted.
|
||||
* @return array
|
||||
*/
|
||||
public function getDatabaseConfig($request, $databaseClasses, $realPassword = true)
|
||||
{
|
||||
// Get config from request
|
||||
if (isset($request['db']['type'])) {
|
||||
$type = $request['db']['type'];
|
||||
if (isset($request['db'][$type])) {
|
||||
$config = $request['db'][$type];
|
||||
// The posted placeholder must be substituted with the real password
|
||||
if (isset($config['password']) && $config['password'] === Installer::PASSWORD_PLACEHOLDER) {
|
||||
$config['password'] = Environment::getEnv('SS_DATABASE_PASSWORD') ?: '';
|
||||
}
|
||||
return array_merge([ 'type' => $type ], $config);
|
||||
}
|
||||
}
|
||||
|
||||
// Guess database config
|
||||
return [
|
||||
'type' => $this->getDatabaseClass($databaseClasses),
|
||||
'server' => Environment::getEnv('SS_DATABASE_SERVER') ?: 'localhost',
|
||||
'username' => Environment::getEnv('SS_DATABASE_USERNAME') ?: 'root',
|
||||
'password' => $realPassword
|
||||
? (Environment::getEnv('SS_DATABASE_PASSWORD') ?: '')
|
||||
: Installer::PASSWORD_PLACEHOLDER, // Avoid password disclosure
|
||||
'database' => Environment::getEnv('SS_DATABASE_NAME') ?: 'SS_mysite',
|
||||
'path' => Environment::getEnv('SS_DATABASE_PATH')
|
||||
?: Environment::getEnv('SS_SQLITE_DATABASE_PATH') // sqlite compat
|
||||
?: null,
|
||||
'key' => Environment::getEnv('SS_DATABASE_KEY')
|
||||
?: Environment::getEnv('SS_SQLITE_DATABASE_KEY') // sqlite compat
|
||||
?: null,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get admin config from the environment
|
||||
*
|
||||
* @param array $request
|
||||
* @param bool $realPassword Set to true to get the real password. If false, any non-posted
|
||||
* password will be redacted as '********'. Note: Posted passwords are considered disclosed and
|
||||
* never redacted.
|
||||
* @return array
|
||||
*/
|
||||
public function getAdminConfig($request, $realPassword = true)
|
||||
{
|
||||
if (isset($request['admin'])) {
|
||||
$config = $request['admin'];
|
||||
if (isset($config['password']) && $config['password'] === Installer::PASSWORD_PLACEHOLDER) {
|
||||
$config['password'] = Environment::getEnv('SS_DEFAULT_ADMIN_PASSWORD') ?: '';
|
||||
}
|
||||
return $request['admin'];
|
||||
}
|
||||
|
||||
return [
|
||||
'username' => Environment::getEnv('SS_DEFAULT_ADMIN_USERNAME') ?: 'admin',
|
||||
'password' => $realPassword
|
||||
? (Environment::getEnv('SS_DEFAULT_ADMIN_PASSWORD') ?: '')
|
||||
: Installer::PASSWORD_PLACEHOLDER, // Avoid password disclosure
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 $this->getBaseDir() . $this->getProjectDir() . DIRECTORY_SEPARATOR . '_config.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
protected function getEnvPath()
|
||||
{
|
||||
return $this->getBaseDir() . '.env';
|
||||
}
|
||||
|
||||
/**
|
||||
* Database configs available for configuration
|
||||
*
|
||||
* @param array $databaseClasses
|
||||
* @return string
|
||||
*/
|
||||
protected function getDatabaseClass($databaseClasses)
|
||||
{
|
||||
$envDatabase = Environment::getEnv('SS_DATABASE_CLASS');
|
||||
if ($envDatabase) {
|
||||
return $envDatabase;
|
||||
}
|
||||
|
||||
// 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' => 'Māori (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';
|
||||
}
|
||||
}
|
@ -1,231 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Dev\Install;
|
||||
|
||||
use BadMethodCallException;
|
||||
use SilverStripe\Core\Path;
|
||||
|
||||
/**
|
||||
* For classes which are aware of install, project, and environment state.
|
||||
*
|
||||
* These should be basic getters / setters that infer from current state.
|
||||
*/
|
||||
trait InstallEnvironmentAware
|
||||
{
|
||||
/**
|
||||
* Base path
|
||||
* @var
|
||||
*/
|
||||
protected $baseDir;
|
||||
|
||||
/**
|
||||
* Init base path, or guess if able
|
||||
*
|
||||
* @param string|null $basePath
|
||||
*/
|
||||
protected function initBaseDir($basePath)
|
||||
{
|
||||
if ($basePath) {
|
||||
$this->setBaseDir($basePath);
|
||||
} elseif (defined('BASE_PATH')) {
|
||||
$this->setBaseDir(BASE_PATH);
|
||||
} else {
|
||||
throw new BadMethodCallException("No BASE_PATH defined");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $base
|
||||
* @return $this
|
||||
*/
|
||||
protected function setBaseDir($base)
|
||||
{
|
||||
$this->baseDir = $base;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get base path for this installation
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getBaseDir()
|
||||
{
|
||||
return Path::normalise($this->baseDir) . DIRECTORY_SEPARATOR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get path to public directory
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getPublicDir()
|
||||
{
|
||||
$base = $this->getBaseDir();
|
||||
$public = Path::join($base, 'public') . DIRECTORY_SEPARATOR;
|
||||
if (file_exists($public)) {
|
||||
return $public;
|
||||
}
|
||||
return $base;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that a module exists
|
||||
*
|
||||
* @param string $dirname
|
||||
* @return bool
|
||||
*/
|
||||
public function checkModuleExists($dirname)
|
||||
{
|
||||
// Mysite is base-only and doesn't need _config.php to be counted
|
||||
if (in_array($dirname, ['mysite', 'app'])) {
|
||||
return file_exists($this->getBaseDir() . $dirname);
|
||||
}
|
||||
|
||||
$paths = [
|
||||
"vendor/silverstripe/{$dirname}/",
|
||||
"{$dirname}/",
|
||||
];
|
||||
foreach ($paths as $path) {
|
||||
$checks = ['_config', '_config.php'];
|
||||
foreach ($checks as $check) {
|
||||
if (file_exists($this->getBaseDir() . $path . $check)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get project dir name.
|
||||
*
|
||||
* @return string 'app', or 'mysite' (deprecated)
|
||||
*/
|
||||
protected function getProjectDir()
|
||||
{
|
||||
$base = $this->getBaseDir();
|
||||
if (is_dir($base . 'mysite')) {
|
||||
/** @deprecated 4.2.0:5.0.0 */
|
||||
return 'mysite';
|
||||
}
|
||||
|
||||
// Default
|
||||
return 'app';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get src dir name for project
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getProjectSrcDir()
|
||||
{
|
||||
$projectDir = $this->getProjectDir();
|
||||
if ($projectDir === 'mysite') {
|
||||
/** @deprecated 4.2.0:5.0.0 */
|
||||
return $projectDir . DIRECTORY_SEPARATOR . 'code';
|
||||
}
|
||||
|
||||
// Default
|
||||
return $projectDir . DIRECTORY_SEPARATOR . 'src';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the web server is IIS and version greater than the given version.
|
||||
*
|
||||
* @param int $fromVersion
|
||||
* @return bool
|
||||
*/
|
||||
public function isIIS($fromVersion = 7)
|
||||
{
|
||||
$webserver = $this->findWebserver();
|
||||
if (preg_match('#.*IIS/(?<version>[.\\d]+)$#', $webserver, $matches)) {
|
||||
return version_compare($matches['version'], $fromVersion, '>=');
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isApache()
|
||||
{
|
||||
return strpos($this->findWebserver(), 'Apache') !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the webserver software running on the PHP host.
|
||||
*
|
||||
* @return string|false Server software or boolean FALSE
|
||||
*/
|
||||
public function findWebserver()
|
||||
{
|
||||
// Try finding from SERVER_SIGNATURE or SERVER_SOFTWARE
|
||||
if (!empty($_SERVER['SERVER_SIGNATURE'])) {
|
||||
$webserver = $_SERVER['SERVER_SIGNATURE'];
|
||||
} elseif (!empty($_SERVER['SERVER_SOFTWARE'])) {
|
||||
$webserver = $_SERVER['SERVER_SOFTWARE'];
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return strip_tags(trim($webserver));
|
||||
}
|
||||
|
||||
public function testApacheRewriteExists($moduleName = 'mod_rewrite')
|
||||
{
|
||||
if (function_exists('apache_get_modules') && in_array($moduleName, apache_get_modules())) {
|
||||
return true;
|
||||
}
|
||||
if (isset($_SERVER['HTTP_MOD_REWRITE']) && $_SERVER['HTTP_MOD_REWRITE'] == 'On') {
|
||||
return true;
|
||||
}
|
||||
if (isset($_SERVER['REDIRECT_HTTP_MOD_REWRITE']) && $_SERVER['REDIRECT_HTTP_MOD_REWRITE'] == 'On') {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function testIISRewriteModuleExists($moduleName = 'IIS_UrlRewriteModule')
|
||||
{
|
||||
if (isset($_SERVER[$moduleName]) && $_SERVER[$moduleName]) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the web server has any rewriting capability.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasRewritingCapability()
|
||||
{
|
||||
return ($this->testApacheRewriteExists() || $this->testIISRewriteModuleExists());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get "nice" database name without "Database" suffix
|
||||
*
|
||||
* @param string $databaseClass
|
||||
* @return string
|
||||
*/
|
||||
public function getDatabaseTypeNice($databaseClass)
|
||||
{
|
||||
return substr($databaseClass, 0, -8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an instance of a helper class for the specific database.
|
||||
*
|
||||
* @param string $databaseClass e.g. MySQLDatabase or MSSQLDatabase
|
||||
* @return DatabaseConfigurationHelper
|
||||
*/
|
||||
public function getDatabaseConfigurationHelper($databaseClass)
|
||||
{
|
||||
return DatabaseAdapterRegistry::getDatabaseConfigurationHelper($databaseClass);
|
||||
}
|
||||
}
|
@ -1,1146 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Dev\Install;
|
||||
|
||||
use BadMethodCallException;
|
||||
use Exception;
|
||||
use InvalidArgumentException;
|
||||
use RecursiveDirectoryIterator;
|
||||
use RecursiveIteratorIterator;
|
||||
use SilverStripe\Core\Path;
|
||||
use SilverStripe\Core\TempFolder;
|
||||
use SplFileInfo;
|
||||
|
||||
/**
|
||||
* This class checks requirements
|
||||
* Each of the requireXXX functions takes an argument which gives a user description of the test.
|
||||
* It's an array of 3 parts:
|
||||
* $description[0] - The test catetgory
|
||||
* $description[1] - The test title
|
||||
* $description[2] - The test error to show, if it goes wrong
|
||||
*/
|
||||
class InstallRequirements
|
||||
{
|
||||
use InstallEnvironmentAware;
|
||||
|
||||
/**
|
||||
* List of errors
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $errors = [];
|
||||
|
||||
/**
|
||||
* List of warnings
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $warnings = [];
|
||||
|
||||
/**
|
||||
* List of tests
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $tests = [];
|
||||
|
||||
/**
|
||||
* Backup of original ini settings
|
||||
* @var array
|
||||
*/
|
||||
protected $originalIni = [];
|
||||
|
||||
public function __construct($basePath = null)
|
||||
{
|
||||
$this->initBaseDir($basePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the database configuration. These are done one after another
|
||||
* starting with checking the database function exists in PHP, and
|
||||
* continuing onto more difficult checks like database permissions.
|
||||
*
|
||||
* @param array $databaseConfig The list of database parameters
|
||||
* @return boolean Validity of database configuration details
|
||||
*/
|
||||
public function checkDatabase($databaseConfig)
|
||||
{
|
||||
// Check if support is available
|
||||
if (!$this->requireDatabaseFunctions(
|
||||
$databaseConfig,
|
||||
array(
|
||||
"Database Configuration",
|
||||
"Database support",
|
||||
"Database support in PHP",
|
||||
$this->getDatabaseTypeNice($databaseConfig['type'])
|
||||
)
|
||||
)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$path = empty($databaseConfig['path']) ? null : $databaseConfig['path'];
|
||||
$server = empty($databaseConfig['server']) ? null : $databaseConfig['server'];
|
||||
|
||||
// Check if the server is available
|
||||
$usePath = $path && empty($server);
|
||||
if (!$this->requireDatabaseServer(
|
||||
$databaseConfig,
|
||||
array(
|
||||
"Database Configuration",
|
||||
"Database server",
|
||||
$usePath
|
||||
? "I couldn't write to path '{$path}'"
|
||||
: "I couldn't find a database server on '{$server}'",
|
||||
$usePath
|
||||
? $path
|
||||
: $server
|
||||
)
|
||||
)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the connection credentials allow access to the server / database
|
||||
if (!$this->requireDatabaseConnection(
|
||||
$databaseConfig,
|
||||
array(
|
||||
"Database Configuration",
|
||||
"Database access credentials",
|
||||
"That username/password doesn't work"
|
||||
)
|
||||
)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check the necessary server version is available
|
||||
if (!$this->requireDatabaseVersion(
|
||||
$databaseConfig,
|
||||
array(
|
||||
"Database Configuration",
|
||||
"Database server version requirement",
|
||||
'',
|
||||
'Version ' . $this->getDatabaseConfigurationHelper($databaseConfig['type'])->getDatabaseVersion($databaseConfig)
|
||||
)
|
||||
)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check that database creation permissions are available
|
||||
if (!$this->requireDatabaseOrCreatePermissions(
|
||||
$databaseConfig,
|
||||
array(
|
||||
"Database Configuration",
|
||||
"Can I access/create the database",
|
||||
"I can't create new databases and the database '$databaseConfig[database]' doesn't exist"
|
||||
)
|
||||
)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check alter permission (necessary to create tables etc)
|
||||
if (!$this->requireDatabaseAlterPermissions(
|
||||
$databaseConfig,
|
||||
array(
|
||||
"Database Configuration",
|
||||
"Can I ALTER tables",
|
||||
"I don't have permission to ALTER tables"
|
||||
)
|
||||
)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Success!
|
||||
return true;
|
||||
}
|
||||
|
||||
public function checkAdminConfig($adminConfig)
|
||||
{
|
||||
if (!$adminConfig['username']) {
|
||||
$this->error(array('', 'Please enter a username!'));
|
||||
}
|
||||
if (!$adminConfig['password']) {
|
||||
$this->error(array('', 'Please enter a password!'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check everything except the database
|
||||
*
|
||||
* @param array $originalIni
|
||||
* @return array
|
||||
*/
|
||||
public function check($originalIni)
|
||||
{
|
||||
$this->originalIni = $originalIni;
|
||||
$this->errors = [];
|
||||
$isApache = $this->isApache();
|
||||
$isIIS = $this->isIIS();
|
||||
$webserver = $this->findWebserver();
|
||||
|
||||
// Get project dirs to inspect
|
||||
$projectDir = $this->getProjectDir();
|
||||
$projectSrcDir = $this->getProjectSrcDir();
|
||||
|
||||
$this->requirePHPVersion('5.5.0', '5.5.0', array(
|
||||
"PHP Configuration",
|
||||
"PHP5 installed",
|
||||
null,
|
||||
"PHP version " . phpversion()
|
||||
));
|
||||
|
||||
// Check that we can identify the root folder successfully
|
||||
$this->requireFile('vendor/silverstripe/framework/src/Dev/Install/config-form.html', array(
|
||||
"File permissions",
|
||||
"Does the webserver know where files are stored?",
|
||||
"The webserver isn't letting me identify where files are stored.",
|
||||
$this->getBaseDir()
|
||||
));
|
||||
|
||||
$this->requireModule($projectDir, [
|
||||
"File permissions",
|
||||
"{$projectDir}/ directory exists?",
|
||||
''
|
||||
]);
|
||||
$this->requireModule('vendor/silverstripe/framework', array(
|
||||
"File permissions",
|
||||
"vendor/silverstripe/framework/ directory exists?",
|
||||
'',
|
||||
));
|
||||
|
||||
|
||||
$this->requireWriteable(
|
||||
$this->getPublicDir() . 'index.php',
|
||||
[
|
||||
"File permissions",
|
||||
"Is the index.php file writeable?",
|
||||
null,
|
||||
],
|
||||
true
|
||||
);
|
||||
|
||||
$this->requireWriteable('.env', ["File permissions", "Is the .env file writeable?", null], false, false);
|
||||
|
||||
if ($isApache) {
|
||||
$this->checkApacheVersion(array(
|
||||
"Webserver Configuration",
|
||||
"Webserver is not Apache 1.x",
|
||||
"SilverStripe requires Apache version 2 or greater",
|
||||
$webserver
|
||||
));
|
||||
$this->requireWriteable(
|
||||
$this->getPublicDir() . '.htaccess',
|
||||
array("File permissions", "Is the .htaccess file writeable?", null),
|
||||
true
|
||||
);
|
||||
} elseif ($isIIS) {
|
||||
$this->requireWriteable(
|
||||
$this->getPublicDir() . 'web.config',
|
||||
array("File permissions", "Is the web.config file writeable?", null),
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
$this->requireWriteable("{$projectDir}/_config.php", [
|
||||
"File permissions",
|
||||
"Is the {$projectDir}/_config.php file writeable?",
|
||||
null,
|
||||
]);
|
||||
|
||||
$this->requireWriteable("{$projectDir}/_config/theme.yml", [
|
||||
"File permissions",
|
||||
"Is the {$projectDir}/_config/theme.yml file writeable?",
|
||||
null,
|
||||
]);
|
||||
|
||||
if (!$this->checkModuleExists('cms')) {
|
||||
$this->requireWriteable("{$projectSrcDir}/RootURLController.php", [
|
||||
"File permissions",
|
||||
"Is the {$projectSrcDir}/RootURLController.php file writeable?",
|
||||
null,
|
||||
]);
|
||||
}
|
||||
|
||||
// Check public folder exists
|
||||
$this->requireFile(
|
||||
'public',
|
||||
[
|
||||
'File permissions',
|
||||
'Is there a public/ directory?',
|
||||
'It is recommended to have a separate public/ web directory',
|
||||
],
|
||||
false,
|
||||
false
|
||||
);
|
||||
|
||||
// Ensure root assets dir is writable
|
||||
$this->requireWriteable(
|
||||
ASSETS_PATH,
|
||||
array("File permissions", "Is the assets/ directory writeable?", null),
|
||||
true
|
||||
);
|
||||
// Make sure asset path actually exists
|
||||
if (!file_exists(ASSETS_PATH)) {
|
||||
mkdir(ASSETS_PATH);
|
||||
}
|
||||
|
||||
// Ensure all assets files are writable
|
||||
$innerIterator = new RecursiveDirectoryIterator(ASSETS_PATH, RecursiveDirectoryIterator::SKIP_DOTS);
|
||||
$iterator = new RecursiveIteratorIterator($innerIterator, RecursiveIteratorIterator::SELF_FIRST);
|
||||
/** @var SplFileInfo $file */
|
||||
foreach ($iterator as $file) {
|
||||
// Only report file as error if not writable
|
||||
if ($file->isWritable()) {
|
||||
continue;
|
||||
}
|
||||
$relativePath = substr($file->getPathname(), strlen($this->getBaseDir()));
|
||||
$message = $file->isDir()
|
||||
? "Is the {$relativePath} directory writeable?"
|
||||
: "Is the {$relativePath} file writeable?";
|
||||
$this->requireWriteable($relativePath, array("File permissions", $message, null));
|
||||
}
|
||||
|
||||
try {
|
||||
$tempFolder = TempFolder::getTempFolder($this->getBaseDir());
|
||||
} catch (Exception $e) {
|
||||
$tempFolder = false;
|
||||
}
|
||||
|
||||
$this->requireTempFolder(array('File permissions', 'Is a temporary directory available?', null, $tempFolder));
|
||||
if ($tempFolder) {
|
||||
// in addition to the temp folder being available, check it is writable
|
||||
$this->requireWriteable($tempFolder, array(
|
||||
"File permissions",
|
||||
sprintf("Is the temporary directory writeable?", $tempFolder),
|
||||
null
|
||||
), true);
|
||||
}
|
||||
|
||||
// Check for web server, unless we're calling the installer from the command-line
|
||||
$this->isRunningWebServer(array("Webserver Configuration", "Server software", "Unknown", $webserver));
|
||||
|
||||
if ($isApache) {
|
||||
$this->requireApacheRewriteModule('mod_rewrite', array(
|
||||
"Webserver Configuration",
|
||||
"URL rewriting support",
|
||||
"You need mod_rewrite to use friendly URLs with SilverStripe, but it is not enabled."
|
||||
));
|
||||
} elseif ($isIIS) {
|
||||
$this->requireIISRewriteModule('IIS_UrlRewriteModule', array(
|
||||
"Webserver Configuration",
|
||||
"URL rewriting support",
|
||||
"You need to enable the IIS URL Rewrite Module to use friendly URLs with SilverStripe, "
|
||||
. "but it is not installed or enabled. Download it for IIS 7 from http://www.iis.net/expand/URLRewrite"
|
||||
));
|
||||
} else {
|
||||
$this->warning(array(
|
||||
"Webserver Configuration",
|
||||
"URL rewriting support",
|
||||
"I can't tell whether any rewriting module is running. You may need to configure a rewriting rule yourself."
|
||||
));
|
||||
}
|
||||
|
||||
$this->requireServerVariables(array('SCRIPT_NAME', 'HTTP_HOST', 'SCRIPT_FILENAME'), array(
|
||||
"Webserver Configuration",
|
||||
"Recognised webserver",
|
||||
"You seem to be using an unsupported webserver. "
|
||||
. "The server variables SCRIPT_NAME, HTTP_HOST, SCRIPT_FILENAME need to be set."
|
||||
));
|
||||
|
||||
$this->requirePostSupport(array(
|
||||
"Webserver Configuration",
|
||||
"POST Support",
|
||||
'I can\'t find $_POST, make sure POST is enabled.'
|
||||
));
|
||||
|
||||
// Check for GD support
|
||||
if (!$this->requireFunction("imagecreatetruecolor", array(
|
||||
"PHP Configuration",
|
||||
"GD2 support",
|
||||
"PHP must have GD version 2."
|
||||
))
|
||||
) {
|
||||
$this->requireFunction("imagecreate", array(
|
||||
"PHP Configuration",
|
||||
"GD2 support",
|
||||
"GD support for PHP not included."
|
||||
));
|
||||
}
|
||||
|
||||
// Check for XML support
|
||||
$this->requireFunction('xml_set_object', array(
|
||||
"PHP Configuration",
|
||||
"XML support",
|
||||
"XML support not included in PHP."
|
||||
));
|
||||
$this->requireClass('DOMDocument', array(
|
||||
"PHP Configuration",
|
||||
"DOM/XML support",
|
||||
"DOM/XML support not included in PHP."
|
||||
));
|
||||
$this->requireFunction('simplexml_load_file', array(
|
||||
'PHP Configuration',
|
||||
'SimpleXML support',
|
||||
'SimpleXML support not included in PHP.'
|
||||
));
|
||||
|
||||
// Check for INTL support
|
||||
$this->requireClass('IntlTimeZone', array(
|
||||
'PHP Configuration',
|
||||
'Intl support',
|
||||
'Internationalization (php-intl) support not included in PHP.'
|
||||
));
|
||||
|
||||
// Check for token_get_all
|
||||
$this->requireFunction('token_get_all', array(
|
||||
"PHP Configuration",
|
||||
"Tokenizer support",
|
||||
"Tokenizer support not included in PHP."
|
||||
));
|
||||
|
||||
// Check for CType support
|
||||
$this->requireFunction('ctype_digit', array(
|
||||
'PHP Configuration',
|
||||
'CType support',
|
||||
'CType support not included in PHP.'
|
||||
));
|
||||
|
||||
// Check for session support
|
||||
$this->requireFunction('session_start', array(
|
||||
'PHP Configuration',
|
||||
'Session support',
|
||||
'Session support not included in PHP.'
|
||||
));
|
||||
|
||||
// Check for iconv support
|
||||
$this->requireFunction('iconv', array(
|
||||
'PHP Configuration',
|
||||
'iconv support',
|
||||
'iconv support not included in PHP.'
|
||||
));
|
||||
|
||||
// Check for hash support
|
||||
$this->requireFunction('hash', array('PHP Configuration', 'hash support', 'hash support not included in PHP.'));
|
||||
|
||||
// Check for mbstring support
|
||||
$this->requireFunction('mb_internal_encoding', array(
|
||||
'PHP Configuration',
|
||||
'mbstring support',
|
||||
'mbstring support not included in PHP.'
|
||||
));
|
||||
|
||||
// Check for Reflection support
|
||||
$this->requireClass('ReflectionClass', array(
|
||||
'PHP Configuration',
|
||||
'Reflection support',
|
||||
'Reflection support not included in PHP.'
|
||||
));
|
||||
|
||||
// Check for Standard PHP Library (SPL) support
|
||||
$this->requireFunction('spl_classes', array(
|
||||
'PHP Configuration',
|
||||
'SPL support',
|
||||
'Standard PHP Library (SPL) not included in PHP.'
|
||||
));
|
||||
|
||||
$this->requireDateTimezone(array(
|
||||
'PHP Configuration',
|
||||
'date.timezone setting and validity',
|
||||
'date.timezone option in php.ini must be set correctly.',
|
||||
$this->getOriginalIni('date.timezone')
|
||||
));
|
||||
|
||||
$this->suggestClass('finfo', array(
|
||||
'PHP Configuration',
|
||||
'fileinfo support',
|
||||
'fileinfo should be enabled in PHP. SilverStripe uses it for MIME type detection of files. '
|
||||
. 'SilverStripe will still operate, but email attachments and sending files to browser '
|
||||
. '(e.g. export data to CSV) may not work correctly without finfo.'
|
||||
));
|
||||
|
||||
$this->suggestFunction('curl_init', array(
|
||||
'PHP Configuration',
|
||||
'curl support',
|
||||
'curl should be enabled in PHP. SilverStripe uses it for consuming web services'
|
||||
. ' via the RestfulService class and many modules rely on it.'
|
||||
));
|
||||
|
||||
$this->suggestClass('tidy', array(
|
||||
'PHP Configuration',
|
||||
'tidy support',
|
||||
'Tidy provides a library of code to clean up your html. '
|
||||
. 'SilverStripe will operate fine without tidy but HTMLCleaner will not be effective.'
|
||||
));
|
||||
|
||||
$this->suggestPHPSetting('asp_tags', array(false), array(
|
||||
'PHP Configuration',
|
||||
'asp_tags option',
|
||||
'This should be turned off as it can cause issues with SilverStripe'
|
||||
));
|
||||
$this->requirePHPSetting('magic_quotes_gpc', array(false), array(
|
||||
'PHP Configuration',
|
||||
'magic_quotes_gpc option',
|
||||
'This should be turned off, as it can cause issues with cookies. '
|
||||
. 'More specifically, unserializing data stored in cookies.'
|
||||
));
|
||||
$this->suggestPHPSetting('display_errors', array(false), array(
|
||||
'PHP Configuration',
|
||||
'display_errors option',
|
||||
'Unless you\'re in a development environment, this should be turned off, '
|
||||
. 'as it can expose sensitive data to website users.'
|
||||
));
|
||||
// on some weirdly configured webservers arg_separator.output is set to &
|
||||
// which will results in links like ?param=value&foo=bar which will not be i
|
||||
$this->suggestPHPSetting('arg_separator.output', array('&', ''), array(
|
||||
'PHP Configuration',
|
||||
'arg_separator.output option',
|
||||
'This option defines how URL parameters are concatenated. '
|
||||
. 'If not set to \'&\' this may cause issues with URL GET parameters'
|
||||
));
|
||||
|
||||
// always_populate_raw_post_data should be set to -1 if PHP < 7.0
|
||||
if (version_compare(PHP_VERSION, '7.0.0', '<')) {
|
||||
$this->suggestPHPSetting('always_populate_raw_post_data', ['-1'], [
|
||||
'PHP Configuration',
|
||||
'always_populate_raw_post_data option',
|
||||
'It\'s highly recommended to set this to \'-1\' in php 5.x, as $HTTP_RAW_POST_DATA is removed in php 7'
|
||||
]);
|
||||
}
|
||||
|
||||
// Check memory allocation
|
||||
$this->requireMemory(32 * 1024 * 1024, 64 * 1024 * 1024, array(
|
||||
"PHP Configuration",
|
||||
"Memory allocation (PHP config option 'memory_limit')",
|
||||
"SilverStripe needs a minimum of 32M allocated to PHP, but recommends 64M.",
|
||||
$this->getOriginalIni("memory_limit")
|
||||
));
|
||||
|
||||
return $this->errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ini setting
|
||||
*
|
||||
* @param string $settingName
|
||||
* @return mixed
|
||||
*/
|
||||
protected function getOriginalIni($settingName)
|
||||
{
|
||||
if (isset($this->originalIni[$settingName])) {
|
||||
return $this->originalIni[$settingName];
|
||||
}
|
||||
return ini_get($settingName);
|
||||
}
|
||||
|
||||
public function suggestPHPSetting($settingName, $settingValues, $testDetails)
|
||||
{
|
||||
$this->testing($testDetails);
|
||||
|
||||
// special case for display_errors, check the original value before
|
||||
// it was changed at the start of this script.
|
||||
$val = $this->getOriginalIni($settingName);
|
||||
|
||||
if (!in_array($val, $settingValues) && $val != $settingValues) {
|
||||
$this->warning($testDetails, "$settingName is set to '$val' in php.ini. $testDetails[2]");
|
||||
}
|
||||
}
|
||||
|
||||
public function requirePHPSetting($settingName, $settingValues, $testDetails)
|
||||
{
|
||||
$this->testing($testDetails);
|
||||
|
||||
$val = $this->getOriginalIni($settingName);
|
||||
if (!in_array($val, $settingValues) && $val != $settingValues) {
|
||||
$this->error($testDetails, "$settingName is set to '$val' in php.ini. $testDetails[2]");
|
||||
}
|
||||
}
|
||||
|
||||
public function suggestClass($class, $testDetails)
|
||||
{
|
||||
$this->testing($testDetails);
|
||||
|
||||
if (!class_exists($class)) {
|
||||
$this->warning($testDetails);
|
||||
}
|
||||
}
|
||||
|
||||
public function suggestFunction($class, $testDetails)
|
||||
{
|
||||
$this->testing($testDetails);
|
||||
|
||||
if (!function_exists($class)) {
|
||||
$this->warning($testDetails);
|
||||
}
|
||||
}
|
||||
|
||||
public function requireDateTimezone($testDetails)
|
||||
{
|
||||
$this->testing($testDetails);
|
||||
$val = $this->getOriginalIni('date.timezone');
|
||||
$result = $val && in_array($val, timezone_identifiers_list());
|
||||
if (!$result) {
|
||||
$this->error($testDetails);
|
||||
}
|
||||
}
|
||||
|
||||
public function requireMemory($min, $recommended, $testDetails)
|
||||
{
|
||||
$_SESSION['forcemem'] = false;
|
||||
|
||||
$mem = $this->getPHPMemory();
|
||||
$memLimit = $this->getOriginalIni("memory_limit");
|
||||
if ($mem < (64 * 1024 * 1024)) {
|
||||
ini_set('memory_limit', '64M');
|
||||
$mem = $this->getPHPMemory();
|
||||
$testDetails[3] = $memLimit;
|
||||
}
|
||||
|
||||
$this->testing($testDetails);
|
||||
|
||||
if ($mem < $min && $mem > 0) {
|
||||
$message = $testDetails[2] . " You only have " . $memLimit . " allocated";
|
||||
$this->error($testDetails, $message);
|
||||
return false;
|
||||
} elseif ($mem < $recommended && $mem > 0) {
|
||||
$message = $testDetails[2] . " You only have " . $memLimit . " allocated";
|
||||
$this->warning($testDetails, $message);
|
||||
return false;
|
||||
} elseif ($mem == 0) {
|
||||
$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.";
|
||||
$this->warning($testDetails, $message);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getPHPMemory()
|
||||
{
|
||||
$memString = $this->getOriginalIni("memory_limit");
|
||||
|
||||
switch (strtolower(substr($memString, -1))) {
|
||||
case "k":
|
||||
return round(substr($memString, 0, -1) * 1024);
|
||||
|
||||
case "m":
|
||||
return round(substr($memString, 0, -1) * 1024 * 1024);
|
||||
|
||||
case "g":
|
||||
return round(substr($memString, 0, -1) * 1024 * 1024 * 1024);
|
||||
|
||||
default:
|
||||
return round($memString);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function listErrors()
|
||||
{
|
||||
if ($this->errors) {
|
||||
echo "<p>The following problems are preventing me from installing SilverStripe CMS:</p>\n\n";
|
||||
foreach ($this->errors as $error) {
|
||||
echo "<li>" . htmlentities(implode(", ", $error), ENT_COMPAT, 'UTF-8') . "</li>\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function showTable($section = null)
|
||||
{
|
||||
if ($section) {
|
||||
$tests = $this->tests[$section];
|
||||
$id = strtolower(str_replace(' ', '_', $section));
|
||||
echo "<table id=\"{$id}_results\" class=\"testResults\" width=\"100%\">";
|
||||
foreach ($tests as $test => $result) {
|
||||
echo "<tr class=\"$result[0]\"><td>$test</td><td>"
|
||||
. nl2br(htmlentities($result[1], ENT_COMPAT, 'UTF-8')) . "</td></tr>";
|
||||
}
|
||||
echo "</table>";
|
||||
} else {
|
||||
foreach ($this->tests as $section => $tests) {
|
||||
$failedRequirements = 0;
|
||||
$warningRequirements = 0;
|
||||
|
||||
$output = "";
|
||||
|
||||
foreach ($tests as $test => $result) {
|
||||
if (isset($result['0'])) {
|
||||
switch ($result['0']) {
|
||||
case 'error':
|
||||
$failedRequirements++;
|
||||
break;
|
||||
case 'warning':
|
||||
$warningRequirements++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$output .= "<tr class=\"$result[0]\"><td>$test</td><td>"
|
||||
. nl2br(htmlentities($result[1], ENT_COMPAT, 'UTF-8')) . "</td></tr>";
|
||||
}
|
||||
$className = "good";
|
||||
$text = "All Requirements Pass";
|
||||
$pluralWarnings = ($warningRequirements == 1) ? 'Warning' : 'Warnings';
|
||||
|
||||
if ($failedRequirements > 0) {
|
||||
$className = "error";
|
||||
$pluralWarnings = ($warningRequirements == 1) ? 'Warning' : 'Warnings';
|
||||
|
||||
$text = $failedRequirements . ' Failed and ' . $warningRequirements . ' ' . $pluralWarnings;
|
||||
} elseif ($warningRequirements > 0) {
|
||||
$className = "warning";
|
||||
$text = "All Requirements Pass but " . $warningRequirements . ' ' . $pluralWarnings;
|
||||
}
|
||||
|
||||
echo "<h5 class='requirement $className'>$section <a href='#'>Show All Requirements</a> <span>$text</span></h5>";
|
||||
echo "<table class=\"testResults\">";
|
||||
echo $output;
|
||||
echo "</table>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function requireFunction($funcName, $testDetails)
|
||||
{
|
||||
$this->testing($testDetails);
|
||||
|
||||
if (!function_exists($funcName)) {
|
||||
$this->error($testDetails);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function requireClass($className, $testDetails)
|
||||
{
|
||||
$this->testing($testDetails);
|
||||
if (!class_exists($className)) {
|
||||
$this->error($testDetails);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Require that the given class doesn't exist
|
||||
*
|
||||
* @param array $classNames
|
||||
* @param array $testDetails
|
||||
* @return bool
|
||||
*/
|
||||
public function requireNoClasses($classNames, $testDetails)
|
||||
{
|
||||
$this->testing($testDetails);
|
||||
$badClasses = array();
|
||||
foreach ($classNames as $className) {
|
||||
if (class_exists($className)) {
|
||||
$badClasses[] = $className;
|
||||
}
|
||||
}
|
||||
if ($badClasses) {
|
||||
$message = $testDetails[2] . ". The following classes are at fault: " . implode(', ', $badClasses);
|
||||
$this->error($testDetails, $message);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function checkApacheVersion($testDetails)
|
||||
{
|
||||
$this->testing($testDetails);
|
||||
|
||||
$is1pointx = preg_match('#Apache[/ ]1\.#', $testDetails[3]);
|
||||
if ($is1pointx) {
|
||||
$this->error($testDetails);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function requirePHPVersion($recommendedVersion, $requiredVersion, $testDetails)
|
||||
{
|
||||
$this->testing($testDetails);
|
||||
|
||||
$installedVersion = phpversion();
|
||||
|
||||
if (version_compare($installedVersion, $requiredVersion, '<')) {
|
||||
$message = "SilverStripe requires PHP version $requiredVersion or later.\n
|
||||
PHP version $installedVersion is currently installed.\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.";
|
||||
$this->error($testDetails, $message);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (version_compare($installedVersion, $recommendedVersion, '<')) {
|
||||
$message = "PHP version $installedVersion is currently installed.\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";
|
||||
$this->warning($testDetails, $message);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* The same as {@link requireFile()} but does additional checks
|
||||
* to ensure the module directory is intact.
|
||||
*
|
||||
* @param string $dirname
|
||||
* @param array $testDetails
|
||||
*/
|
||||
public function requireModule($dirname, $testDetails)
|
||||
{
|
||||
$this->testing($testDetails);
|
||||
$path = $this->getBaseDir() . $dirname;
|
||||
if (!file_exists($path)) {
|
||||
$testDetails[2] .= " Directory '$path' not found. Please make sure you have uploaded the SilverStripe files to your webserver correctly.";
|
||||
$this->error($testDetails);
|
||||
} elseif (!file_exists($path . '/_config.php') && !in_array($dirname, ['mysite', 'app'])) {
|
||||
$testDetails[2] .= " Directory '$path' exists, but is missing files. Please make sure you have uploaded "
|
||||
. "the SilverStripe files to your webserver correctly.";
|
||||
$this->error($testDetails);
|
||||
}
|
||||
}
|
||||
|
||||
public function requireFile($filename, $testDetails, $absolute = false, $error = true)
|
||||
{
|
||||
$this->testing($testDetails);
|
||||
|
||||
if ($absolute) {
|
||||
$filename = Path::normalise($filename);
|
||||
} else {
|
||||
$filename = Path::join($this->getBaseDir(), $filename);
|
||||
}
|
||||
if (file_exists($filename)) {
|
||||
return;
|
||||
}
|
||||
$testDetails[2] .= " (file '$filename' not found)";
|
||||
if ($error) {
|
||||
$this->error($testDetails);
|
||||
} else {
|
||||
$this->warning($testDetails);
|
||||
}
|
||||
}
|
||||
|
||||
public function requireWriteable($filename, $testDetails, $absolute = false, $error = true)
|
||||
{
|
||||
$this->testing($testDetails);
|
||||
|
||||
if ($absolute) {
|
||||
$filename = Path::normalise($filename);
|
||||
} else {
|
||||
$filename = Path::join($this->getBaseDir(), $filename);
|
||||
}
|
||||
|
||||
if (file_exists($filename)) {
|
||||
$isWriteable = is_writeable($filename);
|
||||
} else {
|
||||
$isWriteable = is_writeable(dirname($filename));
|
||||
}
|
||||
|
||||
if ($isWriteable) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (function_exists('posix_getgroups')) {
|
||||
$userID = posix_geteuid();
|
||||
$user = posix_getpwuid($userID);
|
||||
|
||||
$currentOwnerID = fileowner(file_exists($filename) ? $filename : dirname($filename));
|
||||
$currentOwner = posix_getpwuid($currentOwnerID);
|
||||
|
||||
$testDetails[2] .= "User '$user[name]' needs to be able to write to this file:\n$filename\n\nThe "
|
||||
. "file is currently owned by '$currentOwner[name]'. ";
|
||||
|
||||
if ($user['name'] == $currentOwner['name']) {
|
||||
$testDetails[2] .= "We recommend that you make the file writeable.";
|
||||
} else {
|
||||
$groups = posix_getgroups();
|
||||
$groupList = array();
|
||||
foreach ($groups as $group) {
|
||||
$groupInfo = posix_getgrgid($group);
|
||||
if (in_array($currentOwner['name'], $groupInfo['members'])) {
|
||||
$groupList[] = $groupInfo['name'];
|
||||
}
|
||||
}
|
||||
if ($groupList) {
|
||||
$testDetails[2] .= " We recommend that you make the file group-writeable "
|
||||
. "and change the group to one of these groups:\n - " . implode("\n - ", $groupList)
|
||||
. "\n\nFor example:\nchmod g+w $filename\nchgrp " . $groupList[0] . " $filename";
|
||||
} else {
|
||||
$testDetails[2] .= " There is no user-group that contains both the web-server user and the "
|
||||
. "owner of this file. Change the ownership of the file, create a new group, or "
|
||||
. "temporarily make the file writeable by everyone during the install process.";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$testDetails[2] .= "The webserver user needs to be able to write to this file:\n$filename";
|
||||
}
|
||||
|
||||
if ($error) {
|
||||
$this->error($testDetails);
|
||||
} else {
|
||||
$this->warning($testDetails);
|
||||
}
|
||||
}
|
||||
|
||||
public function requireTempFolder($testDetails)
|
||||
{
|
||||
$this->testing($testDetails);
|
||||
|
||||
try {
|
||||
$tempFolder = TempFolder::getTempFolder($this->getBaseDir());
|
||||
} catch (Exception $e) {
|
||||
$tempFolder = false;
|
||||
}
|
||||
|
||||
if (!$tempFolder) {
|
||||
$testDetails[2] = "Permission problem gaining access to a temp directory. " .
|
||||
"Please create a folder named silverstripe-cache in the base directory " .
|
||||
"of the installation and ensure it has the adequate permissions.";
|
||||
$this->error($testDetails);
|
||||
}
|
||||
}
|
||||
|
||||
public function requireApacheModule($moduleName, $testDetails)
|
||||
{
|
||||
$this->testing($testDetails);
|
||||
if (!in_array($moduleName, apache_get_modules())) {
|
||||
$this->error($testDetails);
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public function requireApacheRewriteModule($moduleName, $testDetails)
|
||||
{
|
||||
$this->testing($testDetails);
|
||||
if ($this->testApacheRewriteExists()) {
|
||||
return true;
|
||||
} else {
|
||||
$this->error($testDetails);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function requireIISRewriteModule($moduleName, $testDetails)
|
||||
{
|
||||
$this->testing($testDetails);
|
||||
if ($this->testIISRewriteModuleExists()) {
|
||||
return true;
|
||||
} else {
|
||||
$this->warning($testDetails);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function requireDatabaseFunctions($databaseConfig, $testDetails)
|
||||
{
|
||||
$this->testing($testDetails);
|
||||
$helper = $this->getDatabaseConfigurationHelper($databaseConfig['type']);
|
||||
if (!$helper) {
|
||||
$this->error($testDetails, "Couldn't load database helper code for " . $databaseConfig['type']);
|
||||
return false;
|
||||
}
|
||||
$result = $helper->requireDatabaseFunctions($databaseConfig);
|
||||
if ($result) {
|
||||
return true;
|
||||
} else {
|
||||
$this->error($testDetails);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function requireDatabaseConnection($databaseConfig, $testDetails)
|
||||
{
|
||||
$this->testing($testDetails);
|
||||
$helper = $this->getDatabaseConfigurationHelper($databaseConfig['type']);
|
||||
$result = $helper->requireDatabaseConnection($databaseConfig);
|
||||
if ($result['success']) {
|
||||
return true;
|
||||
} else {
|
||||
$testDetails[2] .= ": " . $result['error'];
|
||||
$this->error($testDetails);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function requireDatabaseVersion($databaseConfig, $testDetails)
|
||||
{
|
||||
$this->testing($testDetails);
|
||||
$helper = $this->getDatabaseConfigurationHelper($databaseConfig['type']);
|
||||
if (method_exists($helper, 'requireDatabaseVersion')) {
|
||||
$result = $helper->requireDatabaseVersion($databaseConfig);
|
||||
if ($result['success']) {
|
||||
return true;
|
||||
} else {
|
||||
$testDetails[2] .= $result['error'];
|
||||
$this->warning($testDetails);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Skipped test because this database has no required version
|
||||
return true;
|
||||
}
|
||||
|
||||
public function requireDatabaseServer($databaseConfig, $testDetails)
|
||||
{
|
||||
$this->testing($testDetails);
|
||||
$helper = $this->getDatabaseConfigurationHelper($databaseConfig['type']);
|
||||
$result = $helper->requireDatabaseServer($databaseConfig);
|
||||
if ($result['success']) {
|
||||
return true;
|
||||
} else {
|
||||
$message = $testDetails[2] . ": " . $result['error'];
|
||||
$this->error($testDetails, $message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function requireDatabaseOrCreatePermissions($databaseConfig, $testDetails)
|
||||
{
|
||||
$this->testing($testDetails);
|
||||
$helper = $this->getDatabaseConfigurationHelper($databaseConfig['type']);
|
||||
$result = $helper->requireDatabaseOrCreatePermissions($databaseConfig);
|
||||
if ($result['success']) {
|
||||
if ($result['alreadyExists']) {
|
||||
$testDetails[3] = "Database $databaseConfig[database]";
|
||||
} else {
|
||||
$testDetails[3] = "Able to create a new database";
|
||||
}
|
||||
$this->testing($testDetails);
|
||||
return true;
|
||||
} else {
|
||||
if (empty($result['cannotCreate'])) {
|
||||
$message = $testDetails[2] . ". Please create the database manually.";
|
||||
} else {
|
||||
$message = $testDetails[2] . " (user '$databaseConfig[username]' doesn't have CREATE DATABASE permissions.)";
|
||||
}
|
||||
|
||||
$this->error($testDetails, $message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function requireDatabaseAlterPermissions($databaseConfig, $testDetails)
|
||||
{
|
||||
$this->testing($testDetails);
|
||||
$helper = $this->getDatabaseConfigurationHelper($databaseConfig['type']);
|
||||
$result = $helper->requireDatabaseAlterPermissions($databaseConfig);
|
||||
if ($result['success']) {
|
||||
return true;
|
||||
} else {
|
||||
$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.";
|
||||
$this->warning($testDetails, $message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function requireServerVariables($varNames, $testDetails)
|
||||
{
|
||||
$this->testing($testDetails);
|
||||
$missing = array();
|
||||
|
||||
foreach ($varNames as $varName) {
|
||||
if (!isset($_SERVER[$varName]) || !$_SERVER[$varName]) {
|
||||
$missing[] = '$_SERVER[' . $varName . ']';
|
||||
}
|
||||
}
|
||||
|
||||
if (!$missing) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$message = $testDetails[2] . " (the following PHP variables are missing: " . implode(", ", $missing) . ")";
|
||||
$this->error($testDetails, $message);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public function requirePostSupport($testDetails)
|
||||
{
|
||||
$this->testing($testDetails);
|
||||
|
||||
if (!isset($_POST)) {
|
||||
$this->error($testDetails);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function isRunningWebServer($testDetails)
|
||||
{
|
||||
$this->testing($testDetails);
|
||||
if ($testDetails[3]) {
|
||||
return true;
|
||||
} else {
|
||||
$this->warning($testDetails);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function testing($testDetails)
|
||||
{
|
||||
if (!$testDetails) {
|
||||
return;
|
||||
}
|
||||
|
||||
$section = $testDetails[0];
|
||||
$test = $testDetails[1];
|
||||
|
||||
$message = "OK";
|
||||
if (isset($testDetails[3])) {
|
||||
$message .= " ($testDetails[3])";
|
||||
}
|
||||
|
||||
$this->tests[$section][$test] = array("good", $message);
|
||||
}
|
||||
|
||||
public function error($testDetails, $message = null)
|
||||
{
|
||||
if (!is_array($testDetails)) {
|
||||
throw new InvalidArgumentException("Invalid error");
|
||||
}
|
||||
$section = $testDetails[0];
|
||||
$test = $testDetails[1];
|
||||
if (!$message && isset($testDetails[2])) {
|
||||
$message = $testDetails[2];
|
||||
}
|
||||
|
||||
$this->tests[$section][$test] = array("error", $message);
|
||||
$this->errors[] = $testDetails;
|
||||
}
|
||||
|
||||
public function warning($testDetails, $message = null)
|
||||
{
|
||||
if (!is_array($testDetails)) {
|
||||
throw new InvalidArgumentException("Invalid warning");
|
||||
}
|
||||
$section = $testDetails[0];
|
||||
$test = $testDetails[1];
|
||||
if (!$message && isset($testDetails[2])) {
|
||||
$message = $testDetails[2];
|
||||
}
|
||||
|
||||
$this->tests[$section][$test] = array("warning", $message);
|
||||
$this->warnings[] = $testDetails;
|
||||
}
|
||||
|
||||
public function hasErrors()
|
||||
{
|
||||
return sizeof($this->errors);
|
||||
}
|
||||
|
||||
public function hasWarnings()
|
||||
{
|
||||
return sizeof($this->warnings);
|
||||
}
|
||||
}
|
@ -1,687 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Dev\Install;
|
||||
|
||||
use Exception;
|
||||
use SilverStripe\Control\Cookie;
|
||||
use SilverStripe\Control\HTTPApplication;
|
||||
use SilverStripe\Control\HTTPRequest;
|
||||
use SilverStripe\Control\HTTPRequestBuilder;
|
||||
use SilverStripe\Core\Convert;
|
||||
use SilverStripe\Core\CoreKernel;
|
||||
use SilverStripe\Core\EnvironmentLoader;
|
||||
use SilverStripe\Core\Kernel;
|
||||
use SilverStripe\Core\Path;
|
||||
use SilverStripe\ORM\DatabaseAdmin;
|
||||
use SilverStripe\Security\DefaultAdminService;
|
||||
use SilverStripe\Security\Security;
|
||||
use SilverStripe\Control\Middleware\URLSpecialsMiddleware\SessionEnvTypeSwitcher;
|
||||
|
||||
/**
|
||||
* This installer doesn't use any of the fancy SilverStripe stuff in case it's unsupported.
|
||||
*/
|
||||
class Installer
|
||||
{
|
||||
use InstallEnvironmentAware;
|
||||
use SessionEnvTypeSwitcher;
|
||||
|
||||
/**
|
||||
* Errors during install
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $errors = [];
|
||||
|
||||
/**
|
||||
* value='' attribute placeholder for password fields
|
||||
*/
|
||||
const PASSWORD_PLACEHOLDER = '********';
|
||||
|
||||
public function __construct($basePath = null)
|
||||
{
|
||||
$this->initBaseDir($basePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Installer error
|
||||
*
|
||||
* @param string $message
|
||||
*/
|
||||
protected function error($message = null)
|
||||
{
|
||||
$this->errors[] = $message;
|
||||
}
|
||||
|
||||
protected function installHeader()
|
||||
{
|
||||
$clientPath = RESOURCES_DIR . (PUBLIC_DIR
|
||||
? '/vendor/silverstripe/framework/src/Dev/Install/client'
|
||||
: '/silverstripe/framework/src/Dev/Install/client');
|
||||
?>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>Installing SilverStripe...</title>
|
||||
<link rel="stylesheet" type="text/css" href="<?=$clientPath; ?>/styles/install.css"/>
|
||||
<script src="//code.jquery.com/jquery-1.7.2.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="install-header">
|
||||
<div class="inner">
|
||||
<div class="brand">
|
||||
<h1>SilverStripe</h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="Navigation"> </div>
|
||||
<div class="clear"><!-- --></div>
|
||||
|
||||
<div class="main">
|
||||
<div class="inner">
|
||||
<h2>Installing SilverStripe...</h2>
|
||||
|
||||
<p>I am now running through the installation steps (this should take about 30 seconds)</p>
|
||||
|
||||
<p>If you receive a fatal error, refresh this page to continue the installation</p>
|
||||
<ul>
|
||||
<?php
|
||||
}
|
||||
|
||||
public function install($config)
|
||||
{
|
||||
// Render header
|
||||
$this->installHeader();
|
||||
$isIIS = $this->isIIS();
|
||||
$isApache = $this->isApache();
|
||||
$projectDir = $this->getProjectDir();
|
||||
$projectSrcDir = $this->getProjectSrcDir();
|
||||
|
||||
flush();
|
||||
|
||||
// Send install stats
|
||||
if (!empty($config['stats'])) {
|
||||
$this->sendInstallStats($config);
|
||||
}
|
||||
|
||||
// Cleanup _config.php
|
||||
$basePath = $this->getBaseDir();
|
||||
$appConfigPath = $basePath . "{$projectDir}/_config.php";
|
||||
if (file_exists($appConfigPath)) {
|
||||
// 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
|
||||
$fh = fopen($appConfigPath, 'wb');
|
||||
fclose($fh);
|
||||
}
|
||||
|
||||
// Write all files
|
||||
$this->writeIndexPHP();
|
||||
$this->writeConfigPHP($config);
|
||||
$this->writeConfigYaml($config);
|
||||
$this->writeConfigEnv($config);
|
||||
|
||||
// Write other stuff
|
||||
if (!$this->checkModuleExists('cms')) {
|
||||
$rootURLControllerPath = $basePath . "{$projectSrcDir}/RootURLController.php";
|
||||
$this->writeToFile($rootURLControllerPath, <<<PHP
|
||||
<?php
|
||||
|
||||
use SilverStripe\\Control\\Controller;
|
||||
|
||||
class RootURLController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
echo "<html>Your site is now set up. Start adding controllers to app/src to get started.</html>";
|
||||
}
|
||||
}
|
||||
PHP
|
||||
);
|
||||
}
|
||||
|
||||
// Write the appropriate web server configuration file for rewriting support
|
||||
if ($this->hasRewritingCapability()) {
|
||||
if ($isApache) {
|
||||
$this->createHtaccess();
|
||||
} elseif ($isIIS) {
|
||||
$this->createWebConfig();
|
||||
}
|
||||
}
|
||||
|
||||
// Build request
|
||||
$request = HTTPRequestBuilder::createFromEnvironment();
|
||||
|
||||
// Install kernel (fix to dev)
|
||||
$kernel = new CoreKernel(Path::normalise($basePath));
|
||||
$kernel->setEnvironment(Kernel::DEV);
|
||||
$app = new HTTPApplication($kernel);
|
||||
|
||||
// Build db within HTTPApplication
|
||||
$app->execute($request, function (HTTPRequest $request) use ($config) {
|
||||
// Suppress cookie errors on install
|
||||
Cookie::config()->set('report_errors', false);
|
||||
|
||||
// Start session and execute
|
||||
$request->getSession()->init($request);
|
||||
|
||||
// Output status
|
||||
$this->statusMessage("Building database schema...");
|
||||
|
||||
// Setup DB
|
||||
$dbAdmin = new DatabaseAdmin();
|
||||
$dbAdmin->setRequest($request);
|
||||
$dbAdmin->pushCurrent();
|
||||
$dbAdmin->doInit();
|
||||
$dbAdmin->doBuild(true);
|
||||
|
||||
// Create default administrator user and group in database
|
||||
// (not using Security::setDefaultAdmin())
|
||||
$username = $config['admin']['username'];
|
||||
$password = $config['admin']['password'];
|
||||
$adminMember = DefaultAdminService::singleton()
|
||||
->findOrCreateAdmin(
|
||||
$username,
|
||||
_t('SilverStripe\\Security\\DefaultAdminService.DefaultAdminFirstname', 'Default Admin')
|
||||
);
|
||||
$adminMember->Email = $username;
|
||||
$adminMember->Password = $password;
|
||||
$adminMember->PasswordEncryption = Security::config()->get('encryption_algorithm');
|
||||
|
||||
try {
|
||||
$this->statusMessage('Creating default CMS admin account...');
|
||||
$adminMember->write();
|
||||
} catch (Exception $e) {
|
||||
$this->statusMessage(
|
||||
sprintf('Warning: Default CMS admin account could not be created (error: %s)', $e->getMessage())
|
||||
);
|
||||
}
|
||||
|
||||
$request->getSession()->set('username', $username);
|
||||
$request->getSession()->set('password', $password);
|
||||
$request->getSession()->save($request);
|
||||
}, true);
|
||||
|
||||
// Check result of install
|
||||
if (!$this->errors) {
|
||||
// switch the session to Dev mode so that
|
||||
// flush does not require authentication
|
||||
// for the first time after installation
|
||||
$request['isDev'] = '1';
|
||||
$this->setSessionEnvType($request);
|
||||
unset($request['isDev']);
|
||||
$request->getSession()->save($request);
|
||||
|
||||
if (isset($_SERVER['HTTP_HOST']) && $this->hasRewritingCapability()) {
|
||||
$this->statusMessage("Checking that friendly URLs work...");
|
||||
$this->checkRewrite();
|
||||
} else {
|
||||
$params = http_build_query($request->getVars() + ['flush' => '']);
|
||||
|
||||
$destinationURL = 'index.php/' .
|
||||
($this->checkModuleExists('cms') ? "home/successfullyinstalled?$params" : "?$params");
|
||||
|
||||
echo <<<HTML
|
||||
<li>SilverStripe successfully installed; I am now redirecting you to your SilverStripe site...</li>
|
||||
<script>
|
||||
setTimeout(function() {
|
||||
window.location = "$destinationURL";
|
||||
}, 2000);
|
||||
</script>
|
||||
<noscript>
|
||||
<li><a href="$destinationURL">Click here to access your site.</a></li>
|
||||
</noscript>
|
||||
HTML;
|
||||
}
|
||||
} else {
|
||||
// Output all errors
|
||||
$this->statusMessage('Encountered ' . count($this->errors) . ' errors during install:');
|
||||
echo "<ul>";
|
||||
foreach ($this->errors as $error) {
|
||||
$this->statusMessage($error);
|
||||
}
|
||||
echo "</ul>";
|
||||
$this->statusMessage('Please <a href="install.php">Click here</a> to return to the installer.');
|
||||
}
|
||||
|
||||
return $this->errors;
|
||||
}
|
||||
|
||||
protected function writeIndexPHP()
|
||||
{
|
||||
$content = <<<'PHP'
|
||||
<?php
|
||||
|
||||
use SilverStripe\Control\HTTPApplication;
|
||||
use SilverStripe\Control\HTTPRequestBuilder;
|
||||
use SilverStripe\Core\CoreKernel;
|
||||
|
||||
// Find autoload.php
|
||||
if (file_exists(__DIR__ . '/vendor/autoload.php')) {
|
||||
require __DIR__ . '/vendor/autoload.php';
|
||||
} elseif (file_exists(__DIR__ . '/../vendor/autoload.php')) {
|
||||
require __DIR__ . '/../vendor/autoload.php';
|
||||
} else {
|
||||
echo "autoload.php not found";
|
||||
die;
|
||||
}
|
||||
|
||||
// Build request and detect flush
|
||||
$request = HTTPRequestBuilder::createFromEnvironment();
|
||||
|
||||
// Default application
|
||||
$kernel = new CoreKernel(BASE_PATH);
|
||||
$app = new HTTPApplication($kernel);
|
||||
$response = $app->handle($request);
|
||||
$response->output();
|
||||
PHP;
|
||||
$path = $this->getPublicDir() . 'index.php';
|
||||
$this->writeToFile($path, $content, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write all .env files
|
||||
*
|
||||
* @param $config
|
||||
*/
|
||||
protected function writeConfigEnv($config)
|
||||
{
|
||||
if (!$config['usingEnv']) {
|
||||
return;
|
||||
}
|
||||
|
||||
$path = $this->getBaseDir() . '.env';
|
||||
$vars = [];
|
||||
|
||||
// Retain existing vars
|
||||
$env = new EnvironmentLoader();
|
||||
if (file_exists($path)) {
|
||||
$vars = $env->loadFile($path) ?: [];
|
||||
}
|
||||
|
||||
// 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
|
||||
$env->loadFile($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write all *.php files
|
||||
*
|
||||
* @param array $config
|
||||
*/
|
||||
protected function writeConfigPHP($config)
|
||||
{
|
||||
$configPath = $this->getProjectDir() . DIRECTORY_SEPARATOR . "_config.php";
|
||||
if ($config['usingEnv']) {
|
||||
$this->writeToFile($configPath, "<?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($configPath, <<<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']);
|
||||
$projectDir = $this->getProjectDir();
|
||||
|
||||
// Set either specified, or no theme
|
||||
if ($config['theme'] && $config['theme'] !== 'tutorial') {
|
||||
$theme = $this->ymlString($config['theme']);
|
||||
$themeYML = <<<YML
|
||||
- '\$public'
|
||||
- '$theme'
|
||||
- '\$default'
|
||||
YML;
|
||||
} else {
|
||||
$themeYML = <<<YML
|
||||
- '\$public'
|
||||
- '\$default'
|
||||
YML;
|
||||
}
|
||||
|
||||
// Write theme.yml
|
||||
$this->writeToFile("{$projectDir}/_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 string $filename
|
||||
* @param string $content
|
||||
* @param bool $absolute If $filename is absolute path set to true
|
||||
* @return bool
|
||||
*/
|
||||
public function writeToFile($filename, $content, $absolute = false)
|
||||
{
|
||||
// Get absolute / relative paths by either combining or removing base from path
|
||||
list($absolutePath, $relativePath) = $absolute
|
||||
? [
|
||||
$filename,
|
||||
substr($filename, strlen($this->getBaseDir()))]
|
||||
: [
|
||||
$this->getBaseDir() . $filename,
|
||||
$filename
|
||||
];
|
||||
$this->statusMessage("Setting up $relativePath");
|
||||
|
||||
if ((@$fh = fopen($absolutePath, 'wb')) && fwrite($fh, $content) && fclose($fh)) {
|
||||
// Set permissions to writable
|
||||
@chmod($absolutePath, 0775);
|
||||
return true;
|
||||
}
|
||||
$this->error("Couldn't write to file $relativePath");
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure root .htaccess is setup
|
||||
*/
|
||||
public function createHtaccess()
|
||||
{
|
||||
$start = "### SILVERSTRIPE START ###\n";
|
||||
$end = "\n### SILVERSTRIPE END ###";
|
||||
|
||||
$base = dirname($_SERVER['SCRIPT_NAME']);
|
||||
$base = Convert::slashes($base, '/');
|
||||
|
||||
if ($base != '.') {
|
||||
$baseClause = "RewriteBase '$base'\n";
|
||||
} else {
|
||||
$baseClause = "";
|
||||
}
|
||||
if (strpos(strtolower(php_sapi_name()), "cgi") !== false) {
|
||||
$cgiClause = "RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]\n";
|
||||
} else {
|
||||
$cgiClause = "";
|
||||
}
|
||||
$rewrite = <<<TEXT
|
||||
# Deny access to templates (but allow from localhost)
|
||||
<Files *.ss>
|
||||
Order deny,allow
|
||||
Deny from all
|
||||
Allow from 127.0.0.1
|
||||
</Files>
|
||||
|
||||
# Deny access to IIS configuration
|
||||
<Files web.config>
|
||||
Order deny,allow
|
||||
Deny from all
|
||||
</Files>
|
||||
|
||||
# Deny access to YAML configuration files which might include sensitive information
|
||||
<Files ~ "\.ya?ml$">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
</Files>
|
||||
|
||||
# Route errors to static pages automatically generated by SilverStripe
|
||||
ErrorDocument 404 /assets/error-404.html
|
||||
ErrorDocument 500 /assets/error-500.html
|
||||
|
||||
<IfModule mod_rewrite.c>
|
||||
|
||||
# Turn off index.php handling requests to the homepage fixes issue in apache >=2.4
|
||||
<IfModule mod_dir.c>
|
||||
DirectoryIndex disabled
|
||||
DirectorySlash On
|
||||
</IfModule>
|
||||
|
||||
SetEnv HTTP_MOD_REWRITE On
|
||||
RewriteEngine On
|
||||
$baseClause
|
||||
$cgiClause
|
||||
|
||||
# Deny access to potentially sensitive files and folders
|
||||
RewriteRule ^vendor(/|$) - [F,L,NC]
|
||||
RewriteRule ^\.env - [F,L,NC]
|
||||
RewriteRule silverstripe-cache(/|$) - [F,L,NC]
|
||||
RewriteRule composer\.(json|lock) - [F,L,NC]
|
||||
RewriteRule (error|silverstripe|debug)\.log - [F,L,NC]
|
||||
|
||||
# Process through SilverStripe if no file with the requested name exists.
|
||||
# Pass through the original path as a query parameter, and retain the existing parameters.
|
||||
# Try finding framework in the vendor folder first
|
||||
RewriteCond %{REQUEST_URI} ^(.*)$
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteRule .* index.php
|
||||
</IfModule>
|
||||
TEXT;
|
||||
|
||||
$htaccessPath = $this->getPublicDir() . '.htaccess';
|
||||
if (file_exists($htaccessPath)) {
|
||||
$htaccess = file_get_contents($htaccessPath);
|
||||
|
||||
if (strpos($htaccess, '### SILVERSTRIPE START ###') === false
|
||||
&& strpos($htaccess, '### SILVERSTRIPE END ###') === false
|
||||
) {
|
||||
$htaccess .= "\n### SILVERSTRIPE START ###\n### SILVERSTRIPE END ###\n";
|
||||
}
|
||||
|
||||
if (strpos($htaccess, '### SILVERSTRIPE START ###') !== false
|
||||
&& strpos($htaccess, '### SILVERSTRIPE END ###') !== false
|
||||
) {
|
||||
$start = substr($htaccess, 0, strpos($htaccess, '### SILVERSTRIPE START ###'))
|
||||
. "### SILVERSTRIPE START ###\n";
|
||||
$end = "\n" . substr($htaccess, strpos($htaccess, '### SILVERSTRIPE END ###'));
|
||||
}
|
||||
}
|
||||
|
||||
$this->writeToFile($htaccessPath, $start . $rewrite . $end, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes basic configuration to the web.config for IIS
|
||||
* so that rewriting capability can be use.
|
||||
*/
|
||||
public function createWebConfig()
|
||||
{
|
||||
$content = <<<TEXT
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<system.webServer>
|
||||
<security>
|
||||
<requestFiltering>
|
||||
<hiddenSegments applyToWebDAV="false">
|
||||
<add segment="silverstripe-cache" />
|
||||
<add segment="composer.json" />
|
||||
<add segment="composer.lock" />
|
||||
</hiddenSegments>
|
||||
<fileExtensions allowUnlisted="true" >
|
||||
<add fileExtension=".ss" allowed="false"/>
|
||||
<add fileExtension=".yml" allowed="false"/>
|
||||
</fileExtensions>
|
||||
</requestFiltering>
|
||||
</security>
|
||||
<rewrite>
|
||||
<rules>
|
||||
<rule name="SilverStripe Clean URLs" stopProcessing="true">
|
||||
<match url="^(.*)$" />
|
||||
<conditions>
|
||||
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
|
||||
</conditions>
|
||||
<action type="Rewrite" url="index.php" appendQueryString="true" />
|
||||
</rule>
|
||||
</rules>
|
||||
</rewrite>
|
||||
</system.webServer>
|
||||
</configuration>
|
||||
TEXT;
|
||||
|
||||
$path = $this->getPublicDir() . 'web.config';
|
||||
$this->writeToFile($path, $content, true);
|
||||
}
|
||||
|
||||
public function checkRewrite()
|
||||
{
|
||||
$params = http_build_query(['flush' => '']);
|
||||
|
||||
$destinationURL = rtrim(BASE_URL, '/') . '/' . (
|
||||
$this->checkModuleExists('cms')
|
||||
? "home/successfullyinstalled?$params"
|
||||
: "?$params"
|
||||
);
|
||||
|
||||
echo <<<HTML
|
||||
<li id="ModRewriteResult">Testing...</li>
|
||||
<script>
|
||||
if (typeof $ == 'undefined') {
|
||||
document.getElementById('ModeRewriteResult').innerHTML = "I can't run jQuery ajax to set rewriting; I will redirect you to the homepage to see if everything is working.";
|
||||
setTimeout(function() {
|
||||
window.location = "$destinationURL";
|
||||
}, 10000);
|
||||
} else {
|
||||
$.ajax({
|
||||
method: 'get',
|
||||
url: 'InstallerTest/testrewrite',
|
||||
complete: function(response) {
|
||||
var r = response.responseText.replace(/[^A-Z]?/g,"");
|
||||
if (r === "OK") {
|
||||
$('#ModRewriteResult').html("Friendly URLs set up successfully; I am now redirecting you to your SilverStripe site...")
|
||||
setTimeout(function() {
|
||||
window.location = "$destinationURL";
|
||||
}, 2000);
|
||||
} else {
|
||||
$('#ModRewriteResult').html("Friendly URLs are not working. This is most likely because a rewrite module isn't configured "
|
||||
+ "correctly on your site. You may need to get your web host or server administrator to do this for you: "
|
||||
+ "<ul>"
|
||||
+ "<li><strong>mod_rewrite</strong> or other rewrite module is enabled on your web server</li>"
|
||||
+ "<li><strong>AllowOverride All</strong> is set for the directory where SilverStripe is installed</li>"
|
||||
+ "</ul>");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<noscript>
|
||||
<li><a href="$destinationURL">Click here</a> to check friendly URLs are working. If you get a 404 then something is wrong.</li>
|
||||
</noscript>
|
||||
HTML;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show an installation status message.
|
||||
* The output differs depending on whether this is CLI or web based
|
||||
*
|
||||
* @param string $msg
|
||||
*/
|
||||
public function statusMessage($msg)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 1.8 KiB |
Binary file not shown.
Before Width: | Height: | Size: 2.0 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.7 KiB |
Binary file not shown.
Before Width: | Height: | Size: 343 B |
Binary file not shown.
Before Width: | Height: | Size: 741 B |
@ -1,49 +0,0 @@
|
||||
$(document).ready(function () {
|
||||
|
||||
/**
|
||||
* 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();
|
||||
});
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// Process
|
||||
$('#saving_top').hide();
|
||||
$(this).val('Installing SilverStripe...');
|
||||
return true;
|
||||
});
|
||||
|
||||
/**
|
||||
* 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;
|
||||
});
|
||||
});
|
@ -1,593 +0,0 @@
|
||||
/* This file is manually maintained, it is not generated from SCSS sources */
|
||||
|
||||
body{
|
||||
font-family:Arial,san-serif;
|
||||
margin-bottom:18px;
|
||||
width:940px;
|
||||
margin:0 auto 18px;
|
||||
background-color:#f4f4f4;
|
||||
}
|
||||
|
||||
body,body p{
|
||||
font-size:13px;
|
||||
line-height:18px;
|
||||
color:#333;
|
||||
}
|
||||
|
||||
body p{
|
||||
margin-bottom:18px;
|
||||
}
|
||||
|
||||
body a{
|
||||
color:#0973a6;
|
||||
}
|
||||
|
||||
body h1,body h2,body h3,body h4,body h5,body h6{
|
||||
color:#222;
|
||||
font-family:inherit;
|
||||
font-weight:700;
|
||||
margin:0;
|
||||
margin:27px 0 9px;
|
||||
text-rendering:optimizelegibility;
|
||||
clear:both;
|
||||
text-shadow:0 1px 0 #fff;
|
||||
}
|
||||
|
||||
body h1 small,body h2 small,body h3 small,body h4 small,body h5 small,body h6 small{
|
||||
font-weight:400;
|
||||
font-size:12px;
|
||||
color:#666;
|
||||
}
|
||||
|
||||
body h1{
|
||||
font-size:36px;
|
||||
background: transparent url("../images/logo.gif") no-repeat left top;
|
||||
text-indent:-9999px;
|
||||
height:164px;
|
||||
width:161px;
|
||||
float:left;
|
||||
padding-right:40px;
|
||||
border-right:1px solid #b1c0c5;
|
||||
margin-right:40px;
|
||||
}
|
||||
|
||||
body h1,body h2{
|
||||
line-height:36px;
|
||||
letter-spacing:-.5px;
|
||||
}
|
||||
|
||||
body h2{
|
||||
font-size:34px;
|
||||
}
|
||||
|
||||
body h3{
|
||||
font-size:18px;
|
||||
line-height:27px;
|
||||
}
|
||||
|
||||
body h4{
|
||||
font-size:14px;
|
||||
margin:18px 0 9px;
|
||||
}
|
||||
|
||||
body h4,body h5{
|
||||
line-height:18px;
|
||||
}
|
||||
|
||||
body h5{
|
||||
font-size:12px;
|
||||
margin:18px 0 0;
|
||||
}
|
||||
|
||||
body #Header h1{
|
||||
margin-top:45px;
|
||||
margin-bottom:27px;
|
||||
}
|
||||
|
||||
body #Header h3{
|
||||
margin-top:-10px;
|
||||
}
|
||||
|
||||
body .clear{
|
||||
clear:both;
|
||||
}
|
||||
|
||||
body .left{
|
||||
float:left;
|
||||
}
|
||||
|
||||
body .message{
|
||||
padding:2px 18px;
|
||||
margin-bottom:18px;
|
||||
-moz-border-radius-topleft:3px;
|
||||
-moz-border-radius-topright:3px;
|
||||
-moz-border-radius-bottomright:3px;
|
||||
-moz-border-radius-bottomleft:3px;
|
||||
border-radius:3px 3px 3px 3px;
|
||||
}
|
||||
|
||||
body .message p{
|
||||
margin:11px 0 13px;
|
||||
}
|
||||
|
||||
body .message.warning{
|
||||
background-color:#fcf8f2;
|
||||
border:1px solid #ffc28b;
|
||||
}
|
||||
|
||||
body .message.error{
|
||||
background-color:#fdf1f3;
|
||||
border:1px solid #f8c3cd;
|
||||
}
|
||||
|
||||
body .message ul{
|
||||
margin-left:18px;
|
||||
margin-top:-9px;
|
||||
}
|
||||
|
||||
body .helpText{
|
||||
float:right;
|
||||
width:425px;
|
||||
padding-left:20px;
|
||||
color:#666;
|
||||
margin-top:0;
|
||||
background: transparent url("../images/question.png") no-repeat left 1px;
|
||||
}
|
||||
|
||||
body .helpText.requirementsHelpText{
|
||||
margin-top:17px;
|
||||
}
|
||||
|
||||
body .typography table{
|
||||
margin:9px 0 27px;
|
||||
border-collapse:collapse;
|
||||
width:100%;
|
||||
}
|
||||
|
||||
body .typography table thead td,body .typography table thead th{
|
||||
font-weight:700;
|
||||
vertical-align:bottom;
|
||||
padding:12px;
|
||||
}
|
||||
|
||||
body .typography table td,body .typography table th{
|
||||
padding:8px 12px;
|
||||
text-align:left;
|
||||
}
|
||||
|
||||
body .typography table td{
|
||||
vertical-align:top;
|
||||
border-top:0;
|
||||
background-color:#fff;
|
||||
}
|
||||
|
||||
body .typography table tbody tr:nth-child(odd) td,body .typography table tbody tr:nth-child(odd) th{
|
||||
background-color:#fcfcfc;
|
||||
}
|
||||
|
||||
body .typography table tbody tr:hover td,body .typography table tbody tr:hover th{
|
||||
background-color:#f6f6f6;
|
||||
}
|
||||
|
||||
body .typography table tfoot{
|
||||
font-style:italic;
|
||||
color:#888;
|
||||
}
|
||||
|
||||
body .typography input,body .typography select,body .typography textarea{
|
||||
width:420px;
|
||||
margin-bottom:9px;
|
||||
color:#707070;
|
||||
border:1px solid #ddd;
|
||||
display:inline-block;
|
||||
height:18px;
|
||||
padding:4px 6px;
|
||||
line-height:18px;
|
||||
font-size:13px;
|
||||
-moz-border-radius-topleft:3px;
|
||||
-moz-border-radius-topright:3px;
|
||||
-moz-border-radius-bottomright:3px;
|
||||
-moz-border-radius-bottomleft:3px;
|
||||
border-radius:3px 3px 3px 3px;
|
||||
}
|
||||
|
||||
body .typography input,body .typography textarea{
|
||||
-webkit-transition:border .2s linear,-webkit-box-shadow .2s linear;
|
||||
transition:border .2s linear,box-shadow .2s linear;
|
||||
box-shadow:inset 0 1px 3px rgba(0,0,0,.1);
|
||||
}
|
||||
|
||||
body .typography input:focus,body .typography textarea:focus{
|
||||
outline:0;
|
||||
border-color:rgba(82,168,236,.8);
|
||||
box-shadow:inset 0 1px 3px rgba(0,0,0,.1),0 0 4px rgba(82,168,236,.6);
|
||||
}
|
||||
|
||||
body .typography input[type=checkbox]:focus,body .typography input[type=file]:focus,body .typography select:focus{
|
||||
box-shadow:none;
|
||||
outline:1px dotted #666;
|
||||
}
|
||||
|
||||
body .typography select{
|
||||
height:26px;
|
||||
}
|
||||
|
||||
body .typography option{
|
||||
line-height:27px;
|
||||
font-size:12px;
|
||||
padding:2px 6px;
|
||||
color:#666;
|
||||
}
|
||||
|
||||
body .typography label{
|
||||
width:auto;
|
||||
float:none;
|
||||
padding-top:0;
|
||||
margin:0 0 5px;
|
||||
text-align:left;
|
||||
display:block;
|
||||
}
|
||||
|
||||
body .typography .fields{
|
||||
float:left;
|
||||
}
|
||||
|
||||
body .typography input.action{
|
||||
text-align:center;
|
||||
font-weight:700;
|
||||
margin:9px 0 27px;
|
||||
padding:6px 8px;
|
||||
width:200px;
|
||||
width:auto;
|
||||
color:#222;
|
||||
border:1px solid #aaa;
|
||||
text-shadow:0 1px 0 #eee;
|
||||
font-size:13px;
|
||||
float:none;
|
||||
height:auto;
|
||||
background:#fbfbfb;
|
||||
background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#fbfbfb),color-stop(100%,#bbb));
|
||||
background:-webkit-linear-gradient(top,#fbfbfb,#bbb);
|
||||
background:-webkit-gradient(linear,left top,left bottom,from(#fbfbfb),to(#bbb));
|
||||
background:linear-gradient(180deg,#fbfbfb 0,#bbb);
|
||||
-moz-border-radius-topleft:3px;
|
||||
-moz-border-radius-topright:3px;
|
||||
-moz-border-radius-bottomright:3px;
|
||||
-moz-border-radius-bottomleft:3px;
|
||||
border-radius:3px 3px 3px 3px;
|
||||
box-shadow:0 1px 0 0 #fff;
|
||||
background-color:#ddd;
|
||||
}
|
||||
|
||||
.lt-ie9 body .typography input.action{
|
||||
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#fbfbfb",endColorstr="#bbb",GradientType=0);
|
||||
}
|
||||
|
||||
body .typography input.action:hover{
|
||||
box-shadow:0 1px 2px 0 #ccc;
|
||||
background:#fbfbfb;
|
||||
background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#fbfbfb),color-stop(100%,#ccc));
|
||||
background:-webkit-linear-gradient(top,#fbfbfb,#ccc);
|
||||
background:-webkit-gradient(linear,left top,left bottom,from(#fbfbfb),to(#ccc));
|
||||
background:linear-gradient(180deg,#fbfbfb 0,#ccc);
|
||||
}
|
||||
|
||||
.lt-ie9 body .typography input.action:hover{
|
||||
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#fbfbfb",endColorstr="#ccc",GradientType=0);
|
||||
}
|
||||
|
||||
body .typography input.action:active,body .typography input.action:focus{
|
||||
box-shadow:0 1px 0 0 #fff;
|
||||
background:#fbfbfb;
|
||||
background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#fbfbfb),color-stop(100%,#bbb));
|
||||
background:-webkit-linear-gradient(top,#fbfbfb,#bbb);
|
||||
background:-webkit-gradient(linear,left top,left bottom,from(#fbfbfb),to(#bbb));
|
||||
background:linear-gradient(180deg,#fbfbfb 0,#bbb);
|
||||
}
|
||||
|
||||
.lt-ie9 body .typography input.action:active,.lt-ie9 body .typography input.action:focus{
|
||||
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#fbfbfb",endColorstr="#bbb",GradientType=0);
|
||||
}
|
||||
|
||||
body .typography input.action:focus,body .typography input.action:hover{
|
||||
cursor:pointer;
|
||||
}
|
||||
|
||||
body .typography input[type=checkbox],body .typography input[type=radio]{
|
||||
border:medium none;
|
||||
height:auto;
|
||||
line-height:normal;
|
||||
padding:0;
|
||||
width:auto;
|
||||
margin-right:6px;
|
||||
float:left;
|
||||
margin-top:3px;
|
||||
}
|
||||
|
||||
body .typography #install_button{
|
||||
font-size:20px;
|
||||
color:#fff;
|
||||
border-color:#78a127 #78a127 #59781d;
|
||||
text-shadow:0 1px 1px #4d7326;
|
||||
padding:8px 14px;
|
||||
background-color:green;
|
||||
background:#80bf40;
|
||||
background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#80bf40),color-stop(100%,#59862d));
|
||||
background:-webkit-linear-gradient(top,#80bf40,#59862d);
|
||||
background:-webkit-gradient(linear,left top,left bottom,from(#80bf40),to(#59862d));
|
||||
background:linear-gradient(180deg,#80bf40 0,#59862d);
|
||||
box-shadow:0 1px 0 0 #fff;
|
||||
}
|
||||
|
||||
.lt-ie9 body .typography #install_button{
|
||||
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#80BF40",endColorstr="#59862D",GradientType=0);
|
||||
}
|
||||
|
||||
body .typography #install_button:hover{
|
||||
box-shadow:0 1px 3px 0 #bbb;
|
||||
}
|
||||
|
||||
body .typography #install_button:active,body .typography #install_button:focus{
|
||||
box-shadow:0 1px 0 0 #fff;
|
||||
background:#80bf40;
|
||||
background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#80bf40),color-stop(100%,#59862d));
|
||||
background:-webkit-linear-gradient(top,#80bf40,#59862d);
|
||||
background:-webkit-gradient(linear,left top,left bottom,from(#80bf40),to(#59862d));
|
||||
background:linear-gradient(180deg,#80bf40 0,#59862d);
|
||||
}
|
||||
|
||||
.lt-ie9 body .typography #install_button:active,.lt-ie9 body .typography #install_button:focus{
|
||||
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#80BF40",endColorstr="#59862D",GradientType=0);
|
||||
}
|
||||
|
||||
body .typography #install_button[disabled=disabled]{
|
||||
border:1px solid #aaa;
|
||||
border-color:#bbb #bbb #aaa;
|
||||
color:#999;
|
||||
text-shadow:0 1px 0 #eee;
|
||||
background:#fbfbfb;
|
||||
background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#fbfbfb),color-stop(100%,#bbb));
|
||||
background:-webkit-linear-gradient(top,#fbfbfb,#bbb);
|
||||
background:-webkit-gradient(linear,left top,left bottom,from(#fbfbfb),to(#bbb));
|
||||
background:linear-gradient(180deg,#fbfbfb 0,#bbb);
|
||||
}
|
||||
|
||||
.lt-ie9 body .typography #install_button[disabled=disabled]{
|
||||
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#fbfbfb",endColorstr="#bbb",GradientType=0);
|
||||
}
|
||||
|
||||
body .typography #install_button[disabled=disabled]:hover{
|
||||
box-shadow:0 1px 0 0 #fff;
|
||||
}
|
||||
|
||||
body #Container{
|
||||
margin-bottom:40px;
|
||||
}
|
||||
|
||||
body #Container h3.sectionHeading{
|
||||
padding-top:27px;
|
||||
border-top:1px solid #b1c0c5;
|
||||
clear:both;
|
||||
}
|
||||
|
||||
body #Container #Header{
|
||||
margin-bottom:30px;
|
||||
height:200px;
|
||||
}
|
||||
|
||||
body #Container #Header div.left{
|
||||
width:698px;
|
||||
margin-top:47px;
|
||||
}
|
||||
|
||||
body #Container #Navigation{
|
||||
display:none;
|
||||
}
|
||||
|
||||
body h5.requirement{
|
||||
padding:12px 18px;
|
||||
font-size:14px;
|
||||
border:1px solid #798c93;
|
||||
border-top:1px solid #8d9da3;
|
||||
margin:0;
|
||||
color:#fff;
|
||||
position:relative;
|
||||
text-shadow:0 -1px 0 #71858c;
|
||||
-moz-border-radius-topleft:3px;
|
||||
-moz-border-radius-topright:3px;
|
||||
-moz-border-radius-bottomright:3px;
|
||||
-moz-border-radius-bottomleft:3px;
|
||||
border-radius:3px 3px 3px 3px;
|
||||
box-shadow:0 1px 0 0 #fff;
|
||||
background-color:#eee;
|
||||
background:#b1c0c5;
|
||||
background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#b1c0c5),color-stop(100%,#7f9198));
|
||||
background:-webkit-linear-gradient(top,#b1c0c5,#7f9198);
|
||||
background:-webkit-gradient(linear,left top,left bottom,from(#b1c0c5),to(#7f9198));
|
||||
background:linear-gradient(180deg,#b1c0c5 0,#7f9198);
|
||||
}
|
||||
|
||||
.lt-ie9 body h5.requirement{
|
||||
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#B1C0C5",endColorstr="#7F9198",GradientType=0);
|
||||
}
|
||||
|
||||
body h5.requirement span{
|
||||
font-weight:400;
|
||||
font-size:12px;
|
||||
padding:3px 6px;
|
||||
margin-left:5px;
|
||||
text-shadow:none;
|
||||
background-color:#fafbfb;
|
||||
-moz-border-radius-topleft:2px;
|
||||
-moz-border-radius-topright:2px;
|
||||
-moz-border-radius-bottomright:2px;
|
||||
-moz-border-radius-bottomleft:2px;
|
||||
border-radius:2px 2px 2px 2px;
|
||||
box-shadow:0 0 2px 0 #7f9198;
|
||||
}
|
||||
|
||||
body h5.requirement.good span{
|
||||
color:#359318;
|
||||
}
|
||||
|
||||
body h5.requirement.warning span{
|
||||
color:#e07127;
|
||||
}
|
||||
|
||||
body h5.requirement.error span{
|
||||
color:#c61414;
|
||||
}
|
||||
|
||||
body h5.requirement a{
|
||||
font-size:11px;
|
||||
right:9px;
|
||||
position:absolute;
|
||||
line-height:19px;
|
||||
margin:0 0 0 30px;
|
||||
color:#fff;
|
||||
text-decoration:none;
|
||||
font-weight:400;
|
||||
padding-right:21px;
|
||||
background: transparent url("../images/arrows.png") no-repeat right top;
|
||||
}
|
||||
|
||||
body h5.requirement a:hover{
|
||||
background: transparent url("../images/arrows.png") no-repeat right -40px;
|
||||
}
|
||||
|
||||
body table.testResults{
|
||||
border-top:0;
|
||||
margin-top:-1px;
|
||||
margin-bottom:9px;
|
||||
box-shadow:0 1px 0 0 #fff;
|
||||
-moz-border-radius-topleft:3px;
|
||||
-moz-border-radius-topright:3px;
|
||||
-moz-border-radius-bottomright:3px;
|
||||
-moz-border-radius-bottomleft:3px;
|
||||
border-radius:3px 3px 3px 3px;
|
||||
overflow:hidden;
|
||||
}
|
||||
|
||||
body table.testResults tr.good{
|
||||
display:none;
|
||||
border:0;
|
||||
}
|
||||
|
||||
body table.testResults tr.good td{
|
||||
color:#359318;
|
||||
}
|
||||
|
||||
body table.testResults tr.warning{
|
||||
border:0;
|
||||
}
|
||||
|
||||
body table.testResults tr.warning td{
|
||||
color:#e07127;
|
||||
}
|
||||
|
||||
body table.testResults tr.error{
|
||||
border:0;
|
||||
color:#c61414;
|
||||
}
|
||||
|
||||
body table.testResults td{
|
||||
border:1px solid #ddd;
|
||||
width:50%;
|
||||
}
|
||||
|
||||
body #database_selection,body #Themes{
|
||||
list-style:none;
|
||||
margin:0;
|
||||
margin-bottom:18px;
|
||||
padding-left:0;
|
||||
}
|
||||
|
||||
body #database_selection li,body #Themes li{
|
||||
clear:left;
|
||||
padding:3px 0;
|
||||
}
|
||||
|
||||
body #database_selection li .dbfields,body #Themes li .dbfields{
|
||||
padding:12px;
|
||||
border:1px solid #ddd;
|
||||
background-color:#fafafa;
|
||||
margin-bottom:9px;
|
||||
-moz-border-radius-topleft:3px;
|
||||
-moz-border-radius-topright:3px;
|
||||
-moz-border-radius-bottomright:3px;
|
||||
-moz-border-radius-bottomleft:3px;
|
||||
border-radius:3px 3px 3px 3px;
|
||||
box-shadow:inset 0 0 3px 0 #ddd;
|
||||
box-shadow:0 1px 0 0 #fff;
|
||||
}
|
||||
|
||||
body ul#Themes{
|
||||
float:left;
|
||||
width:445px;
|
||||
}
|
||||
|
||||
body .databaseError{
|
||||
width:422px;
|
||||
}
|
||||
|
||||
body #Footer{
|
||||
margin-top:67px;
|
||||
margin-bottom:18px;
|
||||
}
|
||||
|
||||
body #Footer p{
|
||||
font-size:12px;
|
||||
color:#999;
|
||||
}
|
||||
|
||||
#adminAcc,#devHelp,#localeHelp{
|
||||
padding-top:20px;
|
||||
}
|
||||
|
||||
#devHelp,#devSection{
|
||||
height:18em;
|
||||
}
|
||||
|
||||
#use_environment_field{
|
||||
margin-bottom:25px;
|
||||
background-color:#fafafa;
|
||||
border:1px solid #ddd;
|
||||
border-radius:3px 3px 3px 3px;
|
||||
box-shadow:0 1px 0 0 #fff;
|
||||
margin-bottom:9px;
|
||||
padding:10px 10px 8px;
|
||||
}
|
||||
|
||||
#use_environment_field input{
|
||||
float:left;
|
||||
margin-right:5px;
|
||||
}
|
||||
|
||||
.databaseError ul{
|
||||
margin-bottom:0;
|
||||
}
|
||||
|
||||
.databaseError li,.databaseError ul{
|
||||
margin-left:0;
|
||||
padding-left:0;
|
||||
}
|
||||
|
||||
#Layout p.goodInstall,.goodInstall{
|
||||
color:#359318;
|
||||
}
|
||||
|
||||
.goodInstall{
|
||||
padding:.5em;
|
||||
background-color:#e2fee1;
|
||||
border:1px solid #43cb3e;
|
||||
overflow:hidden;
|
||||
line-height:18px;
|
||||
padding:10px;
|
||||
}
|
||||
|
||||
.goodInstall a{
|
||||
float:right;
|
||||
font-size:18px;
|
||||
padding:0 2px 2px 0;
|
||||
font-weight:700;
|
||||
}
|
@ -1,279 +0,0 @@
|
||||
<!doctype html>
|
||||
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="en"> <![endif]-->
|
||||
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8" lang="en"> <![endif]-->
|
||||
<!--[if IE 8]> <html class="no-js lt-ie9" lang="en"> <![endif]-->
|
||||
<!--[if gt IE 8]><!--> <html class="no-js" lang="en"> <!--<![endif]-->
|
||||
<head>
|
||||
<title>SilverStripe CMS / Framework Installation</title>
|
||||
<base href="<?php echo htmlentities($base); ?>" />
|
||||
<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="<?=$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>
|
||||
<div id="BgContainer">
|
||||
<div id="Container">
|
||||
<div id="Header">
|
||||
<h1>SilverStripe</h1>
|
||||
<div class="left">
|
||||
<h2>CMS / Framework Installation <?php if($silverstripe_version) echo "<small>Version $silverstripe_version</small>"; ?></h2>
|
||||
<p>Thanks for choosing to use SilverStripe! Please follow the instructions below and you should be up in running in no time.<br>
|
||||
If you get stuck, head over to the <a href="http://silverstripe.org/community/forums/installing-silverstripe" target="_blank">installation forum</a>, or check out our page of <a href="http://www.silverstripe.org/hosting" target="_blank">suggested web hosting options</a> known to work with SilverStripe.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div id="Navigation"> </div>
|
||||
<div class="clear"><!-- --></div>
|
||||
|
||||
<div id="Layout">
|
||||
<div class="typography">
|
||||
<form action="install.php" method="post">
|
||||
<?php if($hasErrorOtherThanDatabase): ?>
|
||||
<p class="message error">
|
||||
You aren't currently able to install the software. Please <a href="#requirements">see below</a> for details.<br>
|
||||
If you are having problems meeting the requirements, see the <a href="http://doc.silverstripe.org/framework/en/installation/server-requirements" target="_blank">server requirements</a>.
|
||||
</p>
|
||||
<?php if ($phpIniLocation): ?>
|
||||
<p class="message warning">Your php.ini file is located at <?=$phpIniLocation; ?></p>
|
||||
<?php endif; ?>
|
||||
<?php else: ?>
|
||||
<?php if($alreadyInstalled): ?>
|
||||
<div class="message warning">
|
||||
<p><strong>Note:</strong> SilverStripe is already installed here.<br>
|
||||
If you choose to reinstall SilverStripe, your current settings will be replaced</p>
|
||||
</div>
|
||||
<?php elseif($req->hasWarnings()): ?>
|
||||
<div class="message warning">
|
||||
<p>There are some issues that we recommend you look at before installing, however, you are still able to install the software.
|
||||
<br>Please see below for details. If you are having problems meeting the requirements, see the <a href="http://doc.silverstripe.org/framework/en/installation/server-requirements" target="_blank">server requirements</a>.</p>
|
||||
</div>
|
||||
<?php elseif(!$dbReq->hasErrors() && !$adminReq->hasErrors()): ?>
|
||||
<div class="message goodInstall"><p>You're ready to install! Please confirm the configuration options below. <a href="#install">Install SilverStripe</a></p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if($dbReq->hasErrors()): ?>
|
||||
<div class="message error">
|
||||
<p>The database details don't appear to be correct. Please <a href="#database_credentials">review and correct</a> before installing.</p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if($adminReq->hasErrors()): ?>
|
||||
<div class="message error">
|
||||
<p>Please <a href="#AdminAccount">enter an email address and password</a> for the default administrator account before installing.</p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<h3 class="sectionHeading" id="requirements">Requirements <small>Step 1 of 5</small></h3>
|
||||
<?php $req->showTable(); ?>
|
||||
<?php $dbReq->showTable(); ?>
|
||||
|
||||
<p class="helpText requirementsHelpText">
|
||||
Read more about our <a href="http://doc.silverstripe.org/framework/en/installation/server-requirements" target="_blank">server requirements</a>.
|
||||
</p>
|
||||
|
||||
<div class="action">
|
||||
<input type="submit" class="action" value="Re-check requirements">
|
||||
</div>
|
||||
<div class="clear"><!-- --></div>
|
||||
<h3 class="sectionHeading">Database Configuration <small>Step 2 of 5</small></h3>
|
||||
<div id="database_credentials" class="section">
|
||||
|
||||
<?php $dbReq->showTable("Database Configuration"); ?>
|
||||
|
||||
<p id="dbHelp" class="helpText">
|
||||
SilverStripe stores its content in a relational SQL database. Please provide the username and password to connect to the server here.
|
||||
If this account has permission to create databases, then we will create the database for you; otherwise, you must give the name of a
|
||||
database that already exists.<br><br>
|
||||
<strong>Other databases:</strong><br>
|
||||
Databases in the list that are greyed out cannot currently be used. Click on them for more information and possible remedies.
|
||||
</p>
|
||||
<div class="fields">
|
||||
<div class="field">
|
||||
<ul id="database_selection">
|
||||
<?php
|
||||
foreach ($databaseClasses as $class => $details) {
|
||||
$checked = ($databaseConfig['type'] == $class) ? ' checked="checked"' : '';
|
||||
$disabled = $help = '';
|
||||
$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>";
|
||||
if ($help) {
|
||||
echo '<div class="message error databaseError"><p>'.$help.'</p></div>';
|
||||
}
|
||||
|
||||
// generate db-specific config fields
|
||||
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';
|
||||
// Get display value
|
||||
if (isset($databaseConfig[$fieldName]) && $databaseConfig['type'] == $class) {
|
||||
$value = $databaseConfig[$fieldName];
|
||||
} elseif (isset($fieldSpec['default'])) {
|
||||
$value = $fieldSpec['default'];
|
||||
} else {
|
||||
$value = null;
|
||||
}
|
||||
|
||||
// attributes
|
||||
$attrs = array(
|
||||
'id' => "db_{$class}_{$fieldName}",
|
||||
'class' => 'text',
|
||||
'type' => $fieldType,
|
||||
'name' => "db[$class][$fieldName]",
|
||||
'value' => $value,
|
||||
);
|
||||
$attrHTML = '';
|
||||
foreach($attrs as $attrName => $attrValue) $attrHTML .= "$attrName=\"" . htmlspecialchars($attrValue) . '"';
|
||||
if(isset($fieldSpec['attributes'])) $attrs = array_merge($attrs, $fieldSpec['attributes']);
|
||||
|
||||
// html
|
||||
echo "<div class=\"field\">";
|
||||
echo "<label for=\"db_{$class}_$fieldName\">$fieldTitle:</label>";
|
||||
echo "<span class=\"middleColumn\">";
|
||||
echo "<input $attrHTML>";
|
||||
echo "</span>";
|
||||
echo "</div>";
|
||||
}
|
||||
echo '</div>';
|
||||
|
||||
echo "</li>";
|
||||
}
|
||||
?>
|
||||
</ul>
|
||||
|
||||
<div id="use_environment_field" class="field">
|
||||
<input id="use_environment" type="checkbox" name="useEnv" <?php if($usingEnv) echo "checked=\"checked\"" ?>>
|
||||
<label for="use_environment">Use environment variables for configuration (<a href="http://doc.silverstripe.org/framework/en/topics/environment-management" target="_blank">?</a>)</label>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="clear"><!-- --></div>
|
||||
|
||||
<div class="action">
|
||||
<input type="submit" class="action" value="Re-check requirements">
|
||||
</div>
|
||||
|
||||
<h3 class="sectionHeading">CMS Admin Account <small>Step 3 of 5</small></h3>
|
||||
|
||||
<div id="AdminAccount" class="section">
|
||||
|
||||
<div class="form__fieldGroup">
|
||||
<p class="helpText">We will set up the first administrator account for you automatically. You can change these details later in the "Security" section within the CMS.</p>
|
||||
|
||||
<div class="field">
|
||||
<label for="admin_username">Email:</label>
|
||||
<span class="middleColumn">
|
||||
<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" 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>
|
||||
|
||||
<div class="form__fieldGroup">
|
||||
<p class="helpText">
|
||||
"Default language" determines the default locale settings
|
||||
(for dates, currencies, etc.), as well as the default language
|
||||
of the CMS interface. This can be changed for each user.
|
||||
<br>
|
||||
<strong>Warning:</strong> The CMS interface may be missing translations in certain locales.
|
||||
</p>
|
||||
|
||||
<div class="field">
|
||||
<label for="locale">Default language:</label>
|
||||
<span class="middleColumn">
|
||||
<select name="locale" id="locale">
|
||||
<?php
|
||||
foreach ($locales as $code => $title) {
|
||||
$selected = ($code === $locale) ? ' selected="selected"' : '';
|
||||
echo "<option$selected value=\"$code\">{$title}</option>\n";
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</span>
|
||||
</div>
|
||||
<div class="clear"><!-- --></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="action">
|
||||
<input type="submit" class="action" value="Re-check requirements">
|
||||
</div>
|
||||
|
||||
<h3 class="sectionHeading">Theme selection <small>Step 4 of 5</small></h3>
|
||||
<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($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>
|
||||
|
||||
<?php if($hasErrorOtherThanDatabase): ?>
|
||||
<p class="error">
|
||||
You aren't currently able to install the software. Please <a href="#requirements">see above</a> for details.<br>
|
||||
If you are having problems meeting the requirements, see the <a href="http://doc.silverstripe.org/doku.php?id=server-requirements">server requirements page</a>.
|
||||
</p>
|
||||
<?php else: ?>
|
||||
<p id="stats-container">
|
||||
<input type="checkbox" id="stats" name="stats" checked="checked">
|
||||
<label for="stats">Send information about my webserver to silverstripe.org<br />
|
||||
<small>(anonymous version information, used for statistical purposes)</small>
|
||||
</label><p>
|
||||
|
||||
<p>
|
||||
<?php if($alreadyInstalled): ?>
|
||||
<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">
|
||||
|
||||
<img src="<?=$clientPath; ?>/images/network-save.gif" alt="Saving">
|
||||
(this will take a minute or so)
|
||||
</span>
|
||||
</p>
|
||||
<?php endif ?>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clear"><!-- --></div>
|
||||
</div>
|
||||
|
||||
<div id="Footer">
|
||||
<div class="footerTop"><!-- --></div>
|
||||
<p><a href="http://silverstripe.org">SilverStripe Open Source CMS / Framework</a> | Copyright © <?=date('Y'); ?> SilverStripe Limited</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,25 +0,0 @@
|
||||
<?php
|
||||
|
||||
/************************************************************************************
|
||||
************************************************************************************
|
||||
** **
|
||||
** If you can read this text in your browser then you don't have PHP installed. **
|
||||
** Please install PHP 5.5.0 or higher. **
|
||||
** **
|
||||
************************************************************************************
|
||||
************************************************************************************/
|
||||
|
||||
/**
|
||||
* PHP version check. Make sure we've got at least PHP 5.6.0 in the most friendly way possible
|
||||
*/
|
||||
if (version_compare(phpversion(), '5.6.0', '<')) {
|
||||
header($_SERVER['SERVER_PROTOCOL'] . " 500 Server Error");
|
||||
echo str_replace(
|
||||
'$PHPVersion',
|
||||
phpversion(),
|
||||
file_get_contents(__DIR__ . "/php5-required.html")
|
||||
);
|
||||
die();
|
||||
}
|
||||
|
||||
include(__DIR__ . '/install5.php');
|
@ -1,156 +0,0 @@
|
||||
<?php
|
||||
|
||||
/************************************************************************************
|
||||
************************************************************************************
|
||||
** **
|
||||
** If you can read this text in your browser then you don't have PHP installed. **
|
||||
** Please install PHP 5.5.0 or higher. **
|
||||
** **
|
||||
************************************************************************************
|
||||
************************************************************************************/
|
||||
|
||||
namespace SilverStripe\Dev\Install;
|
||||
|
||||
// Back up original ini config
|
||||
$originalIni = [];
|
||||
$iniSet = function ($name, $value) use (&$originalIni) {
|
||||
if (!isset($originalIni[$name])) {
|
||||
$originalIni[$name] = ini_get($name);
|
||||
}
|
||||
ini_set($name, $value);
|
||||
};
|
||||
|
||||
// speed up mysql_connect timeout if the server can't be found
|
||||
$iniSet('mysql.connect_timeout', 5);
|
||||
// Don't die half was through installation; that does more harm than good
|
||||
$iniSet('max_execution_time', 0);
|
||||
|
||||
// set display_errors php setting to on to force installer to avoid blank screen of death.
|
||||
// get the original value so it can be used in PHP requirement checks later in this script.
|
||||
$iniSet('display_errors', '1');
|
||||
|
||||
error_reporting(E_ALL | E_STRICT);
|
||||
|
||||
// Attempt to start a session so that the username and password can be sent back to the user.
|
||||
if (function_exists('session_start') && !session_id()) {
|
||||
session_start();
|
||||
}
|
||||
|
||||
// require composers autoloader
|
||||
require_once __DIR__ . '/../../includes/autoload.php';
|
||||
|
||||
$usingEnv = empty($_POST) || !empty($_REQUEST['useEnv']);
|
||||
|
||||
// Set default locale, but try and sniff from the user agent
|
||||
$locale = isset($_POST['locale']) ? $_POST['locale'] : 'en_US';
|
||||
|
||||
// Discover which databases are available
|
||||
DatabaseAdapterRegistry::autodiscover();
|
||||
|
||||
// Determine which external database modules are USABLE
|
||||
$databaseClasses = DatabaseAdapterRegistry::get_adapters();
|
||||
foreach ($databaseClasses as $class => $details) {
|
||||
$helper = DatabaseAdapterRegistry::getDatabaseConfigurationHelper($class);
|
||||
$databaseClasses[$class]['hasModule'] = !empty($helper);
|
||||
}
|
||||
|
||||
// Build config from config / environment / request
|
||||
$config = new InstallConfig();
|
||||
$databaseConfig = $config->getDatabaseConfig($_REQUEST, $databaseClasses, true);
|
||||
$adminConfig = $config->getAdminConfig($_REQUEST, true);
|
||||
$alreadyInstalled = $config->alreadyInstalled();
|
||||
$silverstripe_version = $config->getFrameworkVersion();
|
||||
$sendStats = $config->canSendStats($_REQUEST);
|
||||
$locales = $config->getLocales();
|
||||
$theme = $config->getTheme($_REQUEST);
|
||||
|
||||
// Check requirements
|
||||
$req = new InstallRequirements();
|
||||
$req->check($originalIni);
|
||||
|
||||
if ($req->isIIS()) {
|
||||
$webserverConfigFile = 'web.config';
|
||||
} else {
|
||||
$webserverConfigFile = '.htaccess';
|
||||
}
|
||||
|
||||
$hasErrorOtherThanDatabase = false;
|
||||
$hasOnlyWarnings = false;
|
||||
$phpIniLocation = php_ini_loaded_file();
|
||||
if ($req->hasErrors()) {
|
||||
$hasErrorOtherThanDatabase = true;
|
||||
} elseif ($req->hasWarnings()) {
|
||||
$hasOnlyWarnings = true;
|
||||
}
|
||||
|
||||
$dbReq = new InstallRequirements();
|
||||
if ($databaseConfig) {
|
||||
$dbReq->checkDatabase($databaseConfig);
|
||||
}
|
||||
|
||||
$adminReq = new InstallRequirements();
|
||||
if ($adminConfig) {
|
||||
$adminReq->checkAdminConfig($adminConfig);
|
||||
}
|
||||
|
||||
// Actual processor
|
||||
$installFromCli = (isset($_SERVER['argv'][1]) && $_SERVER['argv'][1] == 'install');
|
||||
|
||||
// CLI-install error message. exit(1) will halt any makefile.
|
||||
if ($installFromCli && ($req->hasErrors() || $dbReq->hasErrors())) {
|
||||
echo "Cannot install due to errors:\n";
|
||||
$req->listErrors();
|
||||
$dbReq->listErrors();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Path to client resources (copied through silverstripe/vendor-plugin)
|
||||
$base = rtrim(BASE_URL, '/') . '/';
|
||||
$clientPath = RESOURCES_DIR . (PUBLIC_DIR
|
||||
? '/vendor/silverstripe/framework/src/Dev/Install/client'
|
||||
: '/silverstripe/framework/src/Dev/Install/client');
|
||||
|
||||
// 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
|
||||
$inst = new Installer();
|
||||
$inst->install([
|
||||
'usingEnv' => $usingEnv,
|
||||
'locale' => $locale,
|
||||
'theme' => $theme,
|
||||
'version' => $silverstripe_version,
|
||||
'db' => $databaseConfig,
|
||||
'admin' => $adminConfig,
|
||||
'stats' => $sendStats,
|
||||
]);
|
||||
return;
|
||||
}
|
||||
|
||||
// Sanitise config prior to rendering config-form.html
|
||||
$databaseConfig = $config->getDatabaseConfig($_REQUEST, $databaseClasses, false);
|
||||
$adminConfig = $config->getAdminConfig($_REQUEST, false);
|
||||
|
||||
// config-form.html vars (placeholder to prevent deletion)
|
||||
[
|
||||
$base,
|
||||
$theme,
|
||||
$clientPath,
|
||||
$adminConfig,
|
||||
$databaseConfig,
|
||||
$usingEnv,
|
||||
$silverstripe_version,
|
||||
$locale,
|
||||
$locales,
|
||||
$webserverConfigFile,
|
||||
$hasErrorOtherThanDatabase,
|
||||
$hasOnlyWarnings, // If warnings but not errors
|
||||
$phpIniLocation,
|
||||
];
|
||||
|
||||
include(__DIR__ . '/config-form.html');
|
@ -1,37 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>PHP 5.6.0 is required</title>
|
||||
<link rel="stylesheet" type="text/css" href="framework/src/Dev/Install/client/styles/install.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="BgContainer">
|
||||
<div id="Container">
|
||||
<div id="Header">
|
||||
<h1>PHP 5.6.0 required</h1>
|
||||
<div class="left">
|
||||
<h3>To run SilverStripe, please install PHP 5.6.0 or greater.</h3>
|
||||
|
||||
<p>We have detected that you are running PHP version <b>$PHPVersion</b>. In order to run SilverStripe,
|
||||
you must have PHP version 5.6.0 or higher.<p/>
|
||||
|
||||
<p>If you are running on a shared host, you may need to ask your hosting provider how to do this.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="Navigation"> </div>
|
||||
<div class="clear"><!-- --></div>
|
||||
|
||||
<div id="Layout">
|
||||
<div class="typography">
|
||||
</div>
|
||||
</div>
|
||||
<div class="clear"><!-- --></div>
|
||||
</div>
|
||||
|
||||
<div id="Footer">
|
||||
<div class="footerTop"><!-- --></div>
|
||||
<p><a href="http://silverstripe.org">SilverStripe Open Source CMS</a> | Copyright © 2017 SilverStripe Limited</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,54 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Dev\Tests\Install;
|
||||
|
||||
use SilverStripe\Dev\Install\InstallRequirements;
|
||||
use SilverStripe\Dev\SapphireTest;
|
||||
|
||||
class InstallRequirementsTest extends SapphireTest
|
||||
{
|
||||
public function testIIS()
|
||||
{
|
||||
$requirements = new InstallRequirements();
|
||||
$_SERVER['SERVER_SIGNATURE'] = 'Microsoft-IIS/10.0';
|
||||
|
||||
// Test server
|
||||
$this->assertEquals('Microsoft-IIS/10.0', $requirements->findWebserver());
|
||||
|
||||
// True conditions
|
||||
$this->assertTrue($requirements->isIIS());
|
||||
$this->assertTrue($requirements->isIIS(10));
|
||||
$this->assertTrue($requirements->isIIS('10.0'));
|
||||
$this->assertTrue($requirements->isIIS(9));
|
||||
|
||||
// Negative - Based on number
|
||||
$this->assertFalse($requirements->isIIS(11));
|
||||
$_SERVER['SERVER_SIGNATURE'] = 'Microsoft-IIS/6.0';
|
||||
$this->assertFalse($requirements->isIIS());
|
||||
$_SERVER['SERVER_SIGNATURE'] = 'Microsoft-IIS/6.5';
|
||||
$this->assertFalse($requirements->isIIS());
|
||||
|
||||
// Negative - Based on string
|
||||
$_SERVER['SERVER_SOFTWARE'] = 'lighttpd/1.4.33';
|
||||
$this->assertFalse($requirements->isIIS());
|
||||
$_SERVER['SERVER_SOFTWARE'] = 'Apache/2.4.25 (Unix) PHP/5.6.30 LibreSSL/2.2.7';
|
||||
$this->assertFalse($requirements->isIIS());
|
||||
}
|
||||
|
||||
public function testApache()
|
||||
{
|
||||
$requirements = new InstallRequirements();
|
||||
$_SERVER['SERVER_SIGNATURE'] = '';
|
||||
$_SERVER['SERVER_SOFTWARE'] = 'Apache/2.4.25 (Unix) PHP/5.6.30 LibreSSL/2.2.7';
|
||||
|
||||
// Test server
|
||||
$this->assertEquals('Apache/2.4.25 (Unix) PHP/5.6.30 LibreSSL/2.2.7', $requirements->findWebserver());
|
||||
|
||||
// True conditions
|
||||
$this->assertTrue($requirements->isApache());
|
||||
|
||||
// False conditions
|
||||
$_SERVER['SERVER_SOFTWARE'] = 'lighttpd/1.4.33';
|
||||
$this->assertFalse($requirements->isApache());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user