Skip to content

Commit

Permalink
[PhpUnitBridge] Fix qualification of deprecations triggered by the de…
Browse files Browse the repository at this point in the history
…bug class loader
  • Loading branch information
fancyweb committed Nov 26, 2020
1 parent 3a5e4cf commit cf620b6
Show file tree
Hide file tree
Showing 9 changed files with 115 additions and 3 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
vendor/
composer.lock
phpunit.xml
Tests/DeprecationErrorHandler/fake_vendor/symfony/error-handler/DebugClassLoader.php
14 changes: 14 additions & 0 deletions DeprecationErrorHandler/Deprecation.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

use PHPUnit\Util\Test;
use Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerFor;
use Symfony\Component\Debug\DebugClassLoader as LegacyDebugClassLoader;
use Symfony\Component\ErrorHandler\DebugClassLoader;

/**
* @internal
Expand Down Expand Up @@ -53,6 +55,18 @@ class Deprecation
public function __construct($message, array $trace, $file)
{
$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;
$i = \count($trace);
while (1 < $i && $this->lineShouldBeSkipped($trace[--$i])) {
Expand Down
51 changes: 51 additions & 0 deletions Tests/DeprecationErrorHandler/debug_class_loader_autoload.phpt
Original file line number Diff line number Diff line change
@@ -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
13 changes: 13 additions & 0 deletions Tests/DeprecationErrorHandler/fake_app/BarService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace App\Services;

use acme\lib\ExtendsDeprecatedClassFromOtherVendor;

final class BarService
{
public function __construct()
{
ExtendsDeprecatedClassFromOtherVendor::FOO;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace acme\lib;

use fcy\lib\DeprecatedClass;

final class ExtendsDeprecatedClassFromOtherVendor extends DeprecatedClass
{
public const FOO = 'bar';
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,33 @@ public function getPrefixesPsr4()
return [
'App\\Services\\' => [__DIR__.'/../../fake_app/'],
'acme\\lib\\' => [__DIR__.'/../acme/lib/'],
'fcy\\lib\\' => [__DIR__.'/../fcy/lib/'],
];
}

public function loadClass($className)
{
if ($file = $this->findFile($className)) {
require $file;
}
}

public function findFile($class)
{
foreach ($this->getPrefixesPsr4() as $prefix => $baseDirs) {
if (strpos($className, $prefix) !== 0) {
if (strpos($class, $prefix) !== 0) {
continue;
}

foreach ($baseDirs as $baseDir) {
$file = str_replace([$prefix, '\\'], [$baseDir, '/'], $className.'.php');
$file = str_replace([$prefix, '\\'], [$baseDir, '/'], $class.'.php');
if (file_exists($file)) {
require $file;
return $file;
}
}
}

return false;
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace fcy\lib;

/**
* @deprecated
*/
class DeprecatedClass
{
}
Empty file.
3 changes: 3 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
"php": "THIS BRIDGE WHEN TESTING LOWEST SYMFONY VERSIONS.",
"php": ">=5.5.9"
},
"require-dev": {
"symfony/error-handler": "^4.4|^5.0"
},
"suggest": {
"symfony/error-handler": "For tracking deprecated interfaces usages at runtime with DebugClassLoader"
},
Expand Down

1 comment on commit cf620b6

@maximium
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello. I guess you shouldn't use null coalescing operator in deprecation error handler due the php version restriction "php": ">=5.5.9"

Please sign in to comment.