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:
Damian Mooyman 2018-05-21 18:08:34 +08:00 committed by Aaron Carlino
parent b0e46ea5c0
commit 865ebb3398
6 changed files with 366 additions and 209 deletions

View File

@ -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';
} }
/** /**

View 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);
}
}

View File

@ -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);

View File

@ -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;
} }

View File

@ -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"

View File

@ -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