Commit dee5a8d1 authored by Tino Goratsch's avatar Tino Goratsch

save current work in progress at getting rid of the global constants

parent 94d2c395
<?php
namespace ACP3\Core\Application;
use ACP3\Core\Application\BootstrapInterface;
use ACP3\Core\Enum\Environment;
use ACP3\Core\Environment\ApplicationMode;
use ACP3\Core\Environment\ApplicationPath;
use ACP3\Core\ErrorHandler;
use Monolog\Logger;
use Monolog\Formatter\LineFormatter;
use Monolog\Handler\StreamHandler;
use Monolog\Logger;
/**
* Class AbstractBootstrap
......@@ -21,14 +21,27 @@ abstract class AbstractBootstrap implements BootstrapInterface
/**
* @var string
*/
protected $environment;
protected $appMode;
/**
* @var \ACP3\Core\Environment\ApplicationPath
*/
protected $appPath;
/**
* @param string $appMode
*/
public function __construct($appMode = ApplicationMode::PRODUCTION)
{
$this->appMode = $appMode;
$this->setAppPath($appMode);
}
/**
* @param string $environment
* @param string $appMode
*/
public function __construct($environment = Environment::PRODUCTION)
protected function setAppPath($appMode)
{
$this->environment = $environment;
$this->appPath = new ApplicationPath($appMode);
}
/**
......@@ -36,7 +49,7 @@ abstract class AbstractBootstrap implements BootstrapInterface
*/
public function setErrorHandler()
{
$stream = new StreamHandler(CACHE_DIR . 'logs/system.log', Logger::NOTICE);
$stream = new StreamHandler($this->appPath->getCacheDir() . 'logs/system.log', Logger::NOTICE);
$stream->setFormatter(new LineFormatter(null, null, true));
$logger = new Logger('system', [$stream]);
......@@ -58,13 +71,12 @@ abstract class AbstractBootstrap implements BootstrapInterface
*/
protected function databaseConfigExists()
{
$path = ACP3_DIR . 'config.yml';
$path = $this->appPath->getAppDir() . 'config.yml';
if (is_file($path) === false || filesize($path) === 0) {
echo 'The ACP3 is not correctly installed. Please navigate to the <a href="' . ROOT_DIR . 'installation/">installation wizard</a> and follow its instructions.';
echo 'The ACP3 is not correctly installed. Please navigate to the <a href="' . $this->appPath->getWebRoot() . 'installation/">installation wizard</a> and follow its instructions.';
return false;
}
return true;
}
}
\ No newline at end of file
......@@ -2,13 +2,11 @@
namespace ACP3\Core\Application;
use ACP3\Core\Application\AbstractBootstrap;
use ACP3\Core\Enum\Environment;
use ACP3\Core\Environment\ApplicationMode;
use ACP3\Core\Exceptions;
use ACP3\Core\FrontController;
use ACP3\Core\Http\RequestInterface;
use ACP3\Core\Modules;
use ACP3\Core\Logger as ACP3Logger;
use ACP3\Core\Redirect;
use ACP3\Core\ServiceContainerBuilder;
use Patchwork\Utf8;
......@@ -57,13 +55,13 @@ class Bootstrap extends AbstractBootstrap
*/
public function defineDirConstants()
{
define('PHP_SELF', htmlentities($_SERVER['SCRIPT_NAME']));
define('ROOT_DIR', substr(PHP_SELF, 0, strrpos(PHP_SELF, '/') + 1));
define('ACP3_DIR', ACP3_ROOT_DIR . 'ACP3/');
define('CLASSES_DIR', ACP3_DIR . 'Core/');
define('MODULES_DIR', ACP3_DIR . 'Modules/');
define('UPLOADS_DIR', ACP3_ROOT_DIR . 'uploads/');
define('CACHE_DIR', ACP3_ROOT_DIR . 'cache/' . $this->environment . '/');
// define('PHP_SELF', $this->appPath->getPhpSelf());
// define('ROOT_DIR', $this->appPath->getWebRoot());
// define('ACP3_DIR', $this->appPath->getAppDir());
// define('CLASSES_DIR', $this->appPath->getClassesDir());
// define('MODULES_DIR', $this->appPath->getModulesDir());
// define('UPLOADS_DIR', $this->appPath->getUploadsDir());
// define('CACHE_DIR', $this->appPath->getCacheDir());
}
/**
......@@ -83,7 +81,7 @@ class Bootstrap extends AbstractBootstrap
$view = $this->container->get('core.view');
$view->assign('PAGE_TITLE', 'ACP3');
$view->assign('ROOT_DIR', ROOT_DIR);
$view->assign('ROOT_DIR', $this->appPath->getWebRoot());
$view->assign('CONTENT', $this->systemSettings['maintenance_message']);
$view->displayTemplate('system/maintenance.tpl');
......@@ -102,12 +100,14 @@ class Bootstrap extends AbstractBootstrap
Utf8\Bootup::filterRequestUri(); // Redirects to an UTF-8 encoded URL if it's not already the case
Utf8\Bootup::filterRequestInputs(); // Normalizes HTTP inputs to UTF-8 NFC
$file = CACHE_DIR . 'sql/container.php';
$file = $this->appPath->getCacheDir() . 'sql/container.php';
$this->dumpContainer($file);
require_once $file;
$this->container = new \ACP3ServiceContainer();
$this->appPath = $this->container->get('core.environment.application_path');
}
/**
......@@ -115,9 +115,16 @@ class Bootstrap extends AbstractBootstrap
*/
private function _setThemeConstants()
{
define('DESIGN_PATH', ROOT_DIR . 'designs/' . $this->systemSettings['design'] . '/');
define('DESIGN_PATH_INTERNAL', ACP3_ROOT_DIR . 'designs/' . $this->systemSettings['design'] . '/');
define('DESIGN_PATH_ABSOLUTE', $this->container->get('core.request')->getDomain() . DESIGN_PATH);
$path = 'designs/' . $this->systemSettings['design'] . '/';
$this->appPath
->setDesignPathWeb($this->appPath->getWebRoot() . $path)
->setDesignPathInternal(ACP3_ROOT_DIR . $path)
->setDesignPathAbsolute($this->container->get('core.request')->getDomain() . $this->appPath->getDesignPathWeb());
define('DESIGN_PATH', $this->appPath->getDesignPathWeb());
define('DESIGN_PATH_INTERNAL', $this->appPath->getDesignPathInternal());
define('DESIGN_PATH_ABSOLUTE', $this->appPath->getDesignPathAbsolute());
}
/**
......@@ -144,9 +151,10 @@ class Bootstrap extends AbstractBootstrap
(new FrontController($this->container))->dispatch();
} catch (Exceptions\ResultNotExists $e) {
if ($e->getMessage()) {
ACP3Logger::error('404', $e);
$this->container->get('core.logger')->error('404', $e);
} else {
ACP3Logger::error('404', 'Could not find any results for request: ' . $request->getQuery());
$this->container->get('core.logger')->error('404',
'Could not find any results for request: ' . $request->getQuery());
}
$redirect->temporary('errors/index/404')->send();
......@@ -156,12 +164,12 @@ class Bootstrap extends AbstractBootstrap
} catch (Exceptions\AccessForbidden $e) {
$redirect->temporary('errors/index/403');
} catch (Exceptions\ControllerActionNotFound $e) {
ACP3Logger::error('404', 'Request: ' . $request->getQuery());
ACP3Logger::error('404', $e);
$this->container->get('core.logger')->error('404', 'Request: ' . $request->getQuery());
$this->container->get('core.logger')->error('404', $e);
$this->handleException($e, $redirect, 'errors/index/404');
} catch (\Exception $e) {
ACP3Logger::error('exception', $e);
$this->container->get('core.logger')->error('exception', $e);
$this->handleException($e, $redirect, 'errors/index/500');
}
......@@ -183,7 +191,7 @@ class Bootstrap extends AbstractBootstrap
private function _renderApplicationException($errorMessage)
{
$view = $this->container->get('core.view');
$view->assign('ROOT_DIR', ROOT_DIR);
$view->assign('ROOT_DIR', $this->appPath->getWebRoot());
$view->assign('PAGE_TITLE', 'ACP3');
$view->assign('CONTENT', $errorMessage);
$view->displayTemplate('system/exception.tpl');
......@@ -196,7 +204,7 @@ class Bootstrap extends AbstractBootstrap
*/
protected function handleException(\Exception $exception, Redirect $redirect, $path)
{
if ($this->environment === Environment::DEVELOPMENT) {
if ($this->appMode === ApplicationMode::DEVELOPMENT) {
$errorMessage = $exception->getMessage();
$this->_renderApplicationException($errorMessage);
} else {
......@@ -209,10 +217,10 @@ class Bootstrap extends AbstractBootstrap
*/
protected function dumpContainer($file)
{
$containerConfigCache = new ConfigCache($file, ($this->environment === Environment::DEVELOPMENT));
$containerConfigCache = new ConfigCache($file, ($this->appMode === ApplicationMode::DEVELOPMENT));
if (!$containerConfigCache->isFresh()) {
$containerBuilder = ServiceContainerBuilder::compileContainer($this->environment);
$containerBuilder = ServiceContainerBuilder::compileContainer($this->appMode, $this->appPath);
$dumper = new PhpDumper($containerBuilder);
$containerConfigCache->write(
......
......@@ -4,6 +4,7 @@ namespace ACP3\Core\Assets;
use ACP3\Core\Assets;
use ACP3\Core\Cache;
use ACP3\Core\Config;
use ACP3\Core\Environment\ApplicationPath;
use ACP3\Core\Modules;
/**
......@@ -20,6 +21,10 @@ abstract class AbstractMinifier implements MinifierInterface
* @var \ACP3\Core\Assets
*/
protected $assets;
/**
* @var \ACP3\Core\Environment\ApplicationPath
*/
protected $appPath;
/**
* @var \ACP3\Core\Cache
*/
......@@ -55,15 +60,17 @@ abstract class AbstractMinifier implements MinifierInterface
protected $assetGroup = '';
/**
* @param \ACP3\Core\Assets $assets
* @param \ACP3\Core\Cache $systemCache
* @param \ACP3\Core\Config $config
* @param \ACP3\Core\Modules $modules
* @param \ACP3\Core\Assets\FileResolver $fileResolver
* @param string $environment
* @param \ACP3\Core\Assets $assets
* @param \ACP3\Core\Environment\ApplicationPath $appPath
* @param \ACP3\Core\Cache $systemCache
* @param \ACP3\Core\Config $config
* @param \ACP3\Core\Modules $modules
* @param \ACP3\Core\Assets\FileResolver $fileResolver
* @param string $environment
*/
public function __construct(
Assets $assets,
ApplicationPath $appPath,
Cache $systemCache,
Config $config,
Modules $modules,
......@@ -72,6 +79,7 @@ abstract class AbstractMinifier implements MinifierInterface
)
{
$this->assets = $assets;
$this->appPath = $appPath;
$this->systemCache = $systemCache;
$this->config = $config;
$this->modules = $modules;
......@@ -129,7 +137,7 @@ abstract class AbstractMinifier implements MinifierInterface
$path = $this->buildAssetPath($debug, $this->assetGroup, $filenameHash, $lastGenerated);
// If the requested minified StyleSheet and/or the JavaScript file doesn't exist, generate it
if (is_file(UPLOADS_DIR . $path) === false || $debug === true) {
if (is_file($this->appPath->getUploadsDir() . $path) === false || $debug === true) {
// Get the enabled libraries and filter out empty entries
$files = array_filter(
$this->processLibraries($layout),
......@@ -138,13 +146,13 @@ abstract class AbstractMinifier implements MinifierInterface
}
);
$this->saveMinifiedAsset($files, UPLOADS_DIR . $path);
$this->saveMinifiedAsset($files, $this->appPath->getUploadsDir() . $path);
// Save the time of the generation if the requested file
$this->systemCache->save($cacheId, $lastGenerated);
}
return ROOT_DIR . 'uploads/' . $path . ($debug === true ? '?v=' . $lastGenerated : '');
return $this->appPath->getWebRoot() . 'uploads/' . $path . ($debug === true ? '?v=' . $lastGenerated : '');
}
/**
......
......@@ -13,6 +13,10 @@ class FileResolver
* @var \ACP3\Core\XML
*/
protected $xml;
/**
* @var \ACP3\Core\Environment\ApplicationPath
*/
protected $appPath;
/**
* @var \ACP3\Core\Assets\Cache
*/
......@@ -32,27 +36,33 @@ class FileResolver
/**
* @var string
*/
protected $modulesAssetsPath = MODULES_DIR;
protected $modulesAssetsPath;
/**
* @var string
*/
protected $designAssetsPath = DESIGN_PATH_INTERNAL;
protected $designAssetsPath;
/**
* @param \ACP3\Core\XML $xml
* @param \ACP3\Core\Assets\Cache $resourcesCache
* @param \ACP3\Core\Modules\Vendors $vendors
* @param \ACP3\Core\XML $xml
* @param \ACP3\Core\Assets\Cache $resourcesCache
* @param \ACP3\Core\Environment\ApplicationPath $appPath
* @param \ACP3\Core\Modules\Vendors $vendors
*/
public function __construct(
Core\XML $xml,
Core\Assets\Cache $resourcesCache,
Core\Environment\ApplicationPath $appPath,
Core\Modules\Vendors $vendors
)
{
$this->xml = $xml;
$this->resourcesCache = $resourcesCache;
$this->appPath = $appPath;
$this->vendors = $vendors;
$this->cachedPaths = $resourcesCache->getCache();
$this->modulesAssetsPath = $appPath->getModulesDir();
$this->designAssetsPath = $appPath->getDesignPathInternal();
}
/**
......@@ -118,7 +128,7 @@ class FileResolver
if (!empty($designInfo['parent'])) {
$this->designAssetsPath = ACP3_ROOT_DIR . 'designs/' . $designInfo['parent'];
$assetPath = $this->getStaticAssetPath($modulePath, $designPath, $dir, $file);
$this->designAssetsPath = DESIGN_PATH_INTERNAL;
$this->designAssetsPath = $this->appPath->getDesignPathInternal();
}
// No overrides have been found -> iterate over all possible module namespaces
......
<?php
namespace ACP3\Core;
use ACP3\Core\Enum\Environment;
use ACP3\Core\Environment\ApplicationMode;
use ACP3\Core\Environment\ApplicationPath;
use Symfony\Component\DependencyInjection\Container;
/**
......@@ -29,16 +30,17 @@ class Cache
/**
* @param \Symfony\Component\DependencyInjection\Container $container
* @param \ACP3\Core\Environment\ApplicationPath $appPath
* @param string $namespace
*
* @throws \InvalidArgumentException
*/
public function __construct(
Container $container,
ApplicationPath $appPath,
$namespace
)
{
$this->container = $container;
$this->appPath = $appPath;
$this->namespace = $namespace;
}
......@@ -158,14 +160,14 @@ class Cache
}
// If debug mode is enabled, override the cache driver configuration
if ($this->container->getParameter('core.environment') === Environment::DEVELOPMENT) {
if ($this->container->getParameter('core.environment') === ApplicationMode::DEVELOPMENT) {
$driverName = 'Array';
}
$cacheDriverPath = "\\Doctrine\\Common\\Cache\\" . $driverName . 'Cache';
if (class_exists($cacheDriverPath)) {
if ($driverName === 'PhpFile') {
$cacheDir = CACHE_DIR . 'sql/';
$cacheDir = $this->appPath->getCacheDir() . 'sql/';
$this->driver = new $cacheDriverPath($cacheDir);
} else {
$this->driver = new $cacheDriverPath();
......
......@@ -2,8 +2,9 @@
namespace ACP3\Core;
use ACP3\Core\DB\SQLLogger;
use ACP3\Core\Enum\Environment;
use \Doctrine\DBAL;
use ACP3\Core\Environment\ApplicationMode;
use ACP3\Core\Environment\ApplicationPath;
use Doctrine\DBAL;
use Doctrine\DBAL\Cache\QueryCacheProfile;
/**
......@@ -12,6 +13,14 @@ use Doctrine\DBAL\Cache\QueryCacheProfile;
*/
class DB
{
/**
* @var \ACP3\Core\Logger
*/
protected $logger;
/**
* @var \ACP3\Core\Environment\ApplicationPath
*/
protected $appPath;
/**
* @var \Doctrine\DBAL\Connection
*/
......@@ -26,19 +35,23 @@ class DB
protected $prefix = '';
/**
* @param string $environment
* @param string $host
* @param string $database
* @param string $userName
* @param string $password
* @param string $tablePrefix
* @param string $driver
* @param string $charset
* @param string $cacheDriverName
* @param \ACP3\Core\Logger $logger
* @param \ACP3\Core\Environment\ApplicationPath $appPath
* @param string $environment
* @param string $host
* @param string $database
* @param string $userName
* @param string $password
* @param string $tablePrefix
* @param string $driver
* @param string $charset
* @param string $cacheDriverName
*
* @throws \Doctrine\DBAL\DBALException
*/
public function __construct(
Logger $logger,
ApplicationPath $appPath,
$environment,
$host,
$database,
......@@ -48,34 +61,13 @@ class DB
$driver = 'pdo_mysql',
$charset = 'utf8',
$cacheDriverName = 'Array'
)
{
$config = new DBAL\Configuration();
$connectionParams = [
'dbname' => $database,
'user' => $userName,
'password' => $password,
'host' => $host,
'driver' => $driver,
'charset' => $charset
];
if ($environment === Environment::DEVELOPMENT) {
$config->setSQLLogger(new SQLLogger());
}
$className = "\\Doctrine\\Common\\Cache\\" . $cacheDriverName . "Cache";
/** @var \Doctrine\Common\Cache\CacheProvider $cacheDriverName */
if (strtolower($cacheDriverName)) {
$cacheDriverName = new $className(CACHE_DIR . 'sql/');
} else {
$cacheDriverName = new $className();
}
$cacheDriverName->setNamespace('db-queries');
$config->setResultCacheImpl($cacheDriverName);
) {
$this->logger = $logger;
$this->appPath = $appPath;
$this->connection = DBAL\DriverManager::getConnection($connectionParams, $config);
$this->connection = $this->attemptDbConnection(
$environment, $host, $database, $userName, $password, $driver, $charset, $cacheDriverName
);
$this->prefix = $tablePrefix;
$this->database = $database;
......@@ -125,8 +117,14 @@ class DB
*
* @return array
*/
public function fetchAll($statement, array $params = [], array $types = [], $cache = false, $lifetime = 0, $cacheKey = null)
{
public function fetchAll(
$statement,
array $params = [],
array $types = [],
$cache = false,
$lifetime = 0,
$cacheKey = null
) {
$stmt = $this->executeQuery($statement, $params, $types, $cache, $lifetime, $cacheKey);
$data = $stmt->fetchAll();
$stmt->closeCursor();
......@@ -183,13 +181,20 @@ class DB
* @throws \Doctrine\DBAL\Cache\CacheException
* @throws \Doctrine\DBAL\DBALException
*/
public function executeQuery($query, array $params = [], array $types = [], $cache = false, $lifetime = 0, $cacheKey = null)
{
public function executeQuery(
$query,
array $params = [],
array $types = [],
$cache = false,
$lifetime = 0,
$cacheKey = null
) {
if ($cache === false) {
return $this->connection->executeQuery($query, $params, $types);
}
return $this->connection->executeCacheQuery($query, $params, $types, new QueryCacheProfile($lifetime, $cacheKey ?: md5($query)));
return $this->connection->executeCacheQuery($query, $params, $types,
new QueryCacheProfile($lifetime, $cacheKey ?: md5($query)));
}
/**
......@@ -208,10 +213,70 @@ class DB
$this->connection->commit();
} catch (\Exception $e) {
$this->connection->rollBack();
Logger::error('database', $e->getMessage());
$this->logger->error('database', $e->getMessage());
$result = false;
}
return $result;
}
/**
* @param string $environment
* @param string $host
* @param string $database
* @param string $userName
* @param string $password
* @param string $driver
* @param string $charset
* @param string $cacheDriverName
*
* @return \Doctrine\DBAL\Connection
* @throws \Doctrine\DBAL\DBALException
*/
protected function attemptDbConnection(
$environment,
$host,
$database,
$userName,
$password,
$driver,
$charset,
$cacheDriverName
) {
$config = new DBAL\Configuration();
$connectionParams = [
'dbname' => $database,
'user' => $userName,
'password' => $password,
'host' => $host,
'driver' => $driver,
'charset' => $charset
];
if ($environment === ApplicationMode::DEVELOPMENT) {
$config->setSQLLogger(new SQLLogger($this->logger));
}
$this->applyQueryCache($cacheDriverName, $config);
return DBAL\DriverManager::getConnection($connectionParams, $config);
}
/**
* @param string $cacheDriverName
* @param \Doctrine\DBAL\Configuration $config
*/
protected function applyQueryCache($cacheDriverName, DBAL\Configuration $config)
{
$className = "\\Doctrine\\Common\\Cache\\" . $cacheDriverName . "Cache";
/** @var \Doctrine\Common\Cache\CacheProvider $cacheDriverName */
if (strtolower($cacheDriverName)) {
$cacheDriverName = new $className($this->appPath->getCacheDir() . 'sql/');
} else {
$cacheDriverName = new $className();
}
$cacheDriverName->setNamespace('db-queries');
$config->setResultCacheImpl($cacheDriverName);
}
}
......@@ -9,6 +9,10 @@ use ACP3\Core\Logger;
*/
class SQLLogger implements \Doctrine\DBAL\Logging\SQLLogger
{
/**
* @var \ACP3\Core\Logger
*/
protected $logger;
/**
* Executed SQL queries.
......@@ -36,8 +40,14 @@ class SQLLogger implements \Doctrine\DBAL\Logging\SQLLogger
*/
private $requestPath = '';
public function __construct()
/**
* SQLLogger constructor.
*
* @param \ACP3\Core\Logger $logger
*/
public function __construct(Logger $logger)
{
$this->logger = $logger;
$this->requestPath = $_SERVER['REQUEST_URI'];
}
......@@ -69,7 +79,7 @@ class SQLLogger implements \Doctrine\DBAL\Logging\SQLLogger
$this->queries[$this->requestPath]['queryCount'] = count($this->queries[$this->requestPath]);
$this->queries[$this->requestPath]['totalTime'] = $totalTime;
Logger::debug($this->logFilename, $this->queries);
$this->logger->debug($this->logFilename, $this->queries);
}
}
}
\ No newline at end of file
<?php
namespace ACP3\Core\Enum;
namespace ACP3\Core\Environment;
/**
* Class Environment
* @package ACP3\Core\Enum
* Class ApplicationMode
* @package ACP3\Core\Environment
*/
class Environment
class ApplicationMode
{
const PRODUCTION = 'prod';
const DEVELOPMENT = 'dev';
......
<?php
namespace ACP3\Core\Environment;
/**
* Class AppPath
* @package ACP3\Core\Environment
*/
class ApplicationPath
{
/**
* @var string
*/
protected $phpSelf;
/**
* @var string
*/
protected $webRoot;
/**
* @var string
*/
protected $appDir;
/**
* @var string
*/
protected $classesDir;
/**
* @var string
*/
protected $modulesDir;
/**
* @var string
*/
protected $uploadsDir;
/**
* @var string
*/
protected $cacheDir;
/**
* @var string
*/
protected $designPathInternal;
/**
* @var string