minor #29724 [PHPUnitBridge] Static access in closure (greg0ire, nicolas-grekas)
This PR was merged into the 4.3-dev branch. Discussion ---------- [PHPUnitBridge] Static access in closure | Q | A | ------------- | --- | Branch? | master for features | Bug fix? | no | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | n / a | License | MIT | Doc PR | n / a #29718 bumps php to 5.5 . This is what we could simplify if it gets merged, thanks to this "new" PHP feature: https://3v4l.org/sJOWr EDIT: it was merged, this can be reviewed. Commits -------97f3023963
Use the scope of an instance9df76ebbe5
Extract closures into static functions
This commit is contained in:
commit
98bc3e7917
@ -22,7 +22,23 @@ class DeprecationErrorHandler
|
||||
const MODE_WEAK_VENDORS = 'weak_vendors';
|
||||
const MODE_DISABLED = 'disabled';
|
||||
|
||||
private $mode = false;
|
||||
private $resolvedMode = false;
|
||||
private $deprecations = [
|
||||
'unsilencedCount' => 0,
|
||||
'remainingCount' => 0,
|
||||
'legacyCount' => 0,
|
||||
'otherCount' => 0,
|
||||
'remaining vendorCount' => 0,
|
||||
'unsilenced' => [],
|
||||
'remaining' => [],
|
||||
'legacy' => [],
|
||||
'other' => [],
|
||||
'remaining vendor' => [],
|
||||
];
|
||||
|
||||
private static $isRegistered = false;
|
||||
private static $utilPrefix;
|
||||
|
||||
/**
|
||||
* Registers and configures the deprecation handler.
|
||||
@ -43,78 +59,66 @@ class DeprecationErrorHandler
|
||||
return;
|
||||
}
|
||||
|
||||
$UtilPrefix = class_exists('PHPUnit_Util_ErrorHandler') ? 'PHPUnit_Util_' : 'PHPUnit\Util\\';
|
||||
self::$utilPrefix = class_exists('PHPUnit_Util_ErrorHandler') ? 'PHPUnit_Util_' : 'PHPUnit\Util\\';
|
||||
|
||||
$getMode = function () use ($mode) {
|
||||
static $memoizedMode = false;
|
||||
$handler = new self();
|
||||
$oldErrorHandler = set_error_handler([$handler, 'handleError']);
|
||||
|
||||
if (false !== $memoizedMode) {
|
||||
return $memoizedMode;
|
||||
}
|
||||
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;
|
||||
}
|
||||
if (null !== $oldErrorHandler) {
|
||||
restore_error_handler();
|
||||
|
||||
return $memoizedMode = $mode;
|
||||
};
|
||||
|
||||
$inVendors = function ($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;
|
||||
if ([self::$utilPrefix.'ErrorHandler', 'handleError'] === $oldErrorHandler) {
|
||||
restore_error_handler();
|
||||
self::register($mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$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;
|
||||
} else {
|
||||
$handler->mode = $mode;
|
||||
self::$isRegistered = true;
|
||||
register_shutdown_function([$handler, 'shutdown']);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
public static function collectDeprecations($outputFile)
|
||||
{
|
||||
$deprecations = [];
|
||||
$previousErrorHandler = set_error_handler(function ($type, $msg, $file, $line, $context = []) use (&$deprecations, &$previousErrorHandler) {
|
||||
if (E_USER_DEPRECATED !== $type && E_DEPRECATED !== $type) {
|
||||
if ($previousErrorHandler) {
|
||||
return $previousErrorHandler($type, $msg, $file, $line, $context);
|
||||
}
|
||||
|
||||
static $autoload = true;
|
||||
|
||||
$ErrorHandler = class_exists('PHPUnit_Util_ErrorHandler', $autoload) ? 'PHPUnit_Util_ErrorHandler' : 'PHPUnit\Util\ErrorHandler';
|
||||
$autoload = false;
|
||||
|
||||
return $ErrorHandler::handleError($type, $msg, $file, $line, $context);
|
||||
}
|
||||
|
||||
$deprecations[] = [error_reporting(), $msg, $file];
|
||||
});
|
||||
|
||||
register_shutdown_function(function () use ($outputFile, &$deprecations) {
|
||||
file_put_contents($outputFile, serialize($deprecations));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function handleError($type, $msg, $file, $line, $context = [])
|
||||
{
|
||||
$mode = $this->getMode();
|
||||
|
||||
$deprecations = [
|
||||
'unsilencedCount' => 0,
|
||||
'remainingCount' => 0,
|
||||
'legacyCount' => 0,
|
||||
'otherCount' => 0,
|
||||
'remaining vendorCount' => 0,
|
||||
'unsilenced' => [],
|
||||
'remaining' => [],
|
||||
'legacy' => [],
|
||||
'other' => [],
|
||||
'remaining vendor' => [],
|
||||
];
|
||||
$deprecationHandler = function ($type, $msg, $file, $line, $context = []) use (&$deprecations, $getMode, $UtilPrefix, $inVendors) {
|
||||
$mode = $getMode();
|
||||
if ((E_USER_DEPRECATED !== $type && E_DEPRECATED !== $type) || self::MODE_DISABLED === $mode) {
|
||||
$ErrorHandler = $UtilPrefix.'ErrorHandler';
|
||||
$ErrorHandler = self::$utilPrefix.'ErrorHandler';
|
||||
|
||||
return $ErrorHandler::handleError($type, $msg, $file, $line, $context);
|
||||
}
|
||||
|
||||
$trace = debug_backtrace();
|
||||
$group = 'other';
|
||||
$isVendor = self::MODE_WEAK_VENDORS === $mode && $inVendors($file);
|
||||
$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\\')))) {
|
||||
@ -131,13 +135,13 @@ class DeprecationErrorHandler
|
||||
// \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']) && $inVendors($parsedMsg['triggering_file']);
|
||||
$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 = $UtilPrefix.'Test';
|
||||
$Test = self::$utilPrefix.'Test';
|
||||
|
||||
if (0 !== error_reporting()) {
|
||||
$group = 'unsilenced';
|
||||
@ -168,73 +172,176 @@ class DeprecationErrorHandler
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ('legacy' !== $group && self::MODE_WEAK !== $mode) {
|
||||
$ref = &$deprecations[$group][$msg]['count'];
|
||||
$ref = &$this->deprecations[$group][$msg]['count'];
|
||||
++$ref;
|
||||
$ref = &$deprecations[$group][$msg][$class.'::'.$method];
|
||||
$ref = &$this->deprecations[$group][$msg][$class.'::'.$method];
|
||||
++$ref;
|
||||
}
|
||||
} elseif (self::MODE_WEAK !== $mode) {
|
||||
$ref = &$deprecations[$group][$msg]['count'];
|
||||
$ref = &$this->deprecations[$group][$msg]['count'];
|
||||
++$ref;
|
||||
}
|
||||
++$deprecations[$group.'Count'];
|
||||
};
|
||||
$oldErrorHandler = set_error_handler($deprecationHandler);
|
||||
|
||||
if (null !== $oldErrorHandler) {
|
||||
restore_error_handler();
|
||||
if ([$UtilPrefix.'ErrorHandler', 'handleError'] === $oldErrorHandler) {
|
||||
restore_error_handler();
|
||||
self::register($mode);
|
||||
++$this->deprecations[$group.'Count'];
|
||||
}
|
||||
} else {
|
||||
self::$isRegistered = true;
|
||||
if (self::hasColorSupport()) {
|
||||
$colorize = function ($str, $red) {
|
||||
$color = $red ? '41;37' : '43;30';
|
||||
|
||||
return "\x1B[{$color}m{$str}\x1B[0m";
|
||||
};
|
||||
} else {
|
||||
$colorize = function ($str) { return $str; };
|
||||
}
|
||||
register_shutdown_function(function () use ($getMode, &$deprecations, $deprecationHandler, $colorize) {
|
||||
$mode = $getMode();
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function shutdown()
|
||||
{
|
||||
$mode = $this->getMode();
|
||||
|
||||
if (isset($mode[0]) && '/' === $mode[0]) {
|
||||
return;
|
||||
}
|
||||
|
||||
$currErrorHandler = set_error_handler('var_dump');
|
||||
restore_error_handler();
|
||||
|
||||
if (self::MODE_WEAK === $mode) {
|
||||
$colorize = function ($str) { return $str; };
|
||||
}
|
||||
if ($currErrorHandler !== $deprecationHandler) {
|
||||
echo "\n", $colorize('THE ERROR HANDLER HAS CHANGED!', true), "\n";
|
||||
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'];
|
||||
};
|
||||
|
||||
$groups = ['unsilenced', 'remaining'];
|
||||
if (self::MODE_WEAK_VENDORS === $mode) {
|
||||
$groups[] = 'remaining vendor';
|
||||
}
|
||||
array_push($groups, 'legacy', 'other');
|
||||
|
||||
$displayDeprecations = function ($deprecations) use ($colorize, $cmp, $groups) {
|
||||
foreach ($groups as $group) {
|
||||
if ($deprecations[$group.'Count']) {
|
||||
echo "\n", $colorize(
|
||||
sprintf('%s deprecation notices (%d)', ucfirst($group), $deprecations[$group.'Count']),
|
||||
'legacy' !== $group && 'remaining vendor' !== $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($deprecations[$group], $cmp);
|
||||
uasort($this->deprecations[$group], $cmp);
|
||||
|
||||
foreach ($deprecations[$group] as $msg => $notices) {
|
||||
foreach ($this->deprecations[$group] as $msg => $notices) {
|
||||
echo "\n ", $notices['count'], 'x: ', $msg, "\n";
|
||||
|
||||
arsort($notices);
|
||||
@ -246,59 +353,10 @@ class DeprecationErrorHandler
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($notices)) {
|
||||
echo "\n";
|
||||
}
|
||||
};
|
||||
|
||||
$displayDeprecations($deprecations);
|
||||
|
||||
// store failing status
|
||||
$isFailing = self::MODE_WEAK !== $mode && $mode < $deprecations['unsilencedCount'] + $deprecations['remainingCount'] + $deprecations['otherCount'];
|
||||
|
||||
// reset deprecations array
|
||||
foreach ($deprecations as $group => $arrayOrInt) {
|
||||
$deprecations[$group] = \is_int($arrayOrInt) ? 0 : [];
|
||||
}
|
||||
|
||||
register_shutdown_function(function () use (&$deprecations, $isFailing, $displayDeprecations, $mode) {
|
||||
foreach ($deprecations as $group => $arrayOrInt) {
|
||||
if (0 < (\is_int($arrayOrInt) ? $arrayOrInt : \count($arrayOrInt))) {
|
||||
echo "Shutdown-time deprecations:\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
$displayDeprecations($deprecations);
|
||||
if ($isFailing || self::MODE_WEAK !== $mode && $mode < $deprecations['unsilencedCount'] + $deprecations['remainingCount'] + $deprecations['otherCount']) {
|
||||
exit(1);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public static function collectDeprecations($outputFile)
|
||||
{
|
||||
$deprecations = [];
|
||||
$previousErrorHandler = set_error_handler(function ($type, $msg, $file, $line, $context = []) use (&$deprecations, &$previousErrorHandler) {
|
||||
if (E_USER_DEPRECATED !== $type && E_DEPRECATED !== $type) {
|
||||
if ($previousErrorHandler) {
|
||||
return $previousErrorHandler($type, $msg, $file, $line, $context);
|
||||
}
|
||||
static $autoload = true;
|
||||
|
||||
$ErrorHandler = class_exists('PHPUnit_Util_ErrorHandler', $autoload) ? 'PHPUnit_Util_ErrorHandler' : 'PHPUnit\Util\ErrorHandler';
|
||||
$autoload = false;
|
||||
|
||||
return $ErrorHandler::handleError($type, $msg, $file, $line, $context);
|
||||
}
|
||||
$deprecations[] = [error_reporting(), $msg, $file];
|
||||
});
|
||||
|
||||
register_shutdown_function(function () use ($outputFile, &$deprecations) {
|
||||
file_put_contents($outputFile, serialize($deprecations));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -336,6 +394,7 @@ class DeprecationErrorHandler
|
||||
}
|
||||
|
||||
$stat = fstat(STDOUT);
|
||||
|
||||
// Check if formatted mode is S_IFCHR
|
||||
return $stat ? 0020000 === ($stat['mode'] & 0170000) : false;
|
||||
}
|
||||
|
Reference in New Issue
Block a user