Use the scope of an instance
This commit is contained in:
parent
9df76ebbe5
commit
97f3023963
@ -22,10 +22,9 @@ class DeprecationErrorHandler
|
|||||||
const MODE_WEAK_VENDORS = 'weak_vendors';
|
const MODE_WEAK_VENDORS = 'weak_vendors';
|
||||||
const MODE_DISABLED = 'disabled';
|
const MODE_DISABLED = 'disabled';
|
||||||
|
|
||||||
private static $rawMode = false;
|
private $mode = false;
|
||||||
private static $mode = false;
|
private $resolvedMode = false;
|
||||||
private static $isRegistered = false;
|
private $deprecations = [
|
||||||
private static $deprecations = [
|
|
||||||
'unsilencedCount' => 0,
|
'unsilencedCount' => 0,
|
||||||
'remainingCount' => 0,
|
'remainingCount' => 0,
|
||||||
'legacyCount' => 0,
|
'legacyCount' => 0,
|
||||||
@ -37,7 +36,9 @@ class DeprecationErrorHandler
|
|||||||
'other' => [],
|
'other' => [],
|
||||||
'remaining vendor' => [],
|
'remaining vendor' => [],
|
||||||
];
|
];
|
||||||
private static $utilPrefix = '';
|
|
||||||
|
private static $isRegistered = false;
|
||||||
|
private static $utilPrefix;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers and configures the deprecation handler.
|
* Registers and configures the deprecation handler.
|
||||||
@ -50,68 +51,30 @@ class DeprecationErrorHandler
|
|||||||
* - use a number to define the upper bound of allowed deprecations,
|
* - use a number to define the upper bound of allowed deprecations,
|
||||||
* making the test suite fail whenever more notices are triggered.
|
* making the test suite fail whenever more notices are triggered.
|
||||||
*
|
*
|
||||||
* @param int|string|false $rawMode The reporting mode, defaults to not allowing any deprecations
|
* @param int|string|false $mode The reporting mode, defaults to not allowing any deprecations
|
||||||
*/
|
*/
|
||||||
public static function register($rawMode = 0)
|
public static function register($mode = 0)
|
||||||
{
|
{
|
||||||
if (self::$isRegistered) {
|
if (self::$isRegistered) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static::$rawMode = $rawMode;
|
self::$utilPrefix = class_exists('PHPUnit_Util_ErrorHandler') ? 'PHPUnit_Util_' : 'PHPUnit\Util\\';
|
||||||
|
|
||||||
$oldErrorHandler = set_error_handler([self::class, 'handleError']);
|
$handler = new self();
|
||||||
|
$oldErrorHandler = set_error_handler([$handler, 'handleError']);
|
||||||
|
|
||||||
if (null !== $oldErrorHandler) {
|
if (null !== $oldErrorHandler) {
|
||||||
restore_error_handler();
|
restore_error_handler();
|
||||||
if ([self::utilPrefix().'ErrorHandler', 'handleError'] === $oldErrorHandler) {
|
|
||||||
|
if ([self::$utilPrefix.'ErrorHandler', 'handleError'] === $oldErrorHandler) {
|
||||||
restore_error_handler();
|
restore_error_handler();
|
||||||
self::register($rawMode);
|
self::register($mode);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
$handler->mode = $mode;
|
||||||
self::$isRegistered = true;
|
self::$isRegistered = true;
|
||||||
register_shutdown_function(function () use ($rawMode) {
|
register_shutdown_function([$handler, 'shutdown']);
|
||||||
self::computeMode($rawMode);
|
|
||||||
$mode = self::$mode;
|
|
||||||
if (isset($mode[0]) && '/' === $mode[0]) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$currErrorHandler = set_error_handler('var_dump');
|
|
||||||
restore_error_handler();
|
|
||||||
|
|
||||||
if ($currErrorHandler !== [self::class, 'handleError']) {
|
|
||||||
echo "\n", self::colorize('THE ERROR HANDLER HAS CHANGED!', true, $mode), "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
$groups = ['unsilenced', 'remaining'];
|
|
||||||
if (self::MODE_WEAK_VENDORS === $mode) {
|
|
||||||
$groups[] = 'remaining vendor';
|
|
||||||
}
|
|
||||||
array_push($groups, 'legacy', 'other');
|
|
||||||
|
|
||||||
self::displayDeprecations($groups, $mode);
|
|
||||||
|
|
||||||
// store failing status
|
|
||||||
$isFailing = self::MODE_WEAK !== $mode && $mode < self::$deprecations['unsilencedCount'] + self::$deprecations['remainingCount'] + self::$deprecations['otherCount'];
|
|
||||||
|
|
||||||
// reset deprecations array
|
|
||||||
foreach (self::$deprecations as $group => $arrayOrInt) {
|
|
||||||
self::$deprecations[$group] = \is_int($arrayOrInt) ? 0 : [];
|
|
||||||
}
|
|
||||||
|
|
||||||
register_shutdown_function(function () use ($isFailing, $groups, $mode) {
|
|
||||||
foreach (self::$deprecations as $group => $arrayOrInt) {
|
|
||||||
if (0 < (\is_int($arrayOrInt) ? $arrayOrInt : \count($arrayOrInt))) {
|
|
||||||
echo "Shutdown-time deprecations:\n";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self::displayDeprecations($groups, $mode);
|
|
||||||
if ($isFailing || self::MODE_WEAK !== $mode && $mode < self::$deprecations['unsilencedCount'] + self::$deprecations['remainingCount'] + self::$deprecations['otherCount']) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,6 +86,7 @@ class DeprecationErrorHandler
|
|||||||
if ($previousErrorHandler) {
|
if ($previousErrorHandler) {
|
||||||
return $previousErrorHandler($type, $msg, $file, $line, $context);
|
return $previousErrorHandler($type, $msg, $file, $line, $context);
|
||||||
}
|
}
|
||||||
|
|
||||||
static $autoload = true;
|
static $autoload = true;
|
||||||
|
|
||||||
$ErrorHandler = class_exists('PHPUnit_Util_ErrorHandler', $autoload) ? 'PHPUnit_Util_ErrorHandler' : 'PHPUnit\Util\ErrorHandler';
|
$ErrorHandler = class_exists('PHPUnit_Util_ErrorHandler', $autoload) ? 'PHPUnit_Util_ErrorHandler' : 'PHPUnit\Util\ErrorHandler';
|
||||||
@ -130,6 +94,7 @@ class DeprecationErrorHandler
|
|||||||
|
|
||||||
return $ErrorHandler::handleError($type, $msg, $file, $line, $context);
|
return $ErrorHandler::handleError($type, $msg, $file, $line, $context);
|
||||||
}
|
}
|
||||||
|
|
||||||
$deprecations[] = [error_reporting(), $msg, $file];
|
$deprecations[] = [error_reporting(), $msg, $file];
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -138,6 +103,262 @@ class DeprecationErrorHandler
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
public function handleError($type, $msg, $file, $line, $context = [])
|
||||||
|
{
|
||||||
|
$mode = $this->getMode();
|
||||||
|
|
||||||
|
if ((E_USER_DEPRECATED !== $type && E_DEPRECATED !== $type) || self::MODE_DISABLED === $mode) {
|
||||||
|
$ErrorHandler = self::$utilPrefix.'ErrorHandler';
|
||||||
|
|
||||||
|
return $ErrorHandler::handleError($type, $msg, $file, $line, $context);
|
||||||
|
}
|
||||||
|
|
||||||
|
$trace = debug_backtrace();
|
||||||
|
$group = 'other';
|
||||||
|
$isVendor = self::MODE_WEAK_VENDORS === $mode && self::inVendors($file);
|
||||||
|
|
||||||
|
$i = \count($trace);
|
||||||
|
while (1 < $i && (!isset($trace[--$i]['class']) || ('ReflectionMethod' === $trace[$i]['class'] || 0 === strpos($trace[$i]['class'], 'PHPUnit_') || 0 === strpos($trace[$i]['class'], 'PHPUnit\\')))) {
|
||||||
|
// No-op
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($trace[$i]['object']) || isset($trace[$i]['class'])) {
|
||||||
|
if (isset($trace[$i]['class']) && 0 === strpos($trace[$i]['class'], 'Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerFor')) {
|
||||||
|
$parsedMsg = unserialize($msg);
|
||||||
|
$msg = $parsedMsg['deprecation'];
|
||||||
|
$class = $parsedMsg['class'];
|
||||||
|
$method = $parsedMsg['method'];
|
||||||
|
// If the deprecation has been triggered via
|
||||||
|
// \Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerTrait::endTest()
|
||||||
|
// then we need to use the serialized information to determine
|
||||||
|
// if the error has been triggered from vendor code.
|
||||||
|
$isVendor = self::MODE_WEAK_VENDORS === $mode && isset($parsedMsg['triggering_file']) && self::inVendors($parsedMsg['triggering_file']);
|
||||||
|
} else {
|
||||||
|
$class = isset($trace[$i]['object']) ? \get_class($trace[$i]['object']) : $trace[$i]['class'];
|
||||||
|
$method = $trace[$i]['function'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$Test = self::$utilPrefix.'Test';
|
||||||
|
|
||||||
|
if (0 !== error_reporting()) {
|
||||||
|
$group = 'unsilenced';
|
||||||
|
} elseif (0 === strpos($method, 'testLegacy')
|
||||||
|
|| 0 === strpos($method, 'provideLegacy')
|
||||||
|
|| 0 === strpos($method, 'getLegacy')
|
||||||
|
|| strpos($class, '\Legacy')
|
||||||
|
|| \in_array('legacy', $Test::getGroups($class, $method), true)
|
||||||
|
) {
|
||||||
|
$group = 'legacy';
|
||||||
|
} elseif ($isVendor) {
|
||||||
|
$group = 'remaining vendor';
|
||||||
|
} else {
|
||||||
|
$group = 'remaining';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($mode[0]) && '/' === $mode[0] && preg_match($mode, $msg)) {
|
||||||
|
$e = new \Exception($msg);
|
||||||
|
$r = new \ReflectionProperty($e, 'trace');
|
||||||
|
$r->setAccessible(true);
|
||||||
|
$r->setValue($e, \array_slice($trace, 1, $i));
|
||||||
|
|
||||||
|
echo "\n".ucfirst($group).' deprecation triggered by '.$class.'::'.$method.':';
|
||||||
|
echo "\n".$msg;
|
||||||
|
echo "\nStack trace:";
|
||||||
|
echo "\n".str_replace(' '.getcwd().\DIRECTORY_SEPARATOR, ' ', $e->getTraceAsString());
|
||||||
|
echo "\n";
|
||||||
|
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('legacy' !== $group && self::MODE_WEAK !== $mode) {
|
||||||
|
$ref = &$this->deprecations[$group][$msg]['count'];
|
||||||
|
++$ref;
|
||||||
|
$ref = &$this->deprecations[$group][$msg][$class.'::'.$method];
|
||||||
|
++$ref;
|
||||||
|
}
|
||||||
|
} elseif (self::MODE_WEAK !== $mode) {
|
||||||
|
$ref = &$this->deprecations[$group][$msg]['count'];
|
||||||
|
++$ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
++$this->deprecations[$group.'Count'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
public function shutdown()
|
||||||
|
{
|
||||||
|
$mode = $this->getMode();
|
||||||
|
|
||||||
|
if (isset($mode[0]) && '/' === $mode[0]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$currErrorHandler = set_error_handler('var_dump');
|
||||||
|
restore_error_handler();
|
||||||
|
|
||||||
|
if ($currErrorHandler !== [$this, 'handleError']) {
|
||||||
|
echo "\n", self::colorize('THE ERROR HANDLER HAS CHANGED!', true, $mode), "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
$groups = ['unsilenced', 'remaining'];
|
||||||
|
|
||||||
|
if (self::MODE_WEAK_VENDORS === $mode) {
|
||||||
|
$groups[] = 'remaining vendor';
|
||||||
|
}
|
||||||
|
|
||||||
|
array_push($groups, 'legacy', 'other');
|
||||||
|
|
||||||
|
$this->displayDeprecations($groups, $mode);
|
||||||
|
|
||||||
|
// store failing status
|
||||||
|
$isFailing = self::MODE_WEAK !== $mode && $mode < $this->deprecations['unsilencedCount'] + $this->deprecations['remainingCount'] + $this->deprecations['otherCount'];
|
||||||
|
|
||||||
|
// reset deprecations array
|
||||||
|
foreach ($this->deprecations as $group => $arrayOrInt) {
|
||||||
|
$this->deprecations[$group] = \is_int($arrayOrInt) ? 0 : [];
|
||||||
|
}
|
||||||
|
|
||||||
|
register_shutdown_function(function () use ($isFailing, $groups, $mode) {
|
||||||
|
foreach ($this->deprecations as $group => $arrayOrInt) {
|
||||||
|
if (0 < (\is_int($arrayOrInt) ? $arrayOrInt : \count($arrayOrInt))) {
|
||||||
|
echo "Shutdown-time deprecations:\n";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->displayDeprecations($groups, $mode);
|
||||||
|
|
||||||
|
if ($isFailing || self::MODE_WEAK !== $mode && $mode < $this->deprecations['unsilencedCount'] + $this->deprecations['remainingCount'] + $this->deprecations['otherCount']) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getMode()
|
||||||
|
{
|
||||||
|
if (false !== $this->resolvedMode) {
|
||||||
|
return $this->resolvedMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (false === $mode = $this->mode) {
|
||||||
|
$mode = getenv('SYMFONY_DEPRECATIONS_HELPER');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self::MODE_DISABLED !== $mode
|
||||||
|
&& self::MODE_WEAK !== $mode
|
||||||
|
&& self::MODE_WEAK_VENDORS !== $mode
|
||||||
|
&& (!isset($mode[0]) || '/' !== $mode[0])
|
||||||
|
) {
|
||||||
|
$mode = preg_match('/^[1-9][0-9]*$/', $mode) ? (int) $mode : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->resolvedMode = $mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $path
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private static function inVendors($path)
|
||||||
|
{
|
||||||
|
/** @var string[] absolute paths to vendor directories */
|
||||||
|
static $vendors;
|
||||||
|
|
||||||
|
if (null === $vendors) {
|
||||||
|
foreach (get_declared_classes() as $class) {
|
||||||
|
if ('C' !== $class[0] || 0 !== strpos($class, 'ComposerAutoloaderInit')) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$r = new \ReflectionClass($class);
|
||||||
|
$v = \dirname(\dirname($r->getFileName()));
|
||||||
|
|
||||||
|
if (file_exists($v.'/composer/installed.json')) {
|
||||||
|
$vendors[] = $v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$realPath = realpath($path);
|
||||||
|
|
||||||
|
if (false === $realPath && '-' !== $path && 'Standard input code' !== $path) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($vendors as $vendor) {
|
||||||
|
if (0 === strpos($realPath, $vendor) && false !== strpbrk(substr($realPath, \strlen($vendor), 1), '/'.\DIRECTORY_SEPARATOR)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $str
|
||||||
|
* @param bool $red
|
||||||
|
* @param mixed $mode
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private static function colorize($str, $red, $mode)
|
||||||
|
{
|
||||||
|
if (!self::hasColorSupport() || self::MODE_WEAK === $mode) {
|
||||||
|
return $str;
|
||||||
|
}
|
||||||
|
|
||||||
|
$color = $red ? '41;37' : '43;30';
|
||||||
|
|
||||||
|
return "\x1B[{$color}m{$str}\x1B[0m";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string[] $groups
|
||||||
|
* @param mixed $mode
|
||||||
|
*/
|
||||||
|
private function displayDeprecations($groups, $mode)
|
||||||
|
{
|
||||||
|
$cmp = function ($a, $b) {
|
||||||
|
return $b['count'] - $a['count'];
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach ($groups as $group) {
|
||||||
|
if (!$this->deprecations[$group.'Count']) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "\n", self::colorize(
|
||||||
|
sprintf('%s deprecation notices (%d)', ucfirst($group), $this->deprecations[$group.'Count']),
|
||||||
|
'legacy' !== $group && 'remaining vendor' !== $group,
|
||||||
|
$mode
|
||||||
|
), "\n";
|
||||||
|
|
||||||
|
uasort($this->deprecations[$group], $cmp);
|
||||||
|
|
||||||
|
foreach ($this->deprecations[$group] as $msg => $notices) {
|
||||||
|
echo "\n ", $notices['count'], 'x: ', $msg, "\n";
|
||||||
|
|
||||||
|
arsort($notices);
|
||||||
|
|
||||||
|
foreach ($notices as $method => $count) {
|
||||||
|
if ('count' !== $method) {
|
||||||
|
echo ' ', $count, 'x in ', preg_replace('/(.*)\\\\(.*?::.*?)$/', '$2 from $1', $method), "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($notices)) {
|
||||||
|
echo "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if STDOUT is defined and supports colorization.
|
* Returns true if STDOUT is defined and supports colorization.
|
||||||
*
|
*
|
||||||
@ -173,212 +394,8 @@ class DeprecationErrorHandler
|
|||||||
}
|
}
|
||||||
|
|
||||||
$stat = fstat(STDOUT);
|
$stat = fstat(STDOUT);
|
||||||
|
|
||||||
// Check if formatted mode is S_IFCHR
|
// Check if formatted mode is S_IFCHR
|
||||||
return $stat ? 0020000 === ($stat['mode'] & 0170000) : false;
|
return $stat ? 0020000 === ($stat['mode'] & 0170000) : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param mixed $mode
|
|
||||||
*/
|
|
||||||
private static function computeMode($mode)
|
|
||||||
{
|
|
||||||
if (false !== self::$mode) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (false === $mode) {
|
|
||||||
$mode = getenv('SYMFONY_DEPRECATIONS_HELPER');
|
|
||||||
}
|
|
||||||
if (self::MODE_DISABLED !== $mode
|
|
||||||
&& self::MODE_WEAK !== $mode
|
|
||||||
&& self::MODE_WEAK_VENDORS !== $mode
|
|
||||||
&& (!isset($mode[0]) || '/' !== $mode[0])
|
|
||||||
) {
|
|
||||||
$mode = preg_match('/^[1-9][0-9]*$/', $mode) ? (int) $mode : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
self::$mode = $mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $path
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
private static function inVendors($path)
|
|
||||||
{
|
|
||||||
/** @var string[] absolute paths to vendor directories */
|
|
||||||
static $vendors;
|
|
||||||
if (null === $vendors) {
|
|
||||||
foreach (get_declared_classes() as $class) {
|
|
||||||
if ('C' === $class[0] && 0 === strpos($class, 'ComposerAutoloaderInit')) {
|
|
||||||
$r = new \ReflectionClass($class);
|
|
||||||
$v = \dirname(\dirname($r->getFileName()));
|
|
||||||
if (file_exists($v.'/composer/installed.json')) {
|
|
||||||
$vendors[] = $v;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$realPath = realpath($path);
|
|
||||||
if (false === $realPath && '-' !== $path && 'Standard input code' !== $path) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
foreach ($vendors as $vendor) {
|
|
||||||
if (0 === strpos($realPath, $vendor) && false !== strpbrk(substr($realPath, \strlen($vendor), 1), '/'.\DIRECTORY_SEPARATOR)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @internal
|
|
||||||
*/
|
|
||||||
public static function handleError($type, $msg, $file, $line, $context = [])
|
|
||||||
{
|
|
||||||
self::computeMode(self::$rawMode);
|
|
||||||
$mode = self::$mode;
|
|
||||||
if ((E_USER_DEPRECATED !== $type && E_DEPRECATED !== $type) || self::MODE_DISABLED === $mode) {
|
|
||||||
$ErrorHandler = self::utilPrefix().'ErrorHandler';
|
|
||||||
|
|
||||||
return $ErrorHandler::handleError($type, $msg, $file, $line, $context);
|
|
||||||
}
|
|
||||||
|
|
||||||
$trace = debug_backtrace();
|
|
||||||
$group = 'other';
|
|
||||||
$isVendor = self::MODE_WEAK_VENDORS === $mode && self::inVendors($file);
|
|
||||||
|
|
||||||
$i = \count($trace);
|
|
||||||
while (1 < $i && (!isset($trace[--$i]['class']) || ('ReflectionMethod' === $trace[$i]['class'] || 0 === strpos($trace[$i]['class'], 'PHPUnit_') || 0 === strpos($trace[$i]['class'], 'PHPUnit\\')))) {
|
|
||||||
// No-op
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($trace[$i]['object']) || isset($trace[$i]['class'])) {
|
|
||||||
if (isset($trace[$i]['class']) && 0 === strpos($trace[$i]['class'], 'Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerFor')) {
|
|
||||||
$parsedMsg = unserialize($msg);
|
|
||||||
$msg = $parsedMsg['deprecation'];
|
|
||||||
$class = $parsedMsg['class'];
|
|
||||||
$method = $parsedMsg['method'];
|
|
||||||
// If the deprecation has been triggered via
|
|
||||||
// \Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerTrait::endTest()
|
|
||||||
// then we need to use the serialized information to determine
|
|
||||||
// if the error has been triggered from vendor code.
|
|
||||||
$isVendor = self::MODE_WEAK_VENDORS === $mode && isset($parsedMsg['triggering_file']) && self::inVendors($parsedMsg['triggering_file']);
|
|
||||||
} else {
|
|
||||||
$class = isset($trace[$i]['object']) ? \get_class($trace[$i]['object']) : $trace[$i]['class'];
|
|
||||||
$method = $trace[$i]['function'];
|
|
||||||
}
|
|
||||||
|
|
||||||
$Test = self::utilPrefix().'Test';
|
|
||||||
|
|
||||||
if (0 !== error_reporting()) {
|
|
||||||
$group = 'unsilenced';
|
|
||||||
} elseif (0 === strpos($method, 'testLegacy')
|
|
||||||
|| 0 === strpos($method, 'provideLegacy')
|
|
||||||
|| 0 === strpos($method, 'getLegacy')
|
|
||||||
|| strpos($class, '\Legacy')
|
|
||||||
|| \in_array('legacy', $Test::getGroups($class, $method), true)
|
|
||||||
) {
|
|
||||||
$group = 'legacy';
|
|
||||||
} elseif ($isVendor) {
|
|
||||||
$group = 'remaining vendor';
|
|
||||||
} else {
|
|
||||||
$group = 'remaining';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($mode[0]) && '/' === $mode[0] && preg_match($mode, $msg)) {
|
|
||||||
$e = new \Exception($msg);
|
|
||||||
$r = new \ReflectionProperty($e, 'trace');
|
|
||||||
$r->setAccessible(true);
|
|
||||||
$r->setValue($e, \array_slice($trace, 1, $i));
|
|
||||||
|
|
||||||
echo "\n".ucfirst($group).' deprecation triggered by '.$class.'::'.$method.':';
|
|
||||||
echo "\n".$msg;
|
|
||||||
echo "\nStack trace:";
|
|
||||||
echo "\n".str_replace(' '.getcwd().\DIRECTORY_SEPARATOR, ' ', $e->getTraceAsString());
|
|
||||||
echo "\n";
|
|
||||||
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
if ('legacy' !== $group && self::MODE_WEAK !== $mode) {
|
|
||||||
$ref = &self::$deprecations[$group][$msg]['count'];
|
|
||||||
++$ref;
|
|
||||||
$ref = &self::$deprecations[$group][$msg][$class.'::'.$method];
|
|
||||||
++$ref;
|
|
||||||
}
|
|
||||||
} elseif (self::MODE_WEAK !== $mode) {
|
|
||||||
$ref = &self::$deprecations[$group][$msg]['count'];
|
|
||||||
++$ref;
|
|
||||||
}
|
|
||||||
++self::$deprecations[$group.'Count'];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $str
|
|
||||||
* @param bool $red
|
|
||||||
* @param mixed $mode
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
private static function colorize($str, $red, $mode)
|
|
||||||
{
|
|
||||||
if (!self::hasColorSupport() || self::MODE_WEAK === $mode) {
|
|
||||||
return $str;
|
|
||||||
}
|
|
||||||
|
|
||||||
$color = $red ? '41;37' : '43;30';
|
|
||||||
|
|
||||||
return "\x1B[{$color}m{$str}\x1B[0m";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string[] $groups
|
|
||||||
* @param mixed $mode
|
|
||||||
*/
|
|
||||||
private static function displayDeprecations($groups, $mode)
|
|
||||||
{
|
|
||||||
$cmp = function ($a, $b) {
|
|
||||||
return $b['count'] - $a['count'];
|
|
||||||
};
|
|
||||||
|
|
||||||
foreach ($groups as $group) {
|
|
||||||
if (self::$deprecations[$group.'Count']) {
|
|
||||||
echo "\n", self::colorize(
|
|
||||||
sprintf('%s deprecation notices (%d)', ucfirst($group), self::$deprecations[$group.'Count']),
|
|
||||||
'legacy' !== $group && 'remaining vendor' !== $group,
|
|
||||||
$mode
|
|
||||||
), "\n";
|
|
||||||
|
|
||||||
uasort(self::$deprecations[$group], $cmp);
|
|
||||||
|
|
||||||
foreach (self::$deprecations[$group] as $msg => $notices) {
|
|
||||||
echo "\n ", $notices['count'], 'x: ', $msg, "\n";
|
|
||||||
|
|
||||||
arsort($notices);
|
|
||||||
|
|
||||||
foreach ($notices as $method => $count) {
|
|
||||||
if ('count' !== $method) {
|
|
||||||
echo ' ', $count, 'x in ', preg_replace('/(.*)\\\\(.*?::.*?)$/', '$2 from $1', $method), "\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!empty($notices)) {
|
|
||||||
echo "\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
private static function utilPrefix()
|
|
||||||
{
|
|
||||||
if ('' !== self::$utilPrefix) {
|
|
||||||
return self::$utilPrefix;
|
|
||||||
}
|
|
||||||
|
|
||||||
return self::$utilPrefix = class_exists('PHPUnit_Util_ErrorHandler') ? 'PHPUnit_Util_' : 'PHPUnit\Util\\';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user