* Functions for error handling.
*/
-use Drupal\Component\Utility\SafeMarkup;
+use Drupal\Component\Render\FormattableMarkup;
use Drupal\Component\Utility\Xss;
use Drupal\Core\Logger\RfcLogLevel;
use Drupal\Core\Render\Markup;
'@backtrace_string' => (new \Exception())->getTraceAsString(),
], $recoverable || $to_string);
}
+ // If the site is a test site then fail for user deprecations so they can be
+ // caught by the deprecation error handler.
+ elseif (DRUPAL_TEST_IN_CHILD_SITE && $error_level === E_USER_DEPRECATED) {
+ $backtrace = debug_backtrace();
+ $caller = Error::getLastCaller($backtrace);
+ _drupal_error_header(
+ Markup::create(Xss::filterAdmin($message)),
+ 'User deprecated function',
+ $caller['function'],
+ $caller['file'],
+ $caller['line']
+ );
+ }
}
/**
// When running inside the testing framework, we relay the errors
// to the tested site by the way of HTTP headers.
if (DRUPAL_TEST_IN_CHILD_SITE && !headers_sent() && (!defined('SIMPLETEST_COLLECT_ERRORS') || SIMPLETEST_COLLECT_ERRORS)) {
- // $number does not use drupal_static as it should not be reset
- // as it uniquely identifies each PHP error.
- static $number = 0;
- $assertion = [
- $error['@message'],
- $error['%type'],
- [
- 'function' => $error['%function'],
- 'file' => $error['%file'],
- 'line' => $error['%line'],
- ],
- ];
- // For non-fatal errors (e.g. PHP notices) _drupal_log_error can be called
- // multiple times per request. In that case the response is typically
- // generated outside of the error handler, e.g., in a controller. As a
- // result it is not possible to use a Response object here but instead the
- // headers need to be emitted directly.
- header('X-Drupal-Assertion-' . $number . ': ' . rawurlencode(serialize($assertion)));
- $number++;
+ _drupal_error_header($error['@message'], $error['%type'], $error['%function'], $error['%file'], $error['%line']);
}
$response = new Response();
// installer.
if (\Drupal::hasService('logger.factory')) {
try {
- \Drupal::logger('php')->log($error['severity_level'], '%type: @message in %function (line %line of %file) @backtrace_string.', $error);
+ // Provide the PHP backtrace to logger implementations.
+ \Drupal::logger('php')->log($error['severity_level'], '%type: @message in %function (line %line of %file) @backtrace_string.', $error + ['backtrace' => $backtrace]);
}
catch (\Exception $e) {
// We can't log, for example because the database connection is not
if ($fatal) {
// When called from CLI, simply output a plain text message.
// Should not translate the string to avoid errors producing more errors.
- $response->setContent(html_entity_decode(strip_tags(SafeMarkup::format('%type: @message in %function (line %line of %file).', $error))) . "\n");
+ $response->setContent(html_entity_decode(strip_tags(new FormattableMarkup('%type: @message in %function (line %line of %file).', $error))) . "\n");
$response->send();
exit;
}
if (error_displayable($error)) {
// When called from JavaScript, simply output the error message.
// Should not translate the string to avoid errors producing more errors.
- $response->setContent(SafeMarkup::format('%type: @message in %function (line %line of %file).', $error));
+ $response->setContent(new FormattableMarkup('%type: @message in %function (line %line of %file).', $error));
$response->send();
}
exit;
if ($error_level != ERROR_REPORTING_DISPLAY_VERBOSE) {
// Without verbose logging, use a simple message.
- // We call SafeMarkup::format() directly here, rather than use t() since
- // we are in the middle of error handling, and we don't want t() to
- // cause further errors.
- $message = SafeMarkup::format('%type: @message in %function (line %line of %file).', $error);
+ // We use \Drupal\Component\Render\FormattableMarkup directly here,
+ // rather than use t() since we are in the middle of error handling, and
+ // we don't want t() to cause further errors.
+ $message = new FormattableMarkup('%type: @message in %function (line %line of %file).', $error);
}
else {
// With verbose logging, we will also include a backtrace.
array_shift($backtrace);
// Generate a backtrace containing only scalar argument values.
$error['@backtrace'] = Error::formatBacktrace($backtrace);
- $message = SafeMarkup::format('%type: @message in %function (line %line of %file). <pre class="backtrace">@backtrace</pre>', $error);
+ $message = new FormattableMarkup('%type: @message in %function (line %line of %file). <pre class="backtrace">@backtrace</pre>', $error);
}
}
if ($message) {
if (\Drupal::hasService('session')) {
// Message display is dependent on sessions being available.
- drupal_set_message($message, $class, TRUE);
+ \Drupal::messenger()->addMessage($message, $class, TRUE);
}
else {
print $message;
// request on a public site, so use the non-verbose default value.
return $error_level ?: ERROR_REPORTING_DISPLAY_ALL;
}
+
+/**
+ * Adds error information to headers so that tests can access it.
+ *
+ * @param $message
+ * The error message.
+ * @param $type
+ * The type of error.
+ * @param $function
+ * The function that emitted the error.
+ * @param $file
+ * The file that emitted the error.
+ * @param $line
+ * The line number in file that emitted the error.
+ */
+function _drupal_error_header($message, $type, $function, $file, $line) {
+ // $number does not use drupal_static as it should not be reset
+ // as it uniquely identifies each PHP error.
+ static $number = 0;
+ $assertion = [
+ $message,
+ $type,
+ [
+ 'function' => $function,
+ 'file' => $file,
+ 'line' => $line,
+ ],
+ ];
+ // For non-fatal errors (e.g. PHP notices) _drupal_log_error can be called
+ // multiple times per request. In that case the response is typically
+ // generated outside of the error handler, e.g., in a controller. As a
+ // result it is not possible to use a Response object here but instead the
+ // headers need to be emitted directly.
+ header('X-Drupal-Assertion-' . $number . ': ' . rawurlencode(serialize($assertion)));
+ $number++;
+}