Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decouple exceptions from exception handling #6361

Merged
merged 8 commits into from
Feb 7, 2017
2 changes: 1 addition & 1 deletion app/view/twig/exception/database/_invalid-path.twig
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
</h1>

<p>
The database {{ type }} <code>{{ path }}</code> {{ error }}
The database {{ subtype }} <code>{{ path }}</code> {{ error }}
</p>
<p>
Make sure it's present and writable to the user that the web server is using.
Expand Down
2 changes: 1 addition & 1 deletion app/view/twig/exception/system/_apache.twig
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<h1>
The file <code>{{ webroot|default('{{ web root }}') }}/.htaccess</code> doesn't exist.
The file <code>{{ webroot|default('{{ web root }}') }}/.htaccess</code> doesn't exist.
</h1>

<p>
Expand Down
92 changes: 4 additions & 88 deletions src/Configuration/LowlevelChecks.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@
namespace Bolt\Configuration;

use Bolt\Configuration\Validation\ValidatorInterface;
use Bolt\Controller;
use Bolt\Exception\BootException;
use Symfony\Component\HttpFoundation\Response;

/**
* @deprecated Deprecated since 3.1, to be removed in 4.0.
Expand Down Expand Up @@ -208,99 +206,17 @@ public function checkApache()
}
}

/**
* @return Controller\Exception
*/
private function getExceptionController()
{
return $this->config->app['controller.exception'];
}

/**
* Perform the check for the database folder. We do this seperately, because it can only
* be done _after_ the other checks, since we need to have the $config, to see if we even
* _need_ to do this check.
*
* @return Response|null
*/
public function doDatabaseCheck()
{
$cfg = $this->config->app['config']->get('general/database');
$driver = $cfg['driver'];

if ($driver === 'pdo_sqlite') {
return $this->doDatabaseSqliteCheck($cfg);
}

if (!in_array($driver, ['pdo_mysql', 'pdo_pgsql'])) {
return $this->getExceptionController()->databaseDriver('unsupported', null, $driver);
}

if ($driver == 'pdo_mysql' && !$this->mysqlLoaded) {
return $this->getExceptionController()->databaseDriver('missing', 'MySQL', 'pdo_mysql');
}

if ($driver == 'pdo_pgsql' && !$this->postgresLoaded) {
return $this->getExceptionController()->databaseDriver('missing', 'PostgreSQL', 'pdo_pgsql');
}

if (empty($cfg['dbname'])) {
return $this->getExceptionController()->databaseDriver('parameter', null, $driver, 'databasename');
}
if (empty($cfg['user'])) {
return $this->getExceptionController()->databaseDriver('parameter', null, $driver, 'username');
}
if (empty($cfg['password']) && ($cfg['user'] === 'root')) {
return $this->getExceptionController()->databaseDriver('insecure', null, $driver);
}

return null;
}

protected function doDatabaseSqliteCheck($config)
{
if (!$this->sqliteLoaded) {
return $this->getExceptionController()->databaseDriver('missing', 'SQLite', 'pdo_sqlite');
}

// If in-memory connection, skip path checks
if (isset($config['memory']) && $config['memory'] === true) {
return null;
}

// If the file is present, make sure it is writable
$file = $config['path'];
if (file_exists($file)) {
if (!is_writable($file)) {
return $this->getExceptionController()->databasePath('file', $file, 'is not writable');
}

return null;
}

// If the file isn't present, make sure the directory
// exists and is writable so the file can be created
$dir = dirname($file);
if (!file_exists($dir)) {
// At this point, it is possible that the site has been moved and
// the configured Sqlite database file path is no longer relevant
// to the site's root path
$cacheJson = $this->config->getPath('cache/config-cache.json');
if (file_exists($cacheJson)) {
unlink($cacheJson);
$this->config->app['config']->initialize();
$config = $this->config->app['config']->get('general/database');
if (!file_exists(dirname($config['path']))) {
return $this->getExceptionController()->databasePath('folder', $dir, 'does not exist');
}
} else {
return $this->getExceptionController()->databasePath('folder', $dir, 'does not exist');
}
}

if (!is_writable($dir)) {
return $this->getExceptionController()->databasePath('folder', $dir, 'is not writable');
}
$validator = new Validation\Database();
$validator->setResourceManager($this->config);
$validator->setConfig($this->config->app['config']);
$validator->check();
}

