Merge branch '4.4'
* 4.4: [FrameworkBundle] added type-hints on private methods add parameter type declarations to private methods add missing changelog entry Avoid using huge amount of memory when formatting long exception [VarDumper] added support for Imagine/Image clarify error handler restoring process [Messenger][Profiler] Attempt to give more useful source info when using HandleTrait [VarDumper] cs fix [DI] fix perf issue with lazy autowire error messages [Messenger][Profiler] Collect the stamps at the end of dispatch Fix pluralizing "season"
This commit is contained in:
commit
f815bce56e
@ -51,6 +51,7 @@ CHANGELOG
|
||||
4.1.0
|
||||
-----
|
||||
|
||||
* The `switch_user.stateless` firewall option is deprecated, use the `stateless` option instead.
|
||||
* The `logout_on_user_change` firewall option is deprecated.
|
||||
* deprecated `SecurityUserValueResolver`, use
|
||||
`Symfony\Component\Security\Http\Controller\UserValueResolver` instead.
|
||||
|
@ -10,11 +10,12 @@ CHANGELOG
|
||||
4.4.0
|
||||
-----
|
||||
|
||||
* Added button to clear the ajax request tab
|
||||
* Deprecated the `ExceptionController::templateExists()` method
|
||||
* Deprecated the `TemplateManager::templateExists()` method
|
||||
* Deprecated the `ExceptionController` in favor of `ExceptionPanelController`
|
||||
* Marked all classes of the WebProfilerBundle as internal
|
||||
* added button to clear the ajax request tab
|
||||
* deprecated the `ExceptionController::templateExists()` method
|
||||
* deprecated the `TemplateManager::templateExists()` method
|
||||
* deprecated the `ExceptionController` in favor of `ExceptionPanelController`
|
||||
* marked all classes of the WebProfilerBundle as internal
|
||||
* added a section with the stamps of a message after it is dispatched in the Messenger panel
|
||||
|
||||
4.3.0
|
||||
-----
|
||||
|
@ -45,7 +45,7 @@
|
||||
{{ parent() }}
|
||||
<style>
|
||||
.message-item thead th { position: relative; cursor: pointer; user-select: none; padding-right: 35px; }
|
||||
.message-item tbody tr td:first-child { width: 115px; }
|
||||
.message-item tbody tr td:first-child { width: 170px; }
|
||||
|
||||
.message-item .label { float: right; padding: 1px 5px; opacity: .75; margin-left: 5px; }
|
||||
.message-item .toggle-button { position: absolute; right: 6px; top: 6px; opacity: .5; pointer-events: none }
|
||||
@ -166,7 +166,7 @@
|
||||
<td>{{ profiler_dump(dispatchCall.message.value, maxDepth=2) }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text-bold">Envelope stamps</td>
|
||||
<td class="text-bold">Envelope stamps <span class="text-muted">when dispatching</span></td>
|
||||
<td>
|
||||
{% for item in dispatchCall.stamps %}
|
||||
{{ profiler_dump(item) }}
|
||||
@ -175,6 +175,18 @@
|
||||
{% endfor %}
|
||||
</td>
|
||||
</tr>
|
||||
{% if dispatchCall.stamps_after_dispatch is defined %}
|
||||
<tr>
|
||||
<td class="text-bold">Envelope stamps <span class="text-muted">after dispatch</span></td>
|
||||
<td>
|
||||
{% for item in dispatchCall.stamps_after_dispatch %}
|
||||
{{ profiler_dump(item) }}
|
||||
{% else %}
|
||||
<span class="text-muted">No items</span>
|
||||
{% endfor %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if dispatchCall.exception is defined %}
|
||||
<tr>
|
||||
<td class="text-bold">Exception</td>
|
||||
|
@ -1111,15 +1111,21 @@ class Application implements ResetInterface
|
||||
$utf8String = mb_convert_encoding($string, 'utf8', $encoding);
|
||||
$lines = [];
|
||||
$line = '';
|
||||
foreach (preg_split('//u', $utf8String) as $char) {
|
||||
// test if $char could be appended to current line
|
||||
if (mb_strwidth($line.$char, 'utf8') <= $width) {
|
||||
$line .= $char;
|
||||
continue;
|
||||
|
||||
$offset = 0;
|
||||
while (preg_match('/.{1,10000}/u', $utf8String, $m, 0, $offset)) {
|
||||
$offset += \strlen($m[0]);
|
||||
|
||||
foreach (preg_split('//u', $m[0]) as $char) {
|
||||
// test if $char could be appended to current line
|
||||
if (mb_strwidth($line.$char, 'utf8') <= $width) {
|
||||
$line .= $char;
|
||||
continue;
|
||||
}
|
||||
// if not, push current line to array and make new line
|
||||
$lines[] = str_pad($line, $width);
|
||||
$line = $char;
|
||||
}
|
||||
// if not, push current line to array and make new line
|
||||
$lines[] = str_pad($line, $width);
|
||||
$line = $char;
|
||||
}
|
||||
|
||||
$lines[] = \count($lines) ? str_pad($line, $width) : $line;
|
||||
|
@ -37,6 +37,7 @@ class AutowirePass extends AbstractRecursivePass
|
||||
private $getPreviousValue;
|
||||
private $decoratedMethodIndex;
|
||||
private $decoratedMethodArgumentIndex;
|
||||
private $typesClone;
|
||||
|
||||
public function __construct(bool $throwOnAutowireException = true)
|
||||
{
|
||||
@ -49,16 +50,16 @@ class AutowirePass extends AbstractRecursivePass
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
try {
|
||||
$this->typesClone = clone $this;
|
||||
parent::process($container);
|
||||
} finally {
|
||||
$this->types = null;
|
||||
$this->ambiguousServiceTypes = null;
|
||||
$this->decoratedClass = null;
|
||||
$this->decoratedId = null;
|
||||
$this->methodCalls = null;
|
||||
$this->getPreviousValue = null;
|
||||
$this->decoratedMethodIndex = null;
|
||||
$this->decoratedMethodArgumentIndex = null;
|
||||
$this->typesClone = null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -375,20 +376,22 @@ class AutowirePass extends AbstractRecursivePass
|
||||
|
||||
private function createTypeNotFoundMessageCallback(TypedReference $reference, string $label)
|
||||
{
|
||||
$container = new ContainerBuilder($this->container->getParameterBag());
|
||||
$container->setAliases($this->container->getAliases());
|
||||
$container->setDefinitions($this->container->getDefinitions());
|
||||
$container->setResourceTracking(false);
|
||||
if (null === $this->typesClone->container) {
|
||||
$this->typesClone->container = new ContainerBuilder($this->container->getParameterBag());
|
||||
$this->typesClone->container->setAliases($this->container->getAliases());
|
||||
$this->typesClone->container->setDefinitions($this->container->getDefinitions());
|
||||
$this->typesClone->container->setResourceTracking(false);
|
||||
}
|
||||
$currentId = $this->currentId;
|
||||
|
||||
return function () use ($container, $reference, $label, $currentId) {
|
||||
return $this->createTypeNotFoundMessage($container, $reference, $label, $currentId);
|
||||
};
|
||||
return (function () use ($reference, $label, $currentId) {
|
||||
return $this->createTypeNotFoundMessage($reference, $label, $currentId);
|
||||
})->bindTo($this->typesClone);
|
||||
}
|
||||
|
||||
private function createTypeNotFoundMessage(ContainerBuilder $container, TypedReference $reference, string $label, string $currentId)
|
||||
private function createTypeNotFoundMessage(TypedReference $reference, string $label, string $currentId)
|
||||
{
|
||||
if (!$r = $container->getReflectionClass($type = $reference->getType(), false)) {
|
||||
if (!$r = $this->container->getReflectionClass($type = $reference->getType(), false)) {
|
||||
// either $type does not exist or a parent class does not exist
|
||||
try {
|
||||
$resource = new ClassExistenceResource($type, false);
|
||||
@ -401,8 +404,8 @@ class AutowirePass extends AbstractRecursivePass
|
||||
|
||||
$message = sprintf('has type "%s" but this class %s.', $type, $parentMsg ? sprintf('is missing a parent class (%s)', $parentMsg) : 'was not found');
|
||||
} else {
|
||||
$alternatives = $this->createTypeAlternatives($container, $reference);
|
||||
$message = $container->has($type) ? 'this service is abstract' : 'no such service exists';
|
||||
$alternatives = $this->createTypeAlternatives($this->container, $reference);
|
||||
$message = $this->container->has($type) ? 'this service is abstract' : 'no such service exists';
|
||||
$message = sprintf('references %s "%s" but %s.%s', $r->isInterface() ? 'interface' : 'class', $type, $message, $alternatives);
|
||||
|
||||
if ($r->isInterface() && !$alternatives) {
|
||||
|
@ -50,10 +50,9 @@ class CacheWarmerAggregate implements CacheWarmerInterface
|
||||
*/
|
||||
public function warmUp($cacheDir)
|
||||
{
|
||||
if ($this->debug) {
|
||||
if ($collectDeprecations = $this->debug && !\defined('PHPUNIT_COMPOSER_INSTALL')) {
|
||||
$collectedLogs = [];
|
||||
$previousHandler = \defined('PHPUNIT_COMPOSER_INSTALL');
|
||||
$previousHandler = $previousHandler ?: set_error_handler(function ($type, $message, $file, $line) use (&$collectedLogs, &$previousHandler) {
|
||||
$previousHandler = set_error_handler(function ($type, $message, $file, $line) use (&$collectedLogs, &$previousHandler) {
|
||||
if (E_USER_DEPRECATED !== $type && E_DEPRECATED !== $type) {
|
||||
return $previousHandler ? $previousHandler($type, $message, $file, $line) : false;
|
||||
}
|
||||
@ -96,7 +95,7 @@ class CacheWarmerAggregate implements CacheWarmerInterface
|
||||
$warmer->warmUp($cacheDir);
|
||||
}
|
||||
} finally {
|
||||
if ($this->debug && true !== $previousHandler) {
|
||||
if ($collectDeprecations) {
|
||||
restore_error_handler();
|
||||
|
||||
if (file_exists($this->deprecationLogsFilepath)) {
|
||||
|
@ -228,6 +228,9 @@ final class Inflector
|
||||
// bacteria (bacterium), criteria (criterion), phenomena (phenomenon)
|
||||
['noi', 3, true, true, 'ions'],
|
||||
|
||||
// seasons (season), treasons (treason), poisons (poison), lessons (lesson)
|
||||
['nos', 3, true, true, 'sons'],
|
||||
|
||||
// bacteria (bacterium), criteria (criterion), phenomena (phenomenon)
|
||||
['no', 2, true, true, 'a'],
|
||||
|
||||
|
@ -93,6 +93,7 @@ class InflectorTest extends TestCase
|
||||
['kisses', 'kiss'],
|
||||
['knives', 'knife'],
|
||||
['lamps', 'lamp'],
|
||||
['lessons', 'lesson'],
|
||||
['leaves', ['leaf', 'leave', 'leaff']],
|
||||
['lice', 'louse'],
|
||||
['lives', 'life'],
|
||||
@ -115,6 +116,7 @@ class InflectorTest extends TestCase
|
||||
['photos', 'photo'],
|
||||
['pianos', 'piano'],
|
||||
['plateaux', 'plateau'],
|
||||
['poisons', 'poison'],
|
||||
['poppies', 'poppy'],
|
||||
['prices', ['prex', 'prix', 'price']],
|
||||
['quizzes', 'quiz'],
|
||||
@ -124,6 +126,7 @@ class InflectorTest extends TestCase
|
||||
['sandwiches', ['sandwich', 'sandwiche']],
|
||||
['scarves', ['scarf', 'scarve', 'scarff']],
|
||||
['schemas', 'schema'], //schemata
|
||||
['seasons', 'season'],
|
||||
['selfies', 'selfie'],
|
||||
['series', 'series'],
|
||||
['services', 'service'],
|
||||
@ -139,6 +142,7 @@ class InflectorTest extends TestCase
|
||||
['teeth', 'tooth'],
|
||||
['theses', ['thes', 'these', 'thesis']],
|
||||
['thieves', ['thief', 'thieve', 'thieff']],
|
||||
['treasons', 'treason'],
|
||||
['trees', ['tre', 'tree']],
|
||||
['waltzes', ['waltz', 'waltze']],
|
||||
['wives', 'wife'],
|
||||
@ -226,6 +230,7 @@ class InflectorTest extends TestCase
|
||||
['knife', 'knives'],
|
||||
['lamp', 'lamps'],
|
||||
['leaf', ['leafs', 'leaves']],
|
||||
['lesson', 'lessons'],
|
||||
['life', 'lives'],
|
||||
['louse', 'lice'],
|
||||
['man', 'men'],
|
||||
@ -245,6 +250,7 @@ class InflectorTest extends TestCase
|
||||
['photo', 'photos'],
|
||||
['piano', 'pianos'],
|
||||
['plateau', ['plateaus', 'plateaux']],
|
||||
['poison', 'poisons'],
|
||||
['poppy', 'poppies'],
|
||||
['price', 'prices'],
|
||||
['quiz', 'quizzes'],
|
||||
@ -254,6 +260,7 @@ class InflectorTest extends TestCase
|
||||
['sandwich', 'sandwiches'],
|
||||
['scarf', ['scarfs', 'scarves']],
|
||||
['schema', 'schemas'], //schemata
|
||||
['season', 'seasons'],
|
||||
['selfie', 'selfies'],
|
||||
['series', 'series'],
|
||||
['service', 'services'],
|
||||
@ -268,6 +275,7 @@ class InflectorTest extends TestCase
|
||||
['tag', 'tags'],
|
||||
['thief', ['thiefs', 'thieves']],
|
||||
['tooth', 'teeth'],
|
||||
['treason', 'treasons'],
|
||||
['tree', 'trees'],
|
||||
['waltz', 'waltzes'],
|
||||
['wife', 'wives'],
|
||||
|
@ -99,6 +99,7 @@ class MessengerDataCollector extends DataCollector implements LateDataCollectorI
|
||||
$debugRepresentation = [
|
||||
'bus' => $busName,
|
||||
'stamps' => $tracedMessage['stamps'] ?? null,
|
||||
'stamps_after_dispatch' => $tracedMessage['stamps_after_dispatch'] ?? null,
|
||||
'message' => [
|
||||
'type' => new ClassStub(\get_class($message)),
|
||||
'value' => $message,
|
||||
|
@ -55,9 +55,10 @@ class MessengerDataCollectorTest extends TestCase
|
||||
|
||||
$file = __FILE__;
|
||||
$expected = <<<DUMP
|
||||
array:4 [
|
||||
array:5 [
|
||||
"bus" => "default"
|
||||
"stamps" => []
|
||||
"stamps_after_dispatch" => []
|
||||
"message" => array:2 [
|
||||
"type" => "Symfony\Component\Messenger\Tests\Fixtures\DummyMessage"
|
||||
"value" => Symfony\Component\Messenger\Tests\Fixtures\DummyMessage %A
|
||||
@ -100,9 +101,10 @@ DUMP;
|
||||
|
||||
$file = __FILE__;
|
||||
$this->assertStringMatchesFormat(<<<DUMP
|
||||
array:5 [
|
||||
array:6 [
|
||||
"bus" => "default"
|
||||
"stamps" => []
|
||||
"stamps_after_dispatch" => []
|
||||
"message" => array:2 [
|
||||
"type" => "Symfony\Component\Messenger\Tests\Fixtures\DummyMessage"
|
||||
"value" => Symfony\Component\Messenger\Tests\Fixtures\DummyMessage %A
|
||||
|
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Messenger\Tests\Fixtures;
|
||||
|
||||
use Symfony\Component\Messenger\HandleTrait;
|
||||
use Symfony\Component\Messenger\MessageBusInterface;
|
||||
|
||||
/**
|
||||
* @see \Symfony\Component\Messenger\Tests\TraceableMessageBusTest::testItTracesDispatchWhenHandleTraitIsUsed
|
||||
*/
|
||||
class TestTracesWithHandleTraitAction
|
||||
{
|
||||
use HandleTrait;
|
||||
|
||||
public function __construct(MessageBusInterface $messageBus)
|
||||
{
|
||||
$this->messageBus = $messageBus;
|
||||
}
|
||||
|
||||
public function __invoke($message)
|
||||
{
|
||||
$this->handle($message);
|
||||
}
|
||||
}
|
@ -15,8 +15,10 @@ use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Messenger\Envelope;
|
||||
use Symfony\Component\Messenger\MessageBusInterface;
|
||||
use Symfony\Component\Messenger\Stamp\DelayStamp;
|
||||
use Symfony\Component\Messenger\Stamp\HandledStamp;
|
||||
use Symfony\Component\Messenger\Tests\Fixtures\AnEnvelopeStamp;
|
||||
use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage;
|
||||
use Symfony\Component\Messenger\Tests\Fixtures\TestTracesWithHandleTraitAction;
|
||||
use Symfony\Component\Messenger\TraceableMessageBus;
|
||||
|
||||
class TraceableMessageBusTest extends TestCase
|
||||
@ -27,7 +29,7 @@ class TraceableMessageBusTest extends TestCase
|
||||
|
||||
$stamp = new DelayStamp(5);
|
||||
$bus = $this->getMockBuilder(MessageBusInterface::class)->getMock();
|
||||
$bus->expects($this->once())->method('dispatch')->with($message, [$stamp])->willReturn(new Envelope($message));
|
||||
$bus->expects($this->once())->method('dispatch')->with($message, [$stamp])->willReturn(new Envelope($message, [$stamp]));
|
||||
|
||||
$traceableBus = new TraceableMessageBus($bus);
|
||||
$line = __LINE__ + 1;
|
||||
@ -38,6 +40,7 @@ class TraceableMessageBusTest extends TestCase
|
||||
$this->assertEquals([
|
||||
'message' => $message,
|
||||
'stamps' => [$stamp],
|
||||
'stamps_after_dispatch' => [$stamp],
|
||||
'caller' => [
|
||||
'name' => 'TraceableMessageBusTest.php',
|
||||
'file' => __FILE__,
|
||||
@ -46,6 +49,29 @@ class TraceableMessageBusTest extends TestCase
|
||||
], $actualTracedMessage);
|
||||
}
|
||||
|
||||
public function testItTracesDispatchWhenHandleTraitIsUsed()
|
||||
{
|
||||
$message = new DummyMessage('Hello');
|
||||
|
||||
$bus = $this->getMockBuilder(MessageBusInterface::class)->getMock();
|
||||
$bus->expects($this->once())->method('dispatch')->with($message)->willReturn((new Envelope($message))->with(new HandledStamp('result', 'handlerName')));
|
||||
|
||||
$traceableBus = new TraceableMessageBus($bus);
|
||||
(new TestTracesWithHandleTraitAction($traceableBus))($message);
|
||||
$this->assertCount(1, $tracedMessages = $traceableBus->getDispatchedMessages());
|
||||
$actualTracedMessage = $tracedMessages[0];
|
||||
unset($actualTracedMessage['callTime']); // don't check, too variable
|
||||
$this->assertEquals([
|
||||
'message' => $message,
|
||||
'stamps' => [],
|
||||
'caller' => [
|
||||
'name' => 'TestTracesWithHandleTraitAction.php',
|
||||
'file' => (new \ReflectionClass(TestTracesWithHandleTraitAction::class))->getFileName(),
|
||||
'line' => (new \ReflectionMethod(TestTracesWithHandleTraitAction::class, '__invoke'))->getStartLine() + 2,
|
||||
],
|
||||
], $actualTracedMessage);
|
||||
}
|
||||
|
||||
public function testItTracesDispatchWithEnvelope()
|
||||
{
|
||||
$message = new DummyMessage('Hello');
|
||||
@ -63,6 +89,33 @@ class TraceableMessageBusTest extends TestCase
|
||||
$this->assertEquals([
|
||||
'message' => $message,
|
||||
'stamps' => [$stamp],
|
||||
'stamps_after_dispatch' => [$stamp],
|
||||
'caller' => [
|
||||
'name' => 'TraceableMessageBusTest.php',
|
||||
'file' => __FILE__,
|
||||
'line' => $line,
|
||||
],
|
||||
], $actualTracedMessage);
|
||||
}
|
||||
|
||||
public function testItCollectsStampsAddedDuringDispatch()
|
||||
{
|
||||
$message = new DummyMessage('Hello');
|
||||
$envelope = (new Envelope($message))->with($stamp = new AnEnvelopeStamp());
|
||||
|
||||
$bus = $this->getMockBuilder(MessageBusInterface::class)->getMock();
|
||||
$bus->expects($this->once())->method('dispatch')->with($envelope)->willReturn($envelope->with($anotherStamp = new AnEnvelopeStamp()));
|
||||
|
||||
$traceableBus = new TraceableMessageBus($bus);
|
||||
$line = __LINE__ + 1;
|
||||
$traceableBus->dispatch($envelope);
|
||||
$this->assertCount(1, $tracedMessages = $traceableBus->getDispatchedMessages());
|
||||
$actualTracedMessage = $tracedMessages[0];
|
||||
unset($actualTracedMessage['callTime']); // don't check, too variable
|
||||
$this->assertEquals([
|
||||
'message' => $message,
|
||||
'stamps' => [$stamp],
|
||||
'stamps_after_dispatch' => [$stamp, $anotherStamp],
|
||||
'caller' => [
|
||||
'name' => 'TraceableMessageBusTest.php',
|
||||
'file' => __FILE__,
|
||||
@ -94,6 +147,7 @@ class TraceableMessageBusTest extends TestCase
|
||||
'message' => $message,
|
||||
'exception' => $exception,
|
||||
'stamps' => [],
|
||||
'stamps_after_dispatch' => [],
|
||||
'caller' => [
|
||||
'name' => 'TraceableMessageBusTest.php',
|
||||
'file' => __FILE__,
|
||||
|
@ -38,13 +38,13 @@ class TraceableMessageBus implements MessageBusInterface
|
||||
];
|
||||
|
||||
try {
|
||||
return $this->decoratedBus->dispatch($message, $stamps);
|
||||
return $envelope = $this->decoratedBus->dispatch($message, $stamps);
|
||||
} catch (\Throwable $e) {
|
||||
$context['exception'] = $e;
|
||||
|
||||
throw $e;
|
||||
} finally {
|
||||
$this->dispatchedMessages[] = $context;
|
||||
$this->dispatchedMessages[] = $context + ['stamps_after_dispatch' => array_merge([], ...array_values($envelope->all()))];
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,7 +65,19 @@ class TraceableMessageBus implements MessageBusInterface
|
||||
$file = $trace[1]['file'];
|
||||
$line = $trace[1]['line'];
|
||||
|
||||
for ($i = 2; $i < 8; ++$i) {
|
||||
$handleTraitFile = (new \ReflectionClass(HandleTrait::class))->getFileName();
|
||||
$found = false;
|
||||
for ($i = 1; $i < 8; ++$i) {
|
||||
if (isset($trace[$i]['file'], $trace[$i + 1]['file'], $trace[$i + 1]['line']) && $trace[$i]['file'] === $handleTraitFile) {
|
||||
$file = $trace[$i + 1]['file'];
|
||||
$line = $trace[$i + 1]['line'];
|
||||
$found = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for ($i = 2; $i < 8 && !$found; ++$i) {
|
||||
if (isset($trace[$i]['class'], $trace[$i]['function'])
|
||||
&& 'dispatch' === $trace[$i]['function']
|
||||
&& is_a($trace[$i]['class'], MessageBusInterface::class, true)
|
||||
|
@ -4,8 +4,10 @@ CHANGELOG
|
||||
4.4.0
|
||||
-----
|
||||
|
||||
* added `VarDumperTestTrait::setUpVarDumper()` and `VarDumperTestTrait::tearDownVarDumper()`
|
||||
* added `VarDumperTestTrait::setUpVarDumper()` and `VarDumperTestTrait::tearDownVarDumper()`
|
||||
to configure casters & flags to use in tests
|
||||
* added `ImagineCaster` and infrastructure to dump images
|
||||
* added the stamps of a message after it is dispatched in `TraceableMessageBus` and `MessengerDataCollector` collected data
|
||||
|
||||
4.3.0
|
||||
-----
|
||||
|
37
src/Symfony/Component/VarDumper/Caster/ImagineCaster.php
Normal file
37
src/Symfony/Component/VarDumper/Caster/ImagineCaster.php
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\VarDumper\Caster;
|
||||
|
||||
use Imagine\Image\ImageInterface;
|
||||
use Symfony\Component\VarDumper\Cloner\Stub;
|
||||
|
||||
/**
|
||||
* @author Grégoire Pineau <lyrixx@lyrixx.info>
|
||||
*/
|
||||
class ImagineCaster
|
||||
{
|
||||
public static function castImage(ImageInterface $c, array $a, Stub $stub, $isNested)
|
||||
{
|
||||
$imgData = $c->get('png');
|
||||
if (\strlen($imgData) > 1 * 1000 * 1000) {
|
||||
$a += [
|
||||
Caster::PREFIX_VIRTUAL.'image' => new ConstStub($c->getSize()),
|
||||
];
|
||||
} else {
|
||||
$a += [
|
||||
Caster::PREFIX_VIRTUAL.'image' => new ImgStub($imgData, 'image/png', $c->getSize()),
|
||||
];
|
||||
}
|
||||
|
||||
return $a;
|
||||
}
|
||||
}
|
26
src/Symfony/Component/VarDumper/Caster/ImgStub.php
Normal file
26
src/Symfony/Component/VarDumper/Caster/ImgStub.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\VarDumper\Caster;
|
||||
|
||||
/**
|
||||
* @author Grégoire Pineau <lyrixx@lyrixx.info>
|
||||
*/
|
||||
class ImgStub extends ConstStub
|
||||
{
|
||||
public function __construct(string $data, string $contentType, string $size)
|
||||
{
|
||||
$this->value = '';
|
||||
$this->attr['img-data'] = $data;
|
||||
$this->attr['img-size'] = $size;
|
||||
$this->attr['content-type'] = $contentType;
|
||||
}
|
||||
}
|
@ -87,6 +87,8 @@ abstract class AbstractCloner implements ClonerInterface
|
||||
'Symfony\Component\VarDumper\Cloner\AbstractCloner' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'],
|
||||
'Symfony\Component\ErrorHandler\Exception\SilencedErrorContext' => ['Symfony\Component\VarDumper\Caster\ExceptionCaster', 'castSilencedErrorContext'],
|
||||
|
||||
'Imagine\Image\ImageInterface' => ['Symfony\Component\VarDumper\Caster\ImagineCaster', 'castImage'],
|
||||
|
||||
'ProxyManager\Proxy\ProxyInterface' => ['Symfony\Component\VarDumper\Caster\ProxyManagerCaster', 'castProxy'],
|
||||
'PHPUnit_Framework_MockObject_MockObject' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'],
|
||||
'Prophecy\Prophecy\ProphecySubjectInterface' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'],
|
||||
|
@ -473,7 +473,7 @@ return function (root, x) {
|
||||
return this.current();
|
||||
}
|
||||
this.idx = this.idx < (this.nodes.length - 1) ? this.idx + 1 : 0;
|
||||
|
||||
|
||||
return this.current();
|
||||
},
|
||||
previous: function () {
|
||||
@ -481,7 +481,7 @@ return function (root, x) {
|
||||
return this.current();
|
||||
}
|
||||
this.idx = this.idx > 0 ? this.idx - 1 : (this.nodes.length - 1);
|
||||
|
||||
|
||||
return this.current();
|
||||
},
|
||||
isEmpty: function () {
|
||||
@ -565,11 +565,11 @@ return function (root, x) {
|
||||
"sf-dump-protected",
|
||||
"sf-dump-private",
|
||||
].map(xpathHasClass).join(' or ');
|
||||
|
||||
|
||||
var xpathResult = doc.evaluate('.//span[' + classMatches + '][contains(translate(child::text(), ' + xpathString(searchQuery.toUpperCase()) + ', ' + xpathString(searchQuery.toLowerCase()) + '), ' + xpathString(searchQuery.toLowerCase()) + ')]', root, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
|
||||
|
||||
while (node = xpathResult.iterateNext()) state.nodes.push(node);
|
||||
|
||||
|
||||
showCurrent(state);
|
||||
}, 400);
|
||||
});
|
||||
@ -682,6 +682,13 @@ pre.sf-dump a {
|
||||
outline: none;
|
||||
color: inherit;
|
||||
}
|
||||
pre.sf-dump img {
|
||||
max-width: 50em;
|
||||
max-height: 50em;
|
||||
margin: .5em 0 0 0;
|
||||
padding: 0;
|
||||
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAAAAAA6mKC9AAAAHUlEQVQY02O8zAABilCaiQEN0EeA8QuUcX9g3QEAAjcC5piyhyEAAAAASUVORK5CYII=) #D3D3D3;
|
||||
}
|
||||
pre.sf-dump .sf-dump-ellipsis {
|
||||
display: inline-block;
|
||||
overflow: visible;
|
||||
@ -792,6 +799,23 @@ EOHTML
|
||||
return $this->dumpHeader = preg_replace('/\s+/', ' ', $line).'</style>'.$this->dumpHeader;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function dumpString(Cursor $cursor, $str, $bin, $cut)
|
||||
{
|
||||
if ('' === $str && isset($cursor->attr['img-data'], $cursor->attr['content-type'])) {
|
||||
$this->dumpKey($cursor);
|
||||
$this->line .= $this->style('default', $cursor->attr['img-size'] ?? '', []).' <samp>';
|
||||
$this->endValue($cursor);
|
||||
$this->line .= $this->indentPad;
|
||||
$this->line .= sprintf('<img src="data:%s;base64,%s" /></samp>', $cursor->attr['content-type'], base64_encode($cursor->attr['img-data']));
|
||||
$this->endValue($cursor);
|
||||
} else {
|
||||
parent::dumpString($cursor, $str, $bin, $cut);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
Reference in New Issue
Block a user