Skip to content

Commit

Permalink
MERGE: Merge branch '5.1' into master
Browse files Browse the repository at this point in the history
# Conflicts:
#	Neos.Flow/Classes/Log/LoggerFactory.php
#	Neos.Flow/Documentation/TheDefinitiveGuide/PartV/TYPO3FluidViewHelperReference.rst
  • Loading branch information
kdambekalns committed Nov 9, 2018
2 parents 39abcd7 + f496abe commit 7c62dee
Show file tree
Hide file tree
Showing 10 changed files with 183 additions and 66 deletions.
12 changes: 10 additions & 2 deletions Neos.Cache/Classes/Backend/RedisBackend.php
Expand Up @@ -501,9 +501,17 @@ private function getRedisClient(): \Redis
$this->port = null;
}
$redis = new \Redis();
if (!$redis->connect($this->hostname, $this->port)) {
throw new CacheException('Could not connect to Redis.', 1391972021);

try {
$connected = false;
// keep the above! the line below leave the variable undefined if an error occurs.
$connected = $redis->connect($this->hostname, $this->port);
} finally {
if ($connected === false) {
throw new CacheException('Could not connect to Redis.', 1391972021);
}
}

if ($this->password !== '') {
if (!$redis->auth($this->password)) {
throw new CacheException('Redis authentication failed.', 1502366200);
Expand Down
62 changes: 59 additions & 3 deletions Neos.Flow/Classes/Core/Booting/Scripts.php
Expand Up @@ -25,6 +25,7 @@
use Neos\Flow\Error\Debugger;
use Neos\Flow\Error\ErrorHandler;
use Neos\Flow\Error\ProductionExceptionHandler;
use Neos\Flow\Http\HttpRequestHandlerInterface;
use Neos\Flow\Log\Logger;
use Neos\Flow\Log\LoggerBackendConfigurationHelper;
use Neos\Flow\Log\LoggerFactory;
Expand Down Expand Up @@ -240,8 +241,7 @@ public static function initializeSystemLogger(Bootstrap $bootstrap)
$configurationManager = $bootstrap->getEarlyInstance(ConfigurationManager::class);
$settings = $configurationManager->getConfiguration(ConfigurationManager::CONFIGURATION_TYPE_SETTINGS, 'Neos.Flow');

$throwableStorage = new FileStorage();
$throwableStorage->injectStoragePath(FLOW_PATH_DATA . 'Logs/Exceptions');
$throwableStorage = self::initializeExceptionStorage($bootstrap);
$bootstrap->setEarlyInstance(ThrowableStorageInterface::class, $throwableStorage);

/** @var PsrLoggerFactoryInterface $psrLoggerFactoryName */
Expand All @@ -254,7 +254,7 @@ public static function initializeSystemLogger(Bootstrap $bootstrap)
$psrLogFactory = $psrLoggerFactoryName::create($psrLogConfigurations);

// This is all deprecated and can be removed with the removal of respective interfaces and classes.
$loggerFactory = new LoggerFactory($psrLogFactory);
$loggerFactory = new LoggerFactory($psrLogFactory, $throwableStorage);
$bootstrap->setEarlyInstance($psrLoggerFactoryName, $psrLogFactory);
$bootstrap->setEarlyInstance(PsrLoggerFactoryInterface::class, $psrLogFactory);
$bootstrap->setEarlyInstance(LoggerFactory::class, $loggerFactory);
Expand All @@ -265,6 +265,62 @@ public static function initializeSystemLogger(Bootstrap $bootstrap)
$bootstrap->setEarlyInstance(SystemLoggerInterface::class, $systemLogger);
}

/**
* Initialize the exception storage
*
* @param Bootstrap $bootstrap
* @return ThrowableStorageInterface
* @throws FlowException
* @throws \Neos\Flow\Configuration\Exception\InvalidConfigurationTypeException
*/
protected static function initializeExceptionStorage(Bootstrap $bootstrap): ThrowableStorageInterface
{
$configurationManager = $bootstrap->getEarlyInstance(ConfigurationManager::class);
$settings = $configurationManager->getConfiguration(ConfigurationManager::CONFIGURATION_TYPE_SETTINGS, 'Neos.Flow');

$storageClassName = $settings['log']['throwables']['storageClass'] ?? FileStorage::class;
$storageOptions = $settings['log']['throwables']['optionsByImplementation'][$storageClassName] ?? [];


if (!in_array(ThrowableStorageInterface::class, class_implements($storageClassName, true))) {
throw new \Exception(
sprintf('The class "%s" configured as throwable storage does not implement the ThrowableStorageInterface', $storageClassName),
1540583485
);
}

/** @var ThrowableStorageInterface $throwableStorage */
$throwableStorage = $storageClassName::createWithOptions($storageOptions);

$throwableStorage->setBacktraceRenderer(function ($backtrace) {
return Debugger::getBacktraceCode($backtrace, false, true);
});

$throwableStorage->setRequestInformationRenderer(function () {
$output = '';
if (!(Bootstrap::$staticObjectManager instanceof ObjectManagerInterface)) {
return $output;
}

$bootstrap = Bootstrap::$staticObjectManager->get(Bootstrap::class);
/* @var Bootstrap $bootstrap */
$requestHandler = $bootstrap->getActiveRequestHandler();
if (!$requestHandler instanceof HttpRequestHandlerInterface) {
return $output;
}

$request = $requestHandler->getHttpRequest();
$response = $requestHandler->getHttpResponse();
$output .= PHP_EOL . 'HTTP REQUEST:' . PHP_EOL . ($request == '' ? '[request was empty]' : $request) . PHP_EOL;
$output .= PHP_EOL . 'HTTP RESPONSE:' . PHP_EOL . ($response == '' ? '[response was empty]' : $response) . PHP_EOL;
$output .= PHP_EOL . 'PHP PROCESS:' . PHP_EOL . 'Inode: ' . getmyinode() . PHP_EOL . 'PID: ' . getmypid() . PHP_EOL . 'UID: ' . getmyuid() . PHP_EOL . 'GID: ' . getmygid() . PHP_EOL . 'User: ' . get_current_user() . PHP_EOL;

return $output;
});

return $throwableStorage;
}

/**
* Initializes the error handling
*
Expand Down
30 changes: 10 additions & 20 deletions Neos.Flow/Classes/Log/LoggerFactory.php
Expand Up @@ -23,6 +23,7 @@
*
* @api
* @Flow\Scope("singleton")
* @Flow\Autowiring(false)
* @deprecated Instead a \Neos\Flow\Log\PsrLoggerFactoryInterface should be used.
*/
class LoggerFactory
Expand All @@ -32,6 +33,11 @@ class LoggerFactory
*/
protected $psrLoggerFactory;

/**
* @var ThrowableStorageInterface
*/
protected $throwableStorage;

/**
* @var array
*/
Expand All @@ -46,10 +52,12 @@ class LoggerFactory
* LoggerFactory constructor.
*
* @param PsrLoggerFactoryInterface $psrLoggerFactory
* @param ThrowableStorageInterface $throwableStorage
*/
public function __construct(PsrLoggerFactoryInterface $psrLoggerFactory)
public function __construct(PsrLoggerFactoryInterface $psrLoggerFactory, ThrowableStorageInterface $throwableStorage)
{
$this->psrLoggerFactory = $psrLoggerFactory;
$this->throwableStorage = $throwableStorage;
$this->requestInfoCallback = function () {
$output = '';
if (!(Bootstrap::$staticObjectManager instanceof ObjectManagerInterface)) {
Expand Down Expand Up @@ -145,27 +153,9 @@ protected function instantiateLogger(string $loggerObjectName, $backendObjectNam
protected function injectAdditionalDependencies(LoggerInterface $logger): LoggerInterface
{
if ($logger instanceof Logger) {
$logger->injectThrowableStorage($this->instantiateThrowableStorage());
$logger->injectThrowableStorage($this->throwableStorage);
}

return $logger;
}

/**
* @return FileStorage|ThrowableStorageInterface
*/
protected function instantiateThrowableStorage(): ThrowableStorageInterface
{
// Fallback early throwable storage
$throwableStorage = new FileStorage();
$throwableStorage->injectStoragePath(FLOW_PATH_DATA . 'Logs/Exceptions');
if (Bootstrap::$staticObjectManager instanceof ObjectManagerInterface) {
$throwableStorage = Bootstrap::$staticObjectManager->get(ThrowableStorageInterface::class);
}
$throwableStorage->setBacktraceRenderer(function ($backtrace) {
return Debugger::getBacktraceCode($backtrace, false, true);
});
$throwableStorage->setRequestInformationRenderer($this->requestInfoCallback);
return $throwableStorage;
}
}
96 changes: 69 additions & 27 deletions Neos.Flow/Classes/Log/ThrowableStorage/FileStorage.php
@@ -1,20 +1,23 @@
<?php
namespace Neos\Flow\Log\ThrowableStorage;

use Neos\Flow\Annotations as Flow;
use Neos\Flow\Core\Bootstrap;
use Neos\Flow\Error\Debugger;
use Neos\Flow\Http\HttpRequestHandlerInterface;
use Neos\Flow\Log\PlainTextFormatter;
use Neos\Flow\Log\ThrowableStorageInterface;
use Neos\Flow\ObjectManagement\ObjectManagerInterface;
use Neos\Utility\Files;

/**
* Stores detailed information about throwables into files.
*
* @Flow\Proxy(false)
* @Flow\Autowiring(false)
*/
class FileStorage implements ThrowableStorageInterface
{
/**
* @var string
*/
protected $storagePath;

/**
* @var \Closure
*/
Expand All @@ -26,13 +29,59 @@ class FileStorage implements ThrowableStorageInterface
protected $backtraceRenderer;

/**
* FileStorage path.
* @var string
*/
protected $storagePath;

/**
* Factory method to get an instance.
*
* @param array $options
* @return ThrowableStorageInterface
*/
public static function createWithOptions(array $options): ThrowableStorageInterface
{
$storagePath = $options['storagePath'] ?? (FLOW_PATH_DATA . 'Logs/Exceptions');
$storage = new static($storagePath);

return $storage;
}

/**
* Create new instance.
*
* @param string $storagePath
* @see createWithOptions
*/
public function injectStoragePath(string $storagePath)
public function __construct(string $storagePath)
{
$this->storagePath = $storagePath;

$this->requestInformationRenderer = function () {
$output = '';
if (!(Bootstrap::$staticObjectManager instanceof ObjectManagerInterface)) {
return $output;
}

$bootstrap = Bootstrap::$staticObjectManager->get(Bootstrap::class);
/* @var Bootstrap $bootstrap */
$requestHandler = $bootstrap->getActiveRequestHandler();
if (!$requestHandler instanceof HttpRequestHandlerInterface) {
return $output;
}

$request = $requestHandler->getHttpRequest();
$response = $requestHandler->getHttpResponse();
$output .= PHP_EOL . 'HTTP REQUEST:' . PHP_EOL . ($request == '' ? '[request was empty]' : $request) . PHP_EOL;
$output .= PHP_EOL . 'HTTP RESPONSE:' . PHP_EOL . ($response == '' ? '[response was empty]' : $response) . PHP_EOL;
$output .= PHP_EOL . 'PHP PROCESS:' . PHP_EOL . 'Inode: ' . getmyinode() . PHP_EOL . 'PID: ' . getmypid() . PHP_EOL . 'UID: ' . getmyuid() . PHP_EOL . 'GID: ' . getmygid() . PHP_EOL . 'User: ' . get_current_user() . PHP_EOL;

return $output;
};

$this->backtraceRenderer = function ($backtrace) {
return Debugger::getBacktraceCode($backtrace, false, true);
};
}

/**
Expand All @@ -42,6 +91,7 @@ public function injectStoragePath(string $storagePath)
public function setRequestInformationRenderer(\Closure $requestInformationRenderer)
{
$this->requestInformationRenderer = $requestInformationRenderer;

return $this;
}

Expand All @@ -52,6 +102,7 @@ public function setRequestInformationRenderer(\Closure $requestInformationRender
public function setBacktraceRenderer(\Closure $backtraceRenderer)
{
$this->backtraceRenderer = $backtraceRenderer;

return $this;
}

Expand All @@ -62,22 +113,10 @@ public function setBacktraceRenderer(\Closure $backtraceRenderer)
*/
public function logThrowable(\Throwable $throwable, array $additionalData = [])
{
return $this->logError($throwable, $additionalData);
}

/**
* Writes information about the given exception into the log.
*
* @param \Throwable $error \Exception or \Throwable
* @param array $additionalData Additional data to log
* @return string The exception message
*/
protected function logError(\Throwable $error, array $additionalData = [])
{
$message = $this->getErrorLogMessage($error);
$message = $this->getErrorLogMessage($throwable);

if ($error->getPrevious() !== null) {
$additionalData['previousException'] = $this->getErrorLogMessage($error->getPrevious());
if ($throwable->getPrevious() !== null) {
$additionalData['previousException'] = $this->getErrorLogMessage($throwable->getPrevious());
}

if (!file_exists($this->storagePath)) {
Expand All @@ -88,10 +127,13 @@ protected function logError(\Throwable $error, array $additionalData = [])
}

// FIXME: getReferenceCode should probably become an interface.
$referenceCode = (is_callable([$error, 'getReferenceCode']) ? $error->getReferenceCode() : $this->generateUniqueReferenceCode());
$errorDumpPathAndFilename = Files::concatenatePaths([$this->storagePath, $referenceCode . '.txt']);
file_put_contents($errorDumpPathAndFilename, $this->renderErrorInfo($error, $additionalData));
$message .= ' - See also: ' . basename($errorDumpPathAndFilename);
$referenceCode = (is_callable([
$throwable,
'getReferenceCode'
]) ? $throwable->getReferenceCode() : $this->generateUniqueReferenceCode());
$throwableDumpPathAndFilename = Files::concatenatePaths([$this->storagePath, $referenceCode . '.txt']);
file_put_contents($throwableDumpPathAndFilename, $this->renderErrorInfo($throwable, $additionalData));
$message .= ' - See also: ' . basename($throwableDumpPathAndFilename);

return $message;
}
Expand Down Expand Up @@ -135,7 +177,7 @@ protected function renderErrorInfo(\Throwable $error, array $additionalData = []

$postMortemInfo .= PHP_EOL . $this->renderRequestInfo();
$postMortemInfo .= PHP_EOL;
$postMortemInfo .= (new PlainTextFormatter($additionalData))->format();
$postMortemInfo .= empty($additionalData) ? '' : (new PlainTextFormatter($additionalData))->format();

return $postMortemInfo;
}
Expand Down
11 changes: 11 additions & 0 deletions Neos.Flow/Classes/Log/ThrowableStorageInterface.php
Expand Up @@ -8,6 +8,17 @@
*/
interface ThrowableStorageInterface
{
/** TODO: Factory method to create an instance, should officially become part of the interface in next major.
*
* A factory method to create an instance of the throwable storage.
* Note that throwable storages must work without proxy so all dependencies need to be resolved manually or via options.
*
* @param array $options
* @return ThrowableStorageInterface
*/
// public static function createWithOptions(array $options): ThrowableStorageInterface;


/**
* Writes information about the given exception into the log.
*
Expand Down
18 changes: 15 additions & 3 deletions Neos.Flow/Classes/ObjectManagement/Proxy/ProxyMethod.php
Expand Up @@ -249,6 +249,7 @@ public function buildMethodParametersCode($fullClassName, $methodName, $addTypeA
{
$methodParametersCode = '';
$methodParameterTypeName = '';
$nullableSign = '';
$defaultValue = '';
$byReferenceSign = '';

Expand All @@ -265,11 +266,16 @@ public function buildMethodParametersCode($fullClassName, $methodName, $addTypeA
$methodParameterTypeName = 'array';
} elseif ($methodParameterInfo['scalarDeclaration']) {
$methodParameterTypeName = $methodParameterInfo['type'];
} elseif ($methodParameterInfo['class'] !== null) {
$methodParameterTypeName = '\\' . $methodParameterInfo['class'];
} else {
$methodParameterTypeName = ($methodParameterInfo['class'] === null) ? '' : '\\' . $methodParameterInfo['class'];
$methodParameterTypeName = '';
}
if (\PHP_MAJOR_VERSION >= 7 && \PHP_MINOR_VERSION >= 1) {
$nullableSign = $methodParameterInfo['allowsNull'] ? '?' : '';
}
if ($methodParameterInfo['optional'] === true) {
$rawDefaultValue = (isset($methodParameterInfo['defaultValue']) ? $methodParameterInfo['defaultValue'] : null);
$rawDefaultValue = $methodParameterInfo['defaultValue'] ?? null;
if ($rawDefaultValue === null) {
$defaultValue = ' = NULL';
} elseif (is_bool($rawDefaultValue)) {
Expand All @@ -285,7 +291,13 @@ public function buildMethodParametersCode($fullClassName, $methodName, $addTypeA
$byReferenceSign = ($methodParameterInfo['byReference'] ? '&' : '');
}

$methodParametersCode .= ($methodParametersCount > 0 ? ', ' : '') . ($methodParameterTypeName ? $methodParameterTypeName . ' ' : '') . $byReferenceSign . '$' . $methodParameterName . $defaultValue;
$methodParametersCode .= ($methodParametersCount > 0 ? ', ' : '')
. ($methodParameterTypeName ? $nullableSign . $methodParameterTypeName . ' ' : '')
. $byReferenceSign
. '$'
. $methodParameterName
. $defaultValue
;
$methodParametersCount++;
}
}
Expand Down

0 comments on commit 7c62dee

Please sign in to comment.