public function disableApacheChecks()
Expand Down
18 changes: 5 additions & 13 deletions src/Configuration/Validation/Apache.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use Bolt\Configuration\LowlevelChecks;
use Bolt\Configuration\ResourceManager;
use Bolt\Controller\ExceptionControllerInterface;
use Bolt\Exception\Configuration\Validation\System\ApacheValidationException;
use Symfony\Component\HttpFoundation\Request;

/**
Expand All @@ -26,31 +26,23 @@ class Apache implements ValidationInterface, ResourceManagerAwareInterface
*
* {@inheritdoc}
*/
public function check(ExceptionControllerInterface $exceptionController)
public function check()
{
$request = Request::createFromGlobals();
$serverSoftware = $request->server->get('SERVER_SOFTWARE', '');
$isApache = strpos($serverSoftware, 'Apache') !== false;
/** @var LowlevelChecks $verifier */
$verifier = $this->resourceManager->getVerifier();
if ($verifier && $verifier->disableApacheChecks === true || !$isApache) {
return null;
return;
}

$path = $this->resourceManager->getPath('web/.htaccess');
if (is_readable($path)) {
return null;
return;
}

return $exceptionController->systemCheck(Validator::CHECK_APACHE);
}

/**
* {@inheritdoc}
*/
public function isTerminal()
{
return true;
throw new ApacheValidationException();
}

/**
Expand Down
18 changes: 4 additions & 14 deletions src/Configuration/Validation/Cache.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace Bolt\Configuration\Validation;

use Bolt\Configuration\ResourceManager;
use Bolt\Controller\ExceptionControllerInterface;
use Bolt\Exception\Configuration\Validation\System\CacheValidationException;

/**
* Cache validation check.
Expand All @@ -18,25 +18,15 @@ class Cache implements ValidationInterface, ResourceManagerAwareInterface
/**
* {@inheritdoc}
*/
public function check(ExceptionControllerInterface $exceptionController)
public function check()
{
$path = $this->resourceManager->getPath('cache');
if (!is_dir($path)) {
return $exceptionController->systemCheck(Validator::CHECK_CACHE, [], ['path' => $path]);
throw new CacheValidationException($path);
}
if (!is_writable($path)) {
return $exceptionController->systemCheck(Validator::CHECK_CACHE, [], ['path' => $path]);
throw new CacheValidationException($path);
}

return null;
}

/**
* {@inheritdoc}
*/
public function isTerminal()
{
return true;
}

/**
Expand Down
13 changes: 3 additions & 10 deletions src/Configuration/Validation/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
namespace Bolt\Configuration\Validation;

use Bolt\Config;
use Bolt\Controller\ExceptionControllerInterface;
use Bolt\Logger\FlashLoggerInterface;

/**
Expand All @@ -17,6 +16,8 @@ class Configuration implements ValidationInterface, ConfigAwareInterface, FlashL
private $config;
/** @var FlashLoggerInterface */
private $flashLogger;
/** @var string */
private $baseName;

/**
* Constructor.
Expand All @@ -31,7 +32,7 @@ public function __construct($baseName)
/**
* {@inheritdoc}
*/
public function check(ExceptionControllerInterface $exceptionController)
public function check()
{
$exceptions = $this->config->getExceptions();
if ($exceptions === null) {
Expand All @@ -43,14 +44,6 @@ public function check(ExceptionControllerInterface $exceptionController)
}
}

/**
* {@inheritdoc}
*/
public function isTerminal()
{
return true;
}

/**
* {@inheritdoc}
*/
Expand Down
55 changes: 23 additions & 32 deletions src/Configuration/Validation/Database.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@

