diff --git a/Caster/Caster.php b/Caster/Caster.php index cd9b35f7..b6a84fcb 100644 --- a/Caster/Caster.php +++ b/Caster/Caster.php @@ -115,7 +115,7 @@ public static function castObject(object $obj, string $class, bool $hasDebugInfo * @param array $a The array containing the properties to filter * @param int $filter A bit field of Caster::EXCLUDE_* constants specifying which properties to filter out * @param string[] $listedProperties List of properties to exclude when Caster::EXCLUDE_VERBOSE is set, and to preserve when Caster::EXCLUDE_NOT_IMPORTANT is set - * @param int &$count Set to the number of removed properties + * @param int|null &$count Set to the number of removed properties */ public static function filter(array $a, int $filter, array $listedProperties = [], ?int &$count = 0): array { diff --git a/Caster/ReflectionCaster.php b/Caster/ReflectionCaster.php index f6c8c741..00675dfd 100644 --- a/Caster/ReflectionCaster.php +++ b/Caster/ReflectionCaster.php @@ -292,7 +292,7 @@ public static function castParameter(\ReflectionParameter $c, array $a, Stub $st if ($c->isOptional()) { try { $a[$prefix.'default'] = $v = $c->getDefaultValue(); - if ($c->isDefaultValueConstant()) { + if ($c->isDefaultValueConstant() && !\is_object($v)) { $a[$prefix.'default'] = new ConstStub($c->getDefaultValueConstantName(), $v); } if (null === $v) { diff --git a/Caster/SymfonyCaster.php b/Caster/SymfonyCaster.php index f2ee0d62..3b13666c 100644 --- a/Caster/SymfonyCaster.php +++ b/Caster/SymfonyCaster.php @@ -76,12 +76,21 @@ public static function castLazyObjectState($state, array $a, Stub $stub, bool $i $stub->cut += \count($a) - 1; - return ['status' => new ConstStub(match ($a['status']) { + $instance = $a['realInstance'] ?? null; + + $a = ['status' => new ConstStub(match ($a['status']) { LazyObjectState::STATUS_INITIALIZED_FULL => 'INITIALIZED_FULL', LazyObjectState::STATUS_INITIALIZED_PARTIAL => 'INITIALIZED_PARTIAL', LazyObjectState::STATUS_UNINITIALIZED_FULL => 'UNINITIALIZED_FULL', LazyObjectState::STATUS_UNINITIALIZED_PARTIAL => 'UNINITIALIZED_PARTIAL', }, $a['status'])]; + + if ($instance) { + $a['realInstance'] = $instance; + --$stub->cut; + } + + return $a; } public static function castUuid(Uuid $uuid, array $a, Stub $stub, bool $isNested) diff --git a/Dumper/CliDumper.php b/Dumper/CliDumper.php index c52ac4db..660ca321 100644 --- a/Dumper/CliDumper.php +++ b/Dumper/CliDumper.php @@ -184,6 +184,9 @@ public function dumpString(Cursor $cursor, string $str, bool $bin, int $cut) } if ('' === $str) { $this->line .= '""'; + if ($cut) { + $this->line .= '…'.$cut; + } $this->endValue($cursor); } else { $attr += [ @@ -418,7 +421,8 @@ protected function style(string $style, string $value, array $attr = []): string $this->colors ??= $this->supportsColors(); $this->handlesHrefGracefully ??= 'JetBrains-JediTerm' !== getenv('TERMINAL_EMULATOR') - && (!getenv('KONSOLE_VERSION') || (int) getenv('KONSOLE_VERSION') > 201100); + && (!getenv('KONSOLE_VERSION') || (int) getenv('KONSOLE_VERSION') > 201100) + && !isset($_SERVER['IDEA_INITIAL_DIRECTORY']); if (isset($attr['ellipsis'], $attr['ellipsis-type'])) { $prefix = substr($value, 0, -$attr['ellipsis']); diff --git a/LICENSE b/LICENSE index 72412a62..29f72d5e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2014-2023 Fabien Potencier +Copyright (c) 2014-present Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Server/Connection.php b/Server/Connection.php index 97b5b94f..c6840867 100644 --- a/Server/Connection.php +++ b/Server/Connection.php @@ -91,7 +91,7 @@ private function createSocket() { set_error_handler([self::class, 'nullErrorHandler']); try { - return stream_socket_client($this->host, $errno, $errstr, 3, \STREAM_CLIENT_CONNECT | \STREAM_CLIENT_ASYNC_CONNECT); + return stream_socket_client($this->host, $errno, $errstr, 3); } finally { restore_error_handler(); } diff --git a/Tests/Caster/CasterTest.php b/Tests/Caster/CasterTest.php index 66cd5fbe..55eb4040 100644 --- a/Tests/Caster/CasterTest.php +++ b/Tests/Caster/CasterTest.php @@ -46,7 +46,7 @@ public function testFilter($filter, $expectedDiff, $listedProperties = null) $this->assertSame($expectedDiff, array_diff_assoc(self::$referenceArray, $filteredArray)); } - public function provideFilter() + public static function provideFilter() { return [ [ diff --git a/Tests/Caster/DateCasterTest.php b/Tests/Caster/DateCasterTest.php index 8abdab50..fbbd901f 100644 --- a/Tests/Caster/DateCasterTest.php +++ b/Tests/Caster/DateCasterTest.php @@ -90,7 +90,7 @@ public function testCastDateTime($time, $timezone, $xDate, $xTimestamp, $xInfos) $this->assertDumpMatchesFormat($xDump, $cast["\0~\0date"]); } - public function provideDateTimes() + public static function provideDateTimes() { return [ ['2017-04-30 00:00:00.000000', 'Europe/Zurich', '2017-04-30 00:00:00.0 Europe/Zurich (+02:00)', 1493503200, 'Sunday, April 30, 2017%Afrom now%ADST On'], @@ -210,7 +210,7 @@ public function testCastInterval($intervalSpec, $ms, $invert, $xInterval, $xSeco $this->assertDumpMatchesFormat($xDump, $cast["\0~\0interval"]); } - public function provideIntervals() + public static function provideIntervals() { return [ ['PT0S', 0, 0, '0s', '0s'], @@ -309,7 +309,7 @@ public function testCastTimeZone($timezone, $xTimezone, $xRegion) $this->assertDumpMatchesFormat($xDump, $cast["\0~\0timezone"]); } - public function provideTimeZones() + public static function provideTimeZones() { $xRegion = \extension_loaded('intl') ? '%s' : ''; @@ -386,7 +386,7 @@ public function testCastPeriod($start, $interval, $end, $options, $xPeriod, $xDa $this->assertDumpMatchesFormat($xDump, $cast["\0~\0period"]); } - public function providePeriods() + public static function providePeriods() { $periods = [ ['2017-01-01', 'P1D', '2017-01-03', 0, 'every + 1d, from [2017-01-01 00:00:00.0 to 2017-01-03 00:00:00.0[', '1) 2017-01-01%a2) 2017-01-02'], diff --git a/Tests/Caster/DoctrineCasterTest.php b/Tests/Caster/DoctrineCasterTest.php new file mode 100644 index 00000000..85f6293b --- /dev/null +++ b/Tests/Caster/DoctrineCasterTest.php @@ -0,0 +1,45 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Tests\Caster; + +use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\ORM\EntityManagerInterface; +use Doctrine\ORM\Mapping\ClassMetadata; +use Doctrine\ORM\PersistentCollection; +use PHPUnit\Framework\TestCase; +use Symfony\Component\VarDumper\Test\VarDumperTestTrait; + +/** + * @requires function \Doctrine\Common\Collections\ArrayCollection::__construct + */ +class DoctrineCasterTest extends TestCase +{ + use VarDumperTestTrait; + + public function testCastPersistentCollection() + { + $classMetadata = new ClassMetadata(__CLASS__); + + $collection = new PersistentCollection($this->createMock(EntityManagerInterface::class), $classMetadata, new ArrayCollection(['test'])); + + $expected = <<assertDumpMatchesFormat($expected, $collection); + } +} diff --git a/Tests/Caster/ExceptionCasterTest.php b/Tests/Caster/ExceptionCasterTest.php index 7de30f4f..cc3c8c74 100644 --- a/Tests/Caster/ExceptionCasterTest.php +++ b/Tests/Caster/ExceptionCasterTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\VarDumper\Tests\Caster; use PHPUnit\Framework\TestCase; +use Symfony\Component\ErrorHandler\Exception\SilencedErrorContext; use Symfony\Component\VarDumper\Caster\Caster; use Symfony\Component\VarDumper\Caster\ExceptionCaster; use Symfony\Component\VarDumper\Caster\FrameStub; @@ -29,6 +30,21 @@ private function getTestException($msg, &$ref = null) return new \Exception(''.$msg); } + private function getTestError($msg): \Error + { + return new \Error(''.$msg); + } + + private function getTestErrorException($msg): \ErrorException + { + return new \ErrorException(''.$msg); + } + + private function getTestSilencedErrorContext(): SilencedErrorContext + { + return new SilencedErrorContext(\E_ERROR, __FILE__, __LINE__); + } + protected function tearDown(): void { ExceptionCaster::$srcContext = 1; @@ -61,6 +77,79 @@ public function testDefaultSettings() $this->assertSame(['foo'], $ref); } + public function testDefaultSettingsOnError() + { + $e = $this->getTestError('foo'); + + $expectedDump = <<<'EODUMP' +Error { + #message: "foo" + #code: 0 + #file: "%sExceptionCasterTest.php" + #line: %d + trace: { + %s%eTests%eCaster%eExceptionCasterTest.php:%d { + Symfony\Component\VarDumper\Tests\Caster\ExceptionCasterTest->getTestError($msg): Error + › { + › return new \Error(''.$msg); + › } + } + %s%eTests%eCaster%eExceptionCasterTest.php:%d { …} +%A +EODUMP; + + $this->assertDumpMatchesFormat($expectedDump, $e); + } + + public function testDefaultSettingsOnErrorException() + { + $e = $this->getTestErrorException('foo'); + + $expectedDump = <<<'EODUMP' +ErrorException { + #message: "foo" + #code: 0 + #file: "%sExceptionCasterTest.php" + #line: %d + #severity: E_ERROR + trace: { + %s%eTests%eCaster%eExceptionCasterTest.php:%d { + Symfony\Component\VarDumper\Tests\Caster\ExceptionCasterTest->getTestErrorException($msg): ErrorException + › { + › return new \ErrorException(''.$msg); + › } + } + %s%eTests%eCaster%eExceptionCasterTest.php:%d { …} +%A +EODUMP; + + $this->assertDumpMatchesFormat($expectedDump, $e); + } + + /** + * @requires function \Symfony\Component\ErrorHandler\Exception\SilencedErrorContext::__construct + */ + public function testCastSilencedErrorContext() + { + $e = $this->getTestSilencedErrorContext(); + + $expectedDump = <<<'EODUMP' +Symfony\Component\ErrorHandler\Exception\SilencedErrorContext { + +count: 1 + -severity: E_ERROR + trace: { + %s%eTests%eCaster%eExceptionCasterTest.php:%d { + › { + › return new SilencedErrorContext(\E_ERROR, __FILE__, __LINE__); + › } + } + } +} +EODUMP; + + $this->assertDumpMatchesFormat($expectedDump, $e); + } + public function testSeek() { $e = $this->getTestException(2); diff --git a/Tests/Caster/FFICasterTest.php b/Tests/Caster/FFICasterTest.php index ac4aa93d..32fea5fc 100644 --- a/Tests/Caster/FFICasterTest.php +++ b/Tests/Caster/FFICasterTest.php @@ -90,7 +90,7 @@ public function testCastNamedEnum() PHP, \FFI::new('enum Example { a, b }')); } - public function scalarsDataProvider(): array + public static function scalarsDataProvider(): array { return [ 'int8_t' => ['int8_t', '0', 1, 1], diff --git a/Tests/Caster/FiberCasterTest.php b/Tests/Caster/FiberCasterTest.php new file mode 100644 index 00000000..41ba099d --- /dev/null +++ b/Tests/Caster/FiberCasterTest.php @@ -0,0 +1,76 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Tests\Caster; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\VarDumper\Test\VarDumperTestTrait; + +class FiberCasterTest extends TestCase +{ + use VarDumperTestTrait; + + public function testCastFiberNotStarted() + { + $fiber = new \Fiber(static fn() => true); + + $expected = <<assertDumpEquals($expected, $fiber); + } + + public function testCastFiberTerminated() + { + $fiber = new \Fiber(static fn () => true); + $fiber->start(); + + $expected = <<assertDumpEquals($expected, $fiber); + } + + public function testCastFiberSuspended() + { + $fiber = new \Fiber(\Fiber::suspend(...)); + $fiber->start(); + + $expected = <<assertDumpEquals($expected, $fiber); + } + + public function testCastFiberRunning() + { + $fiber = new \Fiber(function () { + $expected = <<assertDumpEquals($expected, \Fiber::getCurrent()); + }); + + $fiber->start(); + } +} diff --git a/Tests/Caster/MysqliCasterTest.php b/Tests/Caster/MysqliCasterTest.php index e05ae41b..983f541a 100644 --- a/Tests/Caster/MysqliCasterTest.php +++ b/Tests/Caster/MysqliCasterTest.php @@ -16,6 +16,7 @@ /** * @requires extension mysqli + * * @group integration */ class MysqliCasterTest extends TestCase diff --git a/Tests/Caster/RdKafkaCasterTest.php b/Tests/Caster/RdKafkaCasterTest.php index 4cc836f2..65e8ec3b 100644 --- a/Tests/Caster/RdKafkaCasterTest.php +++ b/Tests/Caster/RdKafkaCasterTest.php @@ -20,6 +20,7 @@ /** * @requires extension rdkafka + * * @group integration */ class RdKafkaCasterTest extends TestCase diff --git a/Tests/Caster/RedisCasterTest.php b/Tests/Caster/RedisCasterTest.php index 058b95d0..566de12a 100644 --- a/Tests/Caster/RedisCasterTest.php +++ b/Tests/Caster/RedisCasterTest.php @@ -16,7 +16,9 @@ /** * @author Nicolas Grekas + * * @requires extension redis + * * @group integration */ class RedisCasterTest extends TestCase diff --git a/Tests/Caster/SplCasterTest.php b/Tests/Caster/SplCasterTest.php index 26887b13..743b357c 100644 --- a/Tests/Caster/SplCasterTest.php +++ b/Tests/Caster/SplCasterTest.php @@ -21,7 +21,7 @@ class SplCasterTest extends TestCase { use VarDumperTestTrait; - public function getCastFileInfoTests() + public static function getCastFileInfoTests() { return [ [__FILE__, <<<'EOTXT' @@ -135,7 +135,7 @@ public function testCastSplDoublyLinkedList($modeValue, $modeDump) $this->assertDumpMatchesFormat($dump, $var); } - public function provideCastSplDoublyLinkedList() + public static function provideCastSplDoublyLinkedList() { return [ [\SplDoublyLinkedList::IT_MODE_FIFO, 'IT_MODE_FIFO | IT_MODE_KEEP'], diff --git a/Tests/Caster/XmlReaderCasterTest.php b/Tests/Caster/XmlReaderCasterTest.php index cde1d7e9..78416f30 100644 --- a/Tests/Caster/XmlReaderCasterTest.php +++ b/Tests/Caster/XmlReaderCasterTest.php @@ -64,7 +64,7 @@ public function testNodes($seek, $expectedDump) $this->assertDumpMatchesFormat($expectedDump, $this->reader); } - public function provideNodes() + public static function provideNodes() { return [ [0, <<<'EODUMP' diff --git a/Tests/Command/Descriptor/CliDescriptorTest.php b/Tests/Command/Descriptor/CliDescriptorTest.php index 56fb2187..5941508a 100644 --- a/Tests/Command/Descriptor/CliDescriptorTest.php +++ b/Tests/Command/Descriptor/CliDescriptorTest.php @@ -54,7 +54,7 @@ public function testDescribe(array $context, string $expectedOutput, bool $decor $this->assertStringMatchesFormat(trim($expectedOutput), str_replace(\PHP_EOL, "\n", trim($output->fetch()))); } - public function provideContext() + public static function provideContext() { yield 'source' => [ [ diff --git a/Tests/Command/Descriptor/HtmlDescriptorTest.php b/Tests/Command/Descriptor/HtmlDescriptorTest.php index 426e99d3..09acf149 100644 --- a/Tests/Command/Descriptor/HtmlDescriptorTest.php +++ b/Tests/Command/Descriptor/HtmlDescriptorTest.php @@ -63,7 +63,7 @@ public function testDescribe(array $context, string $expectedOutput) $this->assertStringMatchesFormat(trim($expectedOutput), trim(preg_replace('@@s', '', $output->fetch()))); } - public function provideContext() + public static function provideContext() { yield 'source' => [ [ diff --git a/Tests/Command/ServerDumpCommandTest.php b/Tests/Command/ServerDumpCommandTest.php index 664a520d..47c45fd1 100644 --- a/Tests/Command/ServerDumpCommandTest.php +++ b/Tests/Command/ServerDumpCommandTest.php @@ -28,7 +28,7 @@ public function testComplete(array $input, array $expectedSuggestions) $this->assertSame($expectedSuggestions, $tester->complete($input)); } - public function provideCompletionSuggestions() + public static function provideCompletionSuggestions() { yield 'option --format' => [ ['--format', ''], diff --git a/Tests/Dumper/CliDumperTest.php b/Tests/Dumper/CliDumperTest.php index b4780cfe..25e9b103 100644 --- a/Tests/Dumper/CliDumperTest.php +++ b/Tests/Dumper/CliDumperTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\VarDumper\Tests\Dumper; use PHPUnit\Framework\TestCase; +use Symfony\Component\VarDumper\Caster\CutStub; use Symfony\Component\VarDumper\Cloner\VarCloner; use Symfony\Component\VarDumper\Dumper\AbstractDumper; use Symfony\Component\VarDumper\Dumper\CliDumper; @@ -37,6 +38,11 @@ public function testGet() ':stream' => function ($res, $a) { unset($a['uri'], $a['wrapper_data']); + return $a; + }, + 'Symfony\Component\VarDumper\Tests\Fixture\DumbFoo' => function ($foo, $a) { + $a['foo'] = new CutStub($a['foo']); + return $a; }, ]); @@ -76,7 +82,7 @@ public function testGet() %A options: [] } "obj" => Symfony\Component\VarDumper\Tests\Fixture\DumbFoo {#%d - +foo: "foo" + +foo: ""…3 +"bar": "bar" } "closure" => Closure(\$a, PDO &\$b = null) {#%d @@ -157,7 +163,7 @@ public function testDumpWithCommaFlagsAndExceptionCodeExcerpt() , $dump); } - public function provideDumpWithCommaFlagTests() + public static function provideDumpWithCommaFlagTests() { $expected = <<<'EOTXT' array:3 [ @@ -398,7 +404,7 @@ public function testIncompleteClass() ); } - public function provideDumpArrayWithColor() + public static function provideDumpArrayWithColor() { yield [ ['foo' => 'bar'], diff --git a/Tests/Dumper/ContextProvider/RequestContextProviderTest.php b/Tests/Dumper/ContextProvider/RequestContextProviderTest.php new file mode 100644 index 00000000..5c141595 --- /dev/null +++ b/Tests/Dumper/ContextProvider/RequestContextProviderTest.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Dumper\ContextProvider; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\VarDumper\Cloner\Data; +use Symfony\Component\VarDumper\Dumper\ContextProvider\RequestContextProvider; + +/** + * @requires function \Symfony\Component\HttpFoundation\RequestStack::__construct + */ +class RequestContextProviderTest extends TestCase +{ + public function testGetContextOnNullRequest() + { + $requestStack = new RequestStack(); + $provider = new RequestContextProvider($requestStack); + + $this->assertNull($provider->getContext()); + } + + public function testGetContextOnRequest() + { + $request = Request::create('https://example.org/', 'POST'); + $request->attributes->set('_controller', 'MyControllerClass'); + + $requestStack = new RequestStack(); + $requestStack->push($request); + + $context = (new RequestContextProvider($requestStack))->getContext(); + $this->assertSame('https://example.org/', $context['uri']); + $this->assertSame('POST', $context['method']); + $this->assertInstanceOf(Data::class, $context['controller']); + $this->assertSame('MyControllerClass', $context['controller']->getValue()); + $this->assertSame('https://example.org/', $context['uri']); + $this->assertArrayHasKey('identifier', $context); + } +} diff --git a/Tests/Dumper/HtmlDumperTest.php b/Tests/Dumper/HtmlDumperTest.php index 1fd98640..8c9592e4 100644 --- a/Tests/Dumper/HtmlDumperTest.php +++ b/Tests/Dumper/HtmlDumperTest.php @@ -180,7 +180,7 @@ public function testDumpString($var, $needle) $this->assertStringContainsString($needle, $out); } - public function varToDumpProvider() + public static function varToDumpProvider() { return [ [['dummy' => new ImgStub('dummy', 'img/png', '100em')], ''],