bug #38597 [PhpUnitBridge] Fix qualification of deprecations triggered by the debug class loader (fancyweb)
This PR was merged into the 4.4 branch.
Discussion
----------
[PhpUnitBridge] Fix qualification of deprecations triggered by the debug class loader
| Q | A
| ------------- | ---
| Branch? | 4.4
| Bug fix? | yes
| New feature? | no
| Deprecations? | no
| Tickets | https://github.com/symfony/symfony/issues/36036
| License | MIT
| Doc PR | -
I tested it successfully against the two examples stof gave in the issue. However, I don't see how to write a working real test for this.
The solution I found is to add the missing checked file in the original files stack so when the type of the deprecation is computed instead of having "self" -> "self", we have "vendor" -> "self".
Commits
-------
dff539434e
[PhpUnitBridge] Fix qualification of deprecations triggered by the debug class loader
This commit is contained in:
commit
6224ffa5a3
1
src/Symfony/Bridge/PhpUnit/.gitignore
vendored
1
src/Symfony/Bridge/PhpUnit/.gitignore
vendored
@ -1,3 +1,4 @@
|
|||||||
vendor/
|
vendor/
|
||||||
composer.lock
|
composer.lock
|
||||||
phpunit.xml
|
phpunit.xml
|
||||||
|
Tests/DeprecationErrorHandler/fake_vendor/symfony/error-handler/DebugClassLoader.php
|
||||||
|
@ -13,6 +13,8 @@ namespace Symfony\Bridge\PhpUnit\DeprecationErrorHandler;
|
|||||||
|
|
||||||
use PHPUnit\Util\Test;
|
use PHPUnit\Util\Test;
|
||||||
use Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerFor;
|
use Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerFor;
|
||||||
|
use Symfony\Component\Debug\DebugClassLoader as LegacyDebugClassLoader;
|
||||||
|
use Symfony\Component\ErrorHandler\DebugClassLoader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
@ -53,6 +55,18 @@ class Deprecation
|
|||||||
public function __construct($message, array $trace, $file)
|
public function __construct($message, array $trace, $file)
|
||||||
{
|
{
|
||||||
$this->trace = $trace;
|
$this->trace = $trace;
|
||||||
|
|
||||||
|
if ('trigger_error' === ($trace[1]['function'] ?? null)
|
||||||
|
&& (DebugClassLoader::class === ($class = $trace[2]['class'] ?? null) || LegacyDebugClassLoader::class === $class)
|
||||||
|
&& 'checkClass' === ($trace[2]['function'] ?? null)
|
||||||
|
&& null !== ($extraFile = $trace[2]['args'][1] ?? null)
|
||||||
|
&& '' !== $extraFile
|
||||||
|
&& false !== $extraFile = realpath($extraFile)
|
||||||
|
) {
|
||||||
|
$this->getOriginalFilesStack();
|
||||||
|
array_splice($this->originalFilesStack, 2, 1, $extraFile);
|
||||||
|
}
|
||||||
|
|
||||||
$this->message = $message;
|
$this->message = $message;
|
||||||
$i = \count($trace);
|
$i = \count($trace);
|
||||||
while (1 < $i && $this->lineShouldBeSkipped($trace[--$i])) {
|
while (1 < $i && $this->lineShouldBeSkipped($trace[--$i])) {
|
||||||
|
@ -0,0 +1,51 @@
|
|||||||
|
--TEST--
|
||||||
|
Test that a deprecation from the DebugClassLoader on a vendor class autoload triggered by an app class is considered indirect.
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$k = 'SYMFONY_DEPRECATIONS_HELPER';
|
||||||
|
putenv($k.'='.$_SERVER[$k] = $_ENV[$k] = 'max[total]=0');
|
||||||
|
putenv('ANSICON');
|
||||||
|
putenv('ConEmuANSI');
|
||||||
|
putenv('TERM');
|
||||||
|
|
||||||
|
$vendor = __DIR__;
|
||||||
|
while (!file_exists($vendor.'/vendor')) {
|
||||||
|
$vendor = dirname($vendor);
|
||||||
|
}
|
||||||
|
define('PHPUNIT_COMPOSER_INSTALL', $vendor.'/vendor/autoload.php');
|
||||||
|
require PHPUNIT_COMPOSER_INSTALL;
|
||||||
|
require_once __DIR__.'/../../bootstrap.php';
|
||||||
|
eval(<<<'EOPHP'
|
||||||
|
namespace PHPUnit\Util;
|
||||||
|
|
||||||
|
class Test
|
||||||
|
{
|
||||||
|
public static function getGroups()
|
||||||
|
{
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOPHP
|
||||||
|
);
|
||||||
|
require __DIR__.'/fake_vendor/autoload.php';
|
||||||
|
|
||||||
|
// We need the real DebugClassLoader FQCN but in a vendor path.
|
||||||
|
if (!file_exists($errorHandlerRootDir = __DIR__.'/../../../../Component/ErrorHandler')) {
|
||||||
|
if (!file_exists($errorHandlerRootDir = __DIR__.'/../../vendor/symfony/error-handler')) {
|
||||||
|
die('Could not find the ErrorHandler component root directory.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
file_put_contents($fakeDebugClassLoadPath = __DIR__.'/fake_vendor/symfony/error-handler/DebugClassLoader.php', file_get_contents($errorHandlerRootDir.'/DebugClassLoader.php'));
|
||||||
|
require $fakeDebugClassLoadPath;
|
||||||
|
|
||||||
|
\Symfony\Component\ErrorHandler\DebugClassLoader::enable();
|
||||||
|
new \App\Services\BarService();
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Remaining indirect deprecation notices (1)
|
||||||
|
|
||||||
|
1x: The "acme\lib\ExtendsDeprecatedClassFromOtherVendor" class extends "fcy\lib\DeprecatedClass" that is deprecated.
|
||||||
|
1x in BarService::__construct from App\Services
|
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Services;
|
||||||
|
|
||||||
|
use acme\lib\ExtendsDeprecatedClassFromOtherVendor;
|
||||||
|
|
||||||
|
final class BarService
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
ExtendsDeprecatedClassFromOtherVendor::FOO;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace acme\lib;
|
||||||
|
|
||||||
|
use fcy\lib\DeprecatedClass;
|
||||||
|
|
||||||
|
final class ExtendsDeprecatedClassFromOtherVendor extends DeprecatedClass
|
||||||
|
{
|
||||||
|
public const FOO = 'bar';
|
||||||
|
}
|
@ -12,23 +12,33 @@ class ComposerLoaderFake
|
|||||||
return [
|
return [
|
||||||
'App\\Services\\' => [__DIR__.'/../../fake_app/'],
|
'App\\Services\\' => [__DIR__.'/../../fake_app/'],
|
||||||
'acme\\lib\\' => [__DIR__.'/../acme/lib/'],
|
'acme\\lib\\' => [__DIR__.'/../acme/lib/'],
|
||||||
|
'fcy\\lib\\' => [__DIR__.'/../fcy/lib/'],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function loadClass($className)
|
public function loadClass($className)
|
||||||
|
{
|
||||||
|
if ($file = $this->findFile($className)) {
|
||||||
|
require $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function findFile($class)
|
||||||
{
|
{
|
||||||
foreach ($this->getPrefixesPsr4() as $prefix => $baseDirs) {
|
foreach ($this->getPrefixesPsr4() as $prefix => $baseDirs) {
|
||||||
if (strpos($className, $prefix) !== 0) {
|
if (strpos($class, $prefix) !== 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($baseDirs as $baseDir) {
|
foreach ($baseDirs as $baseDir) {
|
||||||
$file = str_replace([$prefix, '\\'], [$baseDir, '/'], $className.'.php');
|
$file = str_replace([$prefix, '\\'], [$baseDir, '/'], $class.'.php');
|
||||||
if (file_exists($file)) {
|
if (file_exists($file)) {
|
||||||
require $file;
|
return $file;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace fcy\lib;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
|
class DeprecatedClass
|
||||||
|
{
|
||||||
|
}
|
@ -20,6 +20,9 @@
|
|||||||
"php": "THIS BRIDGE WHEN TESTING LOWEST SYMFONY VERSIONS.",
|
"php": "THIS BRIDGE WHEN TESTING LOWEST SYMFONY VERSIONS.",
|
||||||
"php": ">=5.5.9"
|
"php": ">=5.5.9"
|
||||||
},
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"symfony/error-handler": "^4.4|^5.0"
|
||||||
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
"symfony/error-handler": "For tracking deprecated interfaces usages at runtime with DebugClassLoader"
|
"symfony/error-handler": "For tracking deprecated interfaces usages at runtime with DebugClassLoader"
|
||||||
},
|
},
|
||||||
|
Reference in New Issue
Block a user