use Bolt\Config;
use Bolt\Configuration\ResourceManager;
use Bolt\Controller;
use Bolt\Controller\ExceptionControllerInterface;
use Bolt\Exception\Configuration\Validation\Database\DatabaseParameterException;
use Bolt\Exception\Configuration\Validation\Database\InsecureDatabaseException;
use Bolt\Exception\Configuration\Validation\Database\MissingDatabaseExtensionException;
use Bolt\Exception\Configuration\Validation\Database\SqlitePathException;
use Bolt\Exception\Configuration\Validation\Database\UnsupportedDatabaseException;
use Symfony\Component\Filesystem\Exception\IOException;
use Symfony\Component\Filesystem\Filesystem;

Expand All @@ -24,48 +27,38 @@ class Database implements ValidationInterface, ResourceManagerAwareInterface, Co
/**
* {@inheritdoc}
*/
public function check(ExceptionControllerInterface $exceptionController)
public function check()
{
/** @var Controller\Exception $exceptionController */

$dbConfig = $this->config->get('general/database');
$driver = $dbConfig['driver'];

if ($driver === 'pdo_sqlite') {
return $this->doDatabaseSqliteCheck($exceptionController, $dbConfig);
$this->doDatabaseSqliteCheck($dbConfig);

return;
}

if (!in_array($driver, ['pdo_mysql', 'pdo_pgsql'])) {
return $exceptionController->databaseDriver('unsupported', null, $driver);
throw new UnsupportedDatabaseException($driver);
}

if ($driver === 'pdo_mysql' && extension_loaded('pdo_mysql') === false) {
return $exceptionController->databaseDriver('missing', 'MySQL', 'pdo_mysql');
throw new MissingDatabaseExtensionException($driver);
}

if ($driver === 'pdo_pgsql' && extension_loaded('pdo_pgsql') === false) {
return $exceptionController->databaseDriver('missing', 'PostgreSQL', 'pdo_pgsql');
throw new MissingDatabaseExtensionException($driver);
}

if (empty($dbConfig['dbname'])) {
return $exceptionController->databaseDriver('parameter', null, $driver, 'databasename');
throw new DatabaseParameterException('databasename', $driver);
}
if (empty($dbConfig['user'])) {
return $exceptionController->databaseDriver('parameter', null, $driver, 'username');
throw new DatabaseParameterException('username', $driver);
}
if (empty($dbConfig['password']) && ($dbConfig['user'] === 'root')) {
return $exceptionController->databaseDriver('insecure', null, $driver);
throw new InsecureDatabaseException($driver);
}

return null;
}

/**
* {@inheritdoc}
*/
public function isTerminal()
{
return true;
}

/**
Expand All @@ -84,15 +77,15 @@ public function setConfig(Config $config)
$this->config = $config;
}

protected function doDatabaseSqliteCheck(Controller\Exception $exceptionController, array $dbConfig)
protected function doDatabaseSqliteCheck(array $dbConfig)
{
if (extension_loaded('pdo_sqlite') === false) {
return $exceptionController->databaseDriver('missing', 'SQLite', 'pdo_sqlite');
throw new MissingDatabaseExtensionException('pdo_sqlite');
}

// If in-memory connection, skip path checks
if (isset($dbConfig['memory']) && $dbConfig['memory'] === true) {
return null;
return;
}

$fs = new Filesystem();
Expand All @@ -103,10 +96,10 @@ protected function doDatabaseSqliteCheck(Controller\Exception $exceptionControll
try {
$fs->touch($file);
} catch (IOException $e) {
return $exceptionController->databasePath('file', $file, 'is not writable');
throw SqlitePathException::fileNotWritable($file);
}

return null;
return;
}

// If the file isn't present, make sure the directory
Expand All @@ -122,19 +115,17 @@ protected function doDatabaseSqliteCheck(Controller\Exception $exceptionControll
$this->config->initialize();

if (!$fs->exists($dir)) {
return $exceptionController->databasePath('folder', $dir, 'does not exist');
throw SqlitePathException::folderMissing($dir);
}
} else {
return $exceptionController->databasePath('folder', $dir, 'does not exist');
throw SqlitePathException::folderMissing($dir);
}
}

try {
$fs->touch($dir);
} catch (IOException $e) {
return $exceptionController->databasePath('folder', $dir, 'is not writable');
throw SqlitePathException::folderNotWritable($dir);
}

return null;
}
}
Loading