ENHANCEMENT Improve upgrade experience for beta3 -> beta4 upgrade

This commit is contained in:
Damian Mooyman 2017-10-10 15:23:00 +13:00
parent 5d6a10ca58
commit 11b2c74533
No known key found for this signature in database
GPG Key ID: 78B823A10DE27D1A
6 changed files with 198 additions and 21 deletions

View File

@ -951,3 +951,5 @@ skipConfigs:
excludedPaths: excludedPaths:
- '*fixtures*' - '*fixtures*'
- '*vendor*' - '*vendor*'
doctorTasks:
SilverStripe\Dev\Upgrade\UpgradeBootstrap: src/Dev/Upgrade/UpgradeBootstrap.php

View File

@ -78,7 +78,7 @@ some automated processes that users can run to
This section describes the processes which every project upgrading to 4.0 should follow. This should be followed This section describes the processes which every project upgrading to 4.0 should follow. This should be followed
as a standard first point of upgrade. as a standard first point of upgrade.
#### Upgrade your rewrite rules #### Upgrade project index.php and .htaccess rewrites
The location of SilverStripe's "entry file" has changed. Your project and server environment will need The location of SilverStripe's "entry file" has changed. Your project and server environment will need
to adjust the path to this file from `framework/main.php` to `index.php`. to adjust the path to this file from `framework/main.php` to `index.php`.
@ -87,8 +87,19 @@ please consult the [installation guides](getting_started/installation/).
Since 4.0, URL rewrite capabilities are required, Since 4.0, URL rewrite capabilities are required,
unless you PHP's built-in webserver through [silverstripe/serve](https://github.com/silverstripe/silverstripe-serve). unless you PHP's built-in webserver through [silverstripe/serve](https://github.com/silverstripe/silverstripe-serve).
The `index.php` file should already exist in your project, The [upgrader tool](https://github.com/silverstripe/silverstripe-upgrader/) has a task runner which
but needs its content replaced: automates this process for you.
```
composer global require silverstripe/upgrader
cd ~/Project/Root
~/.composer/vendor/bin/upgrade-code doctor
```
This will ensure that your `.htaccess` and `index.php` are set to a reasonable default value
for a clean installation.
After upgrade the `index.php` should look something similar to the below:
```php ```php
<?php <?php

View File

@ -65,6 +65,7 @@ class TempFolder
*/ */
protected static function getTempParentFolder($base) protected static function getTempParentFolder($base)
{ {
$base = rtrim($base, '/\\');
// first, try finding a silverstripe-cache dir built off the base path // first, try finding a silverstripe-cache dir built off the base path
$tempPath = $base . DIRECTORY_SEPARATOR . 'silverstripe-cache'; $tempPath = $base . DIRECTORY_SEPARATOR . 'silverstripe-cache';
if (@file_exists($tempPath)) { if (@file_exists($tempPath)) {

View File

@ -2,6 +2,7 @@
namespace SilverStripe\Dev\Install; namespace SilverStripe\Dev\Install;
use BadMethodCallException;
use Exception; use Exception;
use InvalidArgumentException; use InvalidArgumentException;
use SilverStripe\Core\TempFolder; use SilverStripe\Core\TempFolder;
@ -16,8 +17,25 @@ use SilverStripe\Core\TempFolder;
*/ */
class InstallRequirements class InstallRequirements
{ {
/**
* List of errors
*
* @var array
*/
protected $errors = []; protected $errors = [];
/**
* List of warnings
*
* @var array
*/
protected $warnings = []; protected $warnings = [];
/**
* List of tests
*
* @var array
*/
protected $tests = []; protected $tests = [];
/** /**
@ -26,6 +44,28 @@ class InstallRequirements
*/ */
protected $originalIni = []; protected $originalIni = [];
/**
* Base path
* @var
*/
protected $baseDir;
public function __construct($basePath = null)
{
if ($basePath) {
$this->baseDir = $basePath;
} elseif (defined('BASE_PATH')) {
$this->baseDir = BASE_PATH;
} else {
throw new BadMethodCallException("No BASE_PATH defined");
}
}
public function getBaseDir()
{
return rtrim($this->baseDir, '/\\') . '/';
}
/** /**
* Check the database configuration. These are done one after another * Check the database configuration. These are done one after another
* starting with checking the database function exists in PHP, and * starting with checking the database function exists in PHP, and
@ -217,6 +257,8 @@ class InstallRequirements
'', '',
)); ));
$this->requireWriteable('index.php', array("File permissions", "Is the index.php file writeable?", null));
if ($isApache) { if ($isApache) {
$this->checkApacheVersion(array( $this->checkApacheVersion(array(
"Webserver Configuration", "Webserver Configuration",
@ -251,7 +293,7 @@ class InstallRequirements
$this->requireWriteable('assets', array("File permissions", "Is the assets/ directory writeable?", null)); $this->requireWriteable('assets', array("File permissions", "Is the assets/ directory writeable?", null));
try { try {
$tempFolder = TempFolder::getTempFolder(BASE_PATH); $tempFolder = TempFolder::getTempFolder($this->getBaseDir());
} catch (Exception $e) { } catch (Exception $e) {
$tempFolder = false; $tempFolder = false;
} }
@ -732,8 +774,25 @@ class InstallRequirements
*/ */
public function checkModuleExists($dirname) public function checkModuleExists($dirname)
{ {
$path = $this->getBaseDir() . $dirname; // Mysite is base-only and doesn't need _config.php to be counted
return file_exists($path) && ($dirname == 'mysite' || file_exists($path . '/_config.php')); 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;
} }
/** /**
@ -828,7 +887,7 @@ class InstallRequirements
$this->testing($testDetails); $this->testing($testDetails);
try { try {
$tempFolder = TempFolder::getTempFolder(BASE_PATH); $tempFolder = TempFolder::getTempFolder($this->getBaseDir());
} catch (Exception $e) { } catch (Exception $e) {
$tempFolder = false; $tempFolder = false;
} }
@ -1070,14 +1129,6 @@ class InstallRequirements
} }
} }
// Must be PHP4 compatible
var $baseDir;
public function getBaseDir()
{
return BASE_PATH . '/';
}
public function testing($testDetails) public function testing($testDetails)
{ {
if (!$testDetails) { if (!$testDetails) {

View File

@ -20,12 +20,6 @@ use SilverStripe\Security\Security;
*/ */
class Installer extends InstallRequirements class Installer extends InstallRequirements
{ {
public function __construct()
{
// Cache the baseDir value
$this->getBaseDir();
}
protected function installHeader() protected function installHeader()
{ {
?> ?>
@ -86,6 +80,7 @@ class Installer extends InstallRequirements
} }
// Write all files // Write all files
$this->writeIndexPHP();
$this->writeConfigPHP($config); $this->writeConfigPHP($config);
$this->writeConfigYaml($config); $this->writeConfigYaml($config);
$this->writeConfigEnv($config); $this->writeConfigEnv($config);
@ -199,6 +194,31 @@ HTML;
return $this->errors; return $this->errors;
} }
protected function writeIndexPHP()
{
$content = <<<'PHP'
<?php
use SilverStripe\Control\HTTPApplication;
use SilverStripe\Control\HTTPRequestBuilder;
use SilverStripe\Core\CoreKernel;
use SilverStripe\Core\Startup\ErrorControlChainMiddleware;
require __DIR__ . '/vendor/autoload.php';
// Build request and detect flush
$request = HTTPRequestBuilder::createFromEnvironment();
// Default application
$kernel = new CoreKernel(BASE_PATH);
$app = new HTTPApplication($kernel);
$app->addMiddleware(new ErrorControlChainMiddleware($app));
$response = $app->handle($request);
$response->output();
PHP;
$this->writeToFile('index.php', $content);
}
/** /**
* Write all .env files * Write all .env files
* *

View File

@ -0,0 +1,92 @@
<?php
namespace SilverStripe\Dev\Upgrade;
use BadMethodCallException;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Provides upgrade interface for bootstrapping.
*
* Note: This class is intended to be loaded from outside of a SilverStripe application
* and should not reference any SilverStripe API.
*
* See https://github.com/silverstripe/silverstripe-upgrader/ for information
* on running this task.
*/
class UpgradeBootstrap
{
/**
* List of files to install.
* Set to true if the file should be re-installed if it doesn't exist.
*
* @var array
*/
protected $files = [
'.htaccess' => true,
'index.php' => true,
'install.php' => false,
];
/**
* @param InputInterface $input
* @param OutputInterface $output
* @param $basePath
*/
public function __invoke(InputInterface $input, OutputInterface $output, $basePath)
{
// Fail if destination isn't writable
$this->ensureWritable($basePath);
// Check source
$source = $basePath . '/vendor/silverstripe/recipe-core';
if (!is_dir($source)) {
throw new BadMethodCallException("silverstripe/recipe-core is not installed.");
}
// Copy scaffolded files from recipe-core
$output->writeln("Upgrading project bootstrapping files:");
foreach ($this->files as $file => $canCreate) {
$fileSource = $source . '/' . $file;
$fileDest = $basePath . '/' . $file;
// Skip if we should only upgrade existing files
if (!$canCreate && !file_exists($fileDest)) {
continue;
}
$output->writeln(" - Upgrading <info>{$file}</info>");
$this->copyFile(
$fileSource,
$fileDest
);
}
}
/**
* Ensure path is writable
*
* @param string $path
*/
protected function ensureWritable($path)
{
if (!is_writable($path)) {
throw new BadMethodCallException("Path $path is not writable");
}
}
/**
* Copy file
*
* @param string $source
* @param string $dest
*/
protected function copyFile($source, $dest)
{
// Ensure existing file can be overwritten
if (file_exists($dest)) {
$this->ensureWritable($dest);
}
file_put_contents($dest, file_get_contents($source));
}
}