mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
ENHANCEMENT Improve upgrading experience. (#8025)
* ENHANCEMENT Improve upgrading experience. Show errors and back button if errors encountered during install BUG Fix hard-coded 'mysite' folder Fixes #8024 * Patch behat tests to work with new buttons
This commit is contained in:
parent
b0e46ea5c0
commit
865ebb3398
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace SilverStripe\Dev\Install;
|
namespace SilverStripe\Dev\Install;
|
||||||
|
|
||||||
|
use BadMethodCallException;
|
||||||
use SilverStripe\Core\Environment;
|
use SilverStripe\Core\Environment;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -11,6 +12,8 @@ use SilverStripe\Core\Environment;
|
|||||||
*/
|
*/
|
||||||
class InstallConfig
|
class InstallConfig
|
||||||
{
|
{
|
||||||
|
use InstallEnvironmentAware;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of preferred DB classes in order
|
* List of preferred DB classes in order
|
||||||
*
|
*
|
||||||
@ -21,6 +24,11 @@ class InstallConfig
|
|||||||
'MySQLDatabase',
|
'MySQLDatabase',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
public function __construct($basePath = null)
|
||||||
|
{
|
||||||
|
$this->initBaseDir($basePath);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get database config from the current environment
|
* Get database config from the current environment
|
||||||
*
|
*
|
||||||
@ -119,7 +127,7 @@ class InstallConfig
|
|||||||
*/
|
*/
|
||||||
protected function getConfigPath()
|
protected function getConfigPath()
|
||||||
{
|
{
|
||||||
return BASE_PATH . '/mysite/_config.php';
|
return $this->getBaseDir() . $this->getProjectDir() . DIRECTORY_SEPARATOR . '_config.php';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -127,7 +135,7 @@ class InstallConfig
|
|||||||
*/
|
*/
|
||||||
protected function getEnvPath()
|
protected function getEnvPath()
|
||||||
{
|
{
|
||||||
return BASE_PATH . '/.env';
|
return $this->getBaseDir() . '.env';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
231
src/Dev/Install/InstallEnvironmentAware.php
Normal file
231
src/Dev/Install/InstallEnvironmentAware.php
Normal file
@ -0,0 +1,231 @@
|
|||||||
|
<?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..5.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..5.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);
|
||||||
|
}
|
||||||
|
}
|
@ -21,6 +21,8 @@ use SplFileInfo;
|
|||||||
*/
|
*/
|
||||||
class InstallRequirements
|
class InstallRequirements
|
||||||
{
|
{
|
||||||
|
use InstallEnvironmentAware;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of errors
|
* List of errors
|
||||||
*
|
*
|
||||||
@ -48,46 +50,9 @@ class InstallRequirements
|
|||||||
*/
|
*/
|
||||||
protected $originalIni = [];
|
protected $originalIni = [];
|
||||||
|
|
||||||
/**
|
|
||||||
* Base path
|
|
||||||
* @var
|
|
||||||
*/
|
|
||||||
protected $baseDir;
|
|
||||||
|
|
||||||
public function __construct($basePath = null)
|
public function __construct($basePath = null)
|
||||||
{
|
{
|
||||||
if ($basePath) {
|
$this->initBaseDir($basePath);
|
||||||
$this->baseDir = $basePath;
|
|
||||||
} elseif (defined('BASE_PATH')) {
|
|
||||||
$this->baseDir = BASE_PATH;
|
|
||||||
} else {
|
|
||||||
throw new BadMethodCallException("No BASE_PATH defined");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -203,50 +168,11 @@ class InstallRequirements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check everything except the database
|
* Check everything except the database
|
||||||
|
*
|
||||||
|
* @param array $originalIni
|
||||||
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function check($originalIni)
|
public function check($originalIni)
|
||||||
{
|
{
|
||||||
@ -256,6 +182,10 @@ class InstallRequirements
|
|||||||
$isIIS = $this->isIIS();
|
$isIIS = $this->isIIS();
|
||||||
$webserver = $this->findWebserver();
|
$webserver = $this->findWebserver();
|
||||||
|
|
||||||
|
// Get project dirs to inspect
|
||||||
|
$projectDir = $this->getProjectDir();
|
||||||
|
$projectSrcDir = $this->getProjectSrcDir();
|
||||||
|
|
||||||
$this->requirePHPVersion('5.5.0', '5.5.0', array(
|
$this->requirePHPVersion('5.5.0', '5.5.0', array(
|
||||||
"PHP Configuration",
|
"PHP Configuration",
|
||||||
"PHP5 installed",
|
"PHP5 installed",
|
||||||
@ -271,11 +201,11 @@ class InstallRequirements
|
|||||||
$this->getBaseDir()
|
$this->getBaseDir()
|
||||||
));
|
));
|
||||||
|
|
||||||
$this->requireModule('mysite', array(
|
$this->requireModule($projectDir, [
|
||||||
"File permissions",
|
"File permissions",
|
||||||
"mysite/ directory exists?",
|
"{$projectDir}/ directory exists?",
|
||||||
''
|
''
|
||||||
));
|
]);
|
||||||
$this->requireModule('vendor/silverstripe/framework', array(
|
$this->requireModule('vendor/silverstripe/framework', array(
|
||||||
"File permissions",
|
"File permissions",
|
||||||
"vendor/silverstripe/framework/ directory exists?",
|
"vendor/silverstripe/framework/ directory exists?",
|
||||||
@ -283,7 +213,15 @@ class InstallRequirements
|
|||||||
));
|
));
|
||||||
|
|
||||||
|
|
||||||
$this->requireWriteable($this->getPublicDir() . 'index.php', array("File permissions", "Is the index.php file writeable?", null), true);
|
$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);
|
$this->requireWriteable('.env', ["File permissions", "Is the .env file writeable?", null], false, false);
|
||||||
|
|
||||||
@ -294,29 +232,37 @@ class InstallRequirements
|
|||||||
"SilverStripe requires Apache version 2 or greater",
|
"SilverStripe requires Apache version 2 or greater",
|
||||||
$webserver
|
$webserver
|
||||||
));
|
));
|
||||||
$this->requireWriteable($this->getPublicDir() . '.htaccess', array("File permissions", "Is the .htaccess file writeable?", null), true);
|
$this->requireWriteable(
|
||||||
|
$this->getPublicDir() . '.htaccess',
|
||||||
|
array("File permissions", "Is the .htaccess file writeable?", null),
|
||||||
|
true
|
||||||
|
);
|
||||||
} elseif ($isIIS) {
|
} elseif ($isIIS) {
|
||||||
$this->requireWriteable($this->getPublicDir() . 'web.config', array("File permissions", "Is the web.config file writeable?", null), true);
|
$this->requireWriteable(
|
||||||
|
$this->getPublicDir() . 'web.config',
|
||||||
|
array("File permissions", "Is the web.config file writeable?", null),
|
||||||
|
true
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->requireWriteable('mysite/_config.php', array(
|
$this->requireWriteable("{$projectDir}/_config.php", [
|
||||||
"File permissions",
|
"File permissions",
|
||||||
"Is the mysite/_config.php file writeable?",
|
"Is the {$projectDir}/_config.php file writeable?",
|
||||||
null
|
null,
|
||||||
));
|
]);
|
||||||
|
|
||||||
$this->requireWriteable('mysite/_config/theme.yml', array(
|
$this->requireWriteable("{$projectDir}/_config/theme.yml", [
|
||||||
"File permissions",
|
"File permissions",
|
||||||
"Is the mysite/_config/theme.yml file writeable?",
|
"Is the {$projectDir}/_config/theme.yml file writeable?",
|
||||||
null
|
null,
|
||||||
));
|
]);
|
||||||
|
|
||||||
if (!$this->checkModuleExists('cms')) {
|
if (!$this->checkModuleExists('cms')) {
|
||||||
$this->requireWriteable('mysite/code/RootURLController.php', array(
|
$this->requireWriteable("{$projectSrcDir}/RootURLController.php", [
|
||||||
"File permissions",
|
"File permissions",
|
||||||
"Is the mysite/code/RootURLController.php file writeable?",
|
"Is the {$projectSrcDir}/RootURLController.php file writeable?",
|
||||||
null
|
null,
|
||||||
));
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check public folder exists
|
// Check public folder exists
|
||||||
@ -332,7 +278,11 @@ class InstallRequirements
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Ensure root assets dir is writable
|
// Ensure root assets dir is writable
|
||||||
$this->requireWriteable(ASSETS_PATH, array("File permissions", "Is the assets/ directory writeable?", null), true);
|
$this->requireWriteable(
|
||||||
|
ASSETS_PATH,
|
||||||
|
array("File permissions", "Is the assets/ directory writeable?", null),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
// Ensure all assets files are writable
|
// Ensure all assets files are writable
|
||||||
$innerIterator = new RecursiveDirectoryIterator(ASSETS_PATH, RecursiveDirectoryIterator::SKIP_DOTS);
|
$innerIterator = new RecursiveDirectoryIterator(ASSETS_PATH, RecursiveDirectoryIterator::SKIP_DOTS);
|
||||||
@ -824,35 +774,6 @@ class InstallRequirements
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 ($dirname === 'mysite') {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The same as {@link requireFile()} but does additional checks
|
* The same as {@link requireFile()} but does additional checks
|
||||||
* to ensure the module directory is intact.
|
* to ensure the module directory is intact.
|
||||||
@ -867,7 +788,7 @@ class InstallRequirements
|
|||||||
if (!file_exists($path)) {
|
if (!file_exists($path)) {
|
||||||
$testDetails[2] .= " Directory '$path' not found. Please make sure you have uploaded the SilverStripe files to your webserver correctly.";
|
$testDetails[2] .= " Directory '$path' not found. Please make sure you have uploaded the SilverStripe files to your webserver correctly.";
|
||||||
$this->error($testDetails);
|
$this->error($testDetails);
|
||||||
} elseif (!file_exists($path . '/_config.php') && $dirname != 'mysite') {
|
} 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 "
|
$testDetails[2] .= " Directory '$path' exists, but is missing files. Please make sure you have uploaded "
|
||||||
. "the SilverStripe files to your webserver correctly.";
|
. "the SilverStripe files to your webserver correctly.";
|
||||||
$this->error($testDetails);
|
$this->error($testDetails);
|
||||||
@ -985,29 +906,6 @@ class InstallRequirements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function requireApacheRewriteModule($moduleName, $testDetails)
|
public function requireApacheRewriteModule($moduleName, $testDetails)
|
||||||
{
|
{
|
||||||
$this->testing($testDetails);
|
$this->testing($testDetails);
|
||||||
@ -1019,15 +917,6 @@ class InstallRequirements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines if the web server has any rewriting capability.
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
public function hasRewritingCapability()
|
|
||||||
{
|
|
||||||
return ($this->testApacheRewriteExists() || $this->testIISRewriteModuleExists());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function requireIISRewriteModule($moduleName, $testDetails)
|
public function requireIISRewriteModule($moduleName, $testDetails)
|
||||||
{
|
{
|
||||||
$this->testing($testDetails);
|
$this->testing($testDetails);
|
||||||
@ -1039,22 +928,6 @@ class InstallRequirements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function requireDatabaseFunctions($databaseConfig, $testDetails)
|
public function requireDatabaseFunctions($databaseConfig, $testDetails)
|
||||||
{
|
{
|
||||||
$this->testing($testDetails);
|
$this->testing($testDetails);
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace SilverStripe\Dev\Install;
|
namespace SilverStripe\Dev\Install;
|
||||||
|
|
||||||
|
use BadMethodCallException;
|
||||||
use Exception;
|
use Exception;
|
||||||
use SilverStripe\Control\Cookie;
|
use SilverStripe\Control\Cookie;
|
||||||
use SilverStripe\Control\HTTPApplication;
|
use SilverStripe\Control\HTTPApplication;
|
||||||
@ -11,6 +12,7 @@ use SilverStripe\Core\Convert;
|
|||||||
use SilverStripe\Core\CoreKernel;
|
use SilverStripe\Core\CoreKernel;
|
||||||
use SilverStripe\Core\EnvironmentLoader;
|
use SilverStripe\Core\EnvironmentLoader;
|
||||||
use SilverStripe\Core\Kernel;
|
use SilverStripe\Core\Kernel;
|
||||||
|
use SilverStripe\Core\Path;
|
||||||
use SilverStripe\Core\Startup\ParameterConfirmationToken;
|
use SilverStripe\Core\Startup\ParameterConfirmationToken;
|
||||||
use SilverStripe\ORM\DatabaseAdmin;
|
use SilverStripe\ORM\DatabaseAdmin;
|
||||||
use SilverStripe\Security\DefaultAdminService;
|
use SilverStripe\Security\DefaultAdminService;
|
||||||
@ -19,13 +21,37 @@ use SilverStripe\Security\Security;
|
|||||||
/**
|
/**
|
||||||
* This installer doesn't use any of the fancy SilverStripe stuff in case it's unsupported.
|
* This installer doesn't use any of the fancy SilverStripe stuff in case it's unsupported.
|
||||||
*/
|
*/
|
||||||
class Installer extends InstallRequirements
|
class Installer
|
||||||
{
|
{
|
||||||
|
use InstallEnvironmentAware;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Errors during install
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $errors = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* value='' attribute placeholder for password fields
|
* value='' attribute placeholder for password fields
|
||||||
*/
|
*/
|
||||||
const PASSWORD_PLACEHOLDER = '********';
|
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()
|
protected function installHeader()
|
||||||
{
|
{
|
||||||
$clientPath = PUBLIC_DIR
|
$clientPath = PUBLIC_DIR
|
||||||
@ -43,8 +69,6 @@ class Installer extends InstallRequirements
|
|||||||
<div class="install-header">
|
<div class="install-header">
|
||||||
<div class="inner">
|
<div class="inner">
|
||||||
<div class="brand">
|
<div class="brand">
|
||||||
<span class="logo"></span>
|
|
||||||
|
|
||||||
<h1>SilverStripe</h1>
|
<h1>SilverStripe</h1>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -68,9 +92,10 @@ class Installer extends InstallRequirements
|
|||||||
{
|
{
|
||||||
// Render header
|
// Render header
|
||||||
$this->installHeader();
|
$this->installHeader();
|
||||||
|
|
||||||
$isIIS = $this->isIIS();
|
$isIIS = $this->isIIS();
|
||||||
$isApache = $this->isApache();
|
$isApache = $this->isApache();
|
||||||
|
$projectDir = $this->getProjectDir();
|
||||||
|
$projectSrcDir = $this->getProjectSrcDir();
|
||||||
|
|
||||||
flush();
|
flush();
|
||||||
|
|
||||||
@ -80,10 +105,12 @@ class Installer extends InstallRequirements
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Cleanup _config.php
|
// Cleanup _config.php
|
||||||
if (file_exists('mysite/_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
|
// 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
|
// differently to UNIX based filesystems - it takes the permissions from the parent directory instead of retaining them
|
||||||
$fh = fopen('mysite/_config.php', 'wb');
|
$fh = fopen($appConfigPath, 'wb');
|
||||||
fclose($fh);
|
fclose($fh);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,17 +122,18 @@ class Installer extends InstallRequirements
|
|||||||
|
|
||||||
// Write other stuff
|
// Write other stuff
|
||||||
if (!$this->checkModuleExists('cms')) {
|
if (!$this->checkModuleExists('cms')) {
|
||||||
$this->writeToFile("mysite/code/RootURLController.php", <<<PHP
|
$rootURLControllerPath = $basePath . "{$projectSrcDir}/RootURLController.php";
|
||||||
|
$this->writeToFile($rootURLControllerPath, <<<PHP
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use SilverStripe\\Control\\Controller;
|
use SilverStripe\\Control\\Controller;
|
||||||
|
|
||||||
class RootURLController extends Controller {
|
class RootURLController extends Controller
|
||||||
|
{
|
||||||
public function index() {
|
public function index()
|
||||||
echo "<html>Your site is now set up. Start adding controllers to mysite to get started.</html>";
|
{
|
||||||
|
echo "<html>Your site is now set up. Start adding controllers to app/src to get started.</html>";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
PHP
|
PHP
|
||||||
);
|
);
|
||||||
@ -124,7 +152,7 @@ PHP
|
|||||||
$request = HTTPRequestBuilder::createFromEnvironment();
|
$request = HTTPRequestBuilder::createFromEnvironment();
|
||||||
|
|
||||||
// Install kernel (fix to dev)
|
// Install kernel (fix to dev)
|
||||||
$kernel = new CoreKernel(BASE_PATH);
|
$kernel = new CoreKernel(Path::normalise($basePath));
|
||||||
$kernel->setEnvironment(Kernel::DEV);
|
$kernel->setEnvironment(Kernel::DEV);
|
||||||
$app = new HTTPApplication($kernel);
|
$app = new HTTPApplication($kernel);
|
||||||
|
|
||||||
@ -197,6 +225,15 @@ PHP
|
|||||||
</noscript>
|
</noscript>
|
||||||
HTML;
|
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;
|
return $this->errors;
|
||||||
@ -310,8 +347,9 @@ PHP;
|
|||||||
*/
|
*/
|
||||||
protected function writeConfigPHP($config)
|
protected function writeConfigPHP($config)
|
||||||
{
|
{
|
||||||
|
$configPath = $this->getProjectDir() . DIRECTORY_SEPARATOR . "_config.php";
|
||||||
if ($config['usingEnv']) {
|
if ($config['usingEnv']) {
|
||||||
$this->writeToFile("mysite/_config.php", "<?php\n ");
|
$this->writeToFile($configPath, "<?php\n ");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -325,7 +363,7 @@ PHP;
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
$databaseConfigContent = implode(",\n", $lines);
|
$databaseConfigContent = implode(",\n", $lines);
|
||||||
$this->writeToFile("mysite/_config.php", <<<PHP
|
$this->writeToFile($configPath, <<<PHP
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use SilverStripe\\ORM\\DB;
|
use SilverStripe\\ORM\\DB;
|
||||||
@ -347,6 +385,7 @@ PHP
|
|||||||
{
|
{
|
||||||
// Escape user input for safe insertion into PHP file
|
// Escape user input for safe insertion into PHP file
|
||||||
$locale = $this->ymlString($config['locale']);
|
$locale = $this->ymlString($config['locale']);
|
||||||
|
$projectDir = $this->getProjectDir();
|
||||||
|
|
||||||
// Set either specified, or no theme
|
// Set either specified, or no theme
|
||||||
if ($config['theme'] && $config['theme'] !== 'tutorial') {
|
if ($config['theme'] && $config['theme'] !== 'tutorial') {
|
||||||
@ -364,7 +403,7 @@ YML;
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Write theme.yml
|
// Write theme.yml
|
||||||
$this->writeToFile("mysite/_config/theme.yml", <<<YML
|
$this->writeToFile("{$projectDir}/_config/theme.yml", <<<YML
|
||||||
---
|
---
|
||||||
Name: mytheme
|
Name: mytheme
|
||||||
---
|
---
|
||||||
@ -399,17 +438,23 @@ YML
|
|||||||
*/
|
*/
|
||||||
public function writeToFile($filename, $content, $absolute = false)
|
public function writeToFile($filename, $content, $absolute = false)
|
||||||
{
|
{
|
||||||
$path = $absolute
|
// Get absolute / relative paths by either combining or removing base from path
|
||||||
? $filename
|
list($absolutePath, $relativePath) = $absolute
|
||||||
: $this->getBaseDir() . $filename;
|
? [
|
||||||
$this->statusMessage("Setting up $path");
|
$filename,
|
||||||
|
substr($filename, strlen($this->getBaseDir()))]
|
||||||
|
: [
|
||||||
|
$this->getBaseDir() . $filename,
|
||||||
|
$filename
|
||||||
|
];
|
||||||
|
$this->statusMessage("Setting up $relativePath");
|
||||||
|
|
||||||
if ((@$fh = fopen($path, 'wb')) && fwrite($fh, $content) && fclose($fh)) {
|
if ((@$fh = fopen($absolutePath, 'wb')) && fwrite($fh, $content) && fclose($fh)) {
|
||||||
// Set permissions to writable
|
// Set permissions to writable
|
||||||
@chmod($path, 0775);
|
@chmod($absolutePath, 0775);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
$this->error("Couldn't write to file $path");
|
$this->error("Couldn't write to file $relativePath");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ Feature: Manage users
|
|||||||
When I click the "Users" CMS tab
|
When I click the "Users" CMS tab
|
||||||
And I click "staffmember@example.org" in the "#Root_Users" element
|
And I click "staffmember@example.org" in the "#Root_Users" element
|
||||||
And I select "ADMIN group" from "Groups"
|
And I select "ADMIN group" from "Groups"
|
||||||
And I press the "Save" button
|
And I press the "Apply changes" button
|
||||||
Then I should see a "Saved Member" message
|
Then I should see a "Saved Member" message
|
||||||
|
|
||||||
When I go to "admin/security"
|
When I go to "admin/security"
|
||||||
|
@ -29,7 +29,7 @@ Feature: Manage Security Permissions for Groups
|
|||||||
Then the "Access to 'Security' section" checkbox should be checked
|
Then the "Access to 'Security' section" checkbox should be checked
|
||||||
|
|
||||||
# Save so the driver can reset without having to deal with the popup alert.
|
# Save so the driver can reset without having to deal with the popup alert.
|
||||||
Then I press the "Save" button
|
Then I press the "Apply changes" button
|
||||||
|
|
||||||
Scenario: I can see sub-permissions being properly set and restored when using "Full administrative rights"
|
Scenario: I can see sub-permissions being properly set and restored when using "Full administrative rights"
|
||||||
When I check "Access to 'Security' section"
|
When I check "Access to 'Security' section"
|
||||||
@ -46,11 +46,11 @@ Feature: Manage Security Permissions for Groups
|
|||||||
And the "Access to 'Security' section" field should be enabled
|
And the "Access to 'Security' section" field should be enabled
|
||||||
|
|
||||||
# Save so the driver can reset without having to deal with the popup alert.
|
# Save so the driver can reset without having to deal with the popup alert.
|
||||||
Then I press the "Save" button
|
Then I press the "Apply changes" button
|
||||||
|
|
||||||
Scenario: I can see sub-permissions being handled properly between reloads when using "Full administrative rights"
|
Scenario: I can see sub-permissions being handled properly between reloads when using "Full administrative rights"
|
||||||
When I check "Full administrative rights"
|
When I check "Full administrative rights"
|
||||||
And I press the "Save" button
|
And I press the "Apply changes" button
|
||||||
And I click the "Permissions" CMS tab
|
And I click the "Permissions" CMS tab
|
||||||
Then the "Full administrative rights" checkbox should be checked
|
Then the "Full administrative rights" checkbox should be checked
|
||||||
And the "Access to 'Security' section" checkbox should be checked
|
And the "Access to 'Security' section" checkbox should be checked
|
||||||
@ -60,7 +60,7 @@ Feature: Manage Security Permissions for Groups
|
|||||||
Then the "Access to 'Security' section" checkbox should not be checked
|
Then the "Access to 'Security' section" checkbox should not be checked
|
||||||
And the "Access to 'Security' section" field should be enabled
|
And the "Access to 'Security' section" field should be enabled
|
||||||
|
|
||||||
When I press the "Save" button
|
When I press the "Apply changes" button
|
||||||
And I click the "Permissions" CMS tab
|
And I click the "Permissions" CMS tab
|
||||||
Then the "Full administrative rights" checkbox should not be checked
|
Then the "Full administrative rights" checkbox should not be checked
|
||||||
And the "Access to 'Security' section" checkbox should not be checked
|
And the "Access to 'Security' section" checkbox should not be checked
|
||||||
@ -68,7 +68,7 @@ Feature: Manage Security Permissions for Groups
|
|||||||
|
|
||||||
Scenario: I can see sub-permissions being handled properly between reloads when using "Access to all CMS sections"
|
Scenario: I can see sub-permissions being handled properly between reloads when using "Access to all CMS sections"
|
||||||
When I check "Access to all CMS sections"
|
When I check "Access to all CMS sections"
|
||||||
And I press the "Save" button
|
And I press the "Apply changes" button
|
||||||
And I click the "Permissions" CMS tab
|
And I click the "Permissions" CMS tab
|
||||||
Then the "Access to all CMS sections" checkbox should be checked
|
Then the "Access to all CMS sections" checkbox should be checked
|
||||||
And the "Access to 'Security' section" checkbox should be checked
|
And the "Access to 'Security' section" checkbox should be checked
|
||||||
@ -78,7 +78,7 @@ Feature: Manage Security Permissions for Groups
|
|||||||
Then the "Access to 'Security' section" checkbox should not be checked
|
Then the "Access to 'Security' section" checkbox should not be checked
|
||||||
And the "Access to 'Security' section" field should be enabled
|
And the "Access to 'Security' section" field should be enabled
|
||||||
|
|
||||||
When I press the "Save" button
|
When I press the "Apply changes" button
|
||||||
And I click the "Permissions" CMS tab
|
And I click the "Permissions" CMS tab
|
||||||
Then the "Access to all CMS sections" checkbox should not be checked
|
Then the "Access to all CMS sections" checkbox should not be checked
|
||||||
And the "Access to 'Security' section" checkbox should not be checked
|
And the "Access to 'Security' section" checkbox should not be checked
|
||||||
|
Loading…
Reference in New Issue
Block a user