Skip to content

Commit 5b8b5de

Browse files
authored
Merge pull request #245 from getsentry/add-class_serializers-option
Add class_serializers option
2 parents 4f4dcf0 + df3905e commit 5b8b5de

File tree

8 files changed

+112
-31
lines changed

8 files changed

+112
-31
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
66

77
## [Unreleased]
88
- Add forward compatibility with Symfony 5 (#235, thanks to @garak)
9+
- Fix Hub initialization for `ErrorListener` (#243, thanks to @teohhanhui)
910
- Fix compatibility with sentry/sentry 2.2+ (#244)
11+
- Add support for `class_serializers` option (#245)
1012

1113
## 3.1.0 - 2019-07-02
1214
- Add support for Symfony 2.8 (#233, thanks to @nocive)

src/DependencyInjection/Configuration.php

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,11 @@ public function getConfigTreeBuilder(): TreeBuilder
5757
if (PrettyVersions::getVersion('sentry/sentry')->getPrettyVersion() !== '2.0.0') {
5858
$optionsChildNodes->booleanNode('capture_silenced_errors');
5959
}
60+
if ($this->classSerializersAreSupported()) {
61+
$optionsChildNodes->arrayNode('class_serializers')
62+
->defaultValue([])
63+
->prototype('scalar');
64+
}
6065
$optionsChildNodes->integerNode('context_lines')
6166
->min(0)
6267
->max(99);
@@ -80,13 +85,13 @@ public function getConfigTreeBuilder(): TreeBuilder
8085
->prototype('scalar')
8186
->validate()
8287
->ifTrue(function ($value): bool {
83-
if (! is_string($value)) {
88+
if (! is_string($value) && '' != $value) {
8489
return true;
8590
}
8691

87-
return '@' !== substr($value, 0, 1);
92+
return '@' !== $value[0];
8893
})
89-
->thenInvalid('Expecting service reference, got %s');
94+
->thenInvalid('Expecting service reference, got "%s"');
9095
$optionsChildNodes->scalarNode('logger');
9196
$optionsChildNodes->integerNode('max_breadcrumbs')
9297
->min(1);
@@ -163,4 +168,15 @@ private function isNotAValidCallback(): \Closure
163168
return true;
164169
};
165170
}
171+
172+
private function classSerializersAreSupported(): bool
173+
{
174+
try {
175+
new Options(['class_serializers' => []]);
176+
177+
return true;
178+
} catch (\Throwable $throwable) {
179+
return false;
180+
}
181+
}
166182
}

src/DependencyInjection/SentryExtension.php

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
use Symfony\Component\Config\FileLocator;
1515
use Symfony\Component\Console\ConsoleEvents;
1616
use Symfony\Component\DependencyInjection\ContainerBuilder;
17-
use Symfony\Component\DependencyInjection\Definition;
1817
use Symfony\Component\DependencyInjection\Loader;
1918
use Symfony\Component\DependencyInjection\Reference;
2019
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
@@ -97,11 +96,22 @@ private function passConfigurationToOptions(ContainerBuilder $container, array $
9796
}
9897

9998
if (\array_key_exists('before_send', $processedOptions)) {
100-
$this->mapCallableValue($options, 'setBeforeSendCallback', $processedOptions['before_send']);
99+
$beforeSendCallable = $this->valueToCallable($processedOptions['before_send']);
100+
$options->addMethodCall('setBeforeSendCallback', [$beforeSendCallable]);
101101
}
102102

103103
if (\array_key_exists('before_breadcrumb', $processedOptions)) {
104-
$this->mapCallableValue($options, 'setBeforeBreadcrumbCallback', $processedOptions['before_breadcrumb']);
104+
$beforeBreadcrumbCallable = $this->valueToCallable($processedOptions['before_breadcrumb']);
105+
$options->addMethodCall('setBeforeBreadcrumbCallback', [$beforeBreadcrumbCallable]);
106+
}
107+
108+
if (\array_key_exists('class_serializers', $processedOptions)) {
109+
$classSerializers = [];
110+
foreach ($processedOptions['class_serializers'] as $class => $serializer) {
111+
$classSerializers[$class] = $this->valueToCallable($serializer);
112+
}
113+
114+
$options->addMethodCall('setClassSerializers', [$classSerializers]);
105115
}
106116

107117
if (\array_key_exists('integrations', $processedOptions)) {
@@ -114,20 +124,13 @@ private function passConfigurationToOptions(ContainerBuilder $container, array $
114124
}
115125
}
116126

117-
/**
118-
* @param Definition $options
119-
* @param string $method
120-
* @param callable|string $optionValue
121-
*/
122-
private function mapCallableValue(Definition $options, string $method, $optionValue): void
127+
private function valueToCallable($value)
123128
{
124-
if (is_string($optionValue) && 0 === strpos($optionValue, '@')) {
125-
$beforeSend = new Reference(substr($optionValue, 1));
126-
} else {
127-
$beforeSend = $optionValue;
129+
if (is_string($value) && 0 === strpos($value, '@')) {
130+
return new Reference(substr($value, 1));
128131
}
129132

130-
$options->addMethodCall($method, [$beforeSend]);
133+
return $value;
131134
}
132135

133136
/**

src/EventListener/ConsoleListener.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
namespace Sentry\SentryBundle\EventListener;
44

55
use Sentry\SentryBundle\SentryBundle;
6-
use Sentry\State\Hub;
76
use Sentry\State\HubInterface;
87
use Sentry\State\Scope;
98
use Symfony\Component\Console\Event\ConsoleCommandEvent;

src/EventListener/RequestListener.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
namespace Sentry\SentryBundle\EventListener;
44

55
use Sentry\SentryBundle\SentryBundle;
6-
use Sentry\State\Hub;
76
use Sentry\State\HubInterface;
87
use Sentry\State\Scope;
98
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;

test/BaseTestCase.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
namespace Sentry\SentryBundle\Test;
4+
5+
use PHPUnit\Framework\TestCase;
6+
use Sentry\Options;
7+
use Sentry\SentryBundle\Test\DependencyInjection\ConfigurationTest;
8+
9+
abstract class BaseTestCase extends TestCase
10+
{
11+
public const SUPPORTED_SENTRY_OPTIONS_COUNT = 23;
12+
13+
protected function classSerializersAreSupported(): bool
14+
{
15+
try {
16+
new Options(['class_serializers' => []]);
17+
18+
return true;
19+
} catch (\Throwable $throwable) {
20+
return false;
21+
}
22+
}
23+
24+
protected function getSupportedOptionsCount(): int
25+
{
26+
if ($this->classSerializersAreSupported()) {
27+
return ConfigurationTest::SUPPORTED_SENTRY_OPTIONS_COUNT + 1;
28+
}
29+
30+
return ConfigurationTest::SUPPORTED_SENTRY_OPTIONS_COUNT;
31+
}
32+
}

test/DependencyInjection/ConfigurationTest.php

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,21 @@
33
namespace Sentry\SentryBundle\Test\DependencyInjection;
44

55
use Jean85\PrettyVersions;
6-
use PHPUnit\Framework\TestCase;
76
use Sentry\Options;
87
use Sentry\SentryBundle\DependencyInjection\Configuration;
8+
use Sentry\SentryBundle\Test\BaseTestCase;
99
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
1010
use Symfony\Component\Config\Definition\Processor;
1111
use Symfony\Component\HttpKernel\Kernel;
1212

13-
class ConfigurationTest extends TestCase
13+
class ConfigurationTest extends BaseTestCase
1414
{
15-
public const SUPPORTED_SENTRY_OPTIONS_COUNT = 23;
16-
1715
public function testDataProviderIsMappingTheRightNumberOfOptions(): void
1816
{
1917
$providerData = $this->optionValuesProvider();
2018
$supportedOptions = \array_unique(\array_column($providerData, 0));
2119

22-
$expectedCount = self::SUPPORTED_SENTRY_OPTIONS_COUNT;
20+
$expectedCount = $this->getSupportedOptionsCount();
2321

2422
if (PrettyVersions::getVersion('sentry/sentry')->getPrettyVersion() !== '2.0.0') {
2523
++$expectedCount;
@@ -38,7 +36,7 @@ public function testInvalidDataProviderIsMappingTheRightNumberOfOptions(): void
3836
$supportedOptions = \array_unique(\array_column($providerData, 0));
3937

4038
$this->assertCount(
41-
self::SUPPORTED_SENTRY_OPTIONS_COUNT,
39+
$this->getSupportedOptionsCount(),
4240
$supportedOptions,
4341
'Provider for invalid configuration options mismatch: ' . PHP_EOL . print_r($supportedOptions, true)
4442
);
@@ -76,6 +74,10 @@ public function testConfigurationDefaults(): void
7674
$expectedDefaults['options']['in_app_exclude'][1] = '%kernel.project_dir%/vendor';
7775
}
7876

77+
if ($this->classSerializersAreSupported()) {
78+
$expectedDefaults['options']['class_serializers'] = [];
79+
}
80+
7981
$this->assertEquals($expectedDefaults, $processed);
8082
$this->assertArrayNotHasKey('server_name', $processed['options'], 'server_name has to be fetched at runtime, not before (see #181)');
8183
}
@@ -127,6 +129,10 @@ public function optionValuesProvider(): array
127129
$options[] = ['capture_silenced_errors', true];
128130
}
129131

132+
if ($this->classSerializersAreSupported()) {
133+
$options[] = ['class_serializers', ['count']];
134+
}
135+
130136
return $options;
131137
}
132138

@@ -144,7 +150,7 @@ public function testInvalidValues(string $option, $value): void
144150

145151
public function invalidValuesProvider(): array
146152
{
147-
return [
153+
$values = [
148154
['attach_stacktrace', 'string'],
149155
['before_breadcrumb', 'this is not a callable'],
150156
['before_breadcrumb', [$this, 'is not a callable']],
@@ -184,6 +190,15 @@ public function invalidValuesProvider(): array
184190
['server_name', []],
185191
['tags', 'invalid-unmapped-tag'],
186192
];
193+
194+
if ($this->classSerializersAreSupported()) {
195+
$values[] = ['class_serializers', 'this is not a callable'];
196+
$values[] = ['class_serializers', [$this, 'is not a callable']];
197+
$values[] = ['class_serializers', false];
198+
$values[] = ['class_serializers', -1];
199+
}
200+
201+
return $values;
187202
}
188203

189204
private function processConfiguration(array $values): array

test/DependencyInjection/SentryExtensionTest.php

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33
namespace Sentry\SentryBundle\Test\DependencyInjection;
44

55
use Jean85\PrettyVersions;
6-
use PHPUnit\Framework\TestCase;
76
use Sentry\Breadcrumb;
87
use Sentry\Event;
98
use Sentry\Integration\IntegrationInterface;
109
use Sentry\Options;
1110
use Sentry\SentryBundle\DependencyInjection\SentryExtension;
11+
use Sentry\SentryBundle\Test\BaseTestCase;
1212
use Symfony\Component\DependencyInjection\Alias;
1313
use Symfony\Component\DependencyInjection\Container;
1414
use Symfony\Component\DependencyInjection\ContainerBuilder;
@@ -17,7 +17,7 @@
1717
use Symfony\Component\HttpFoundation\RequestStack;
1818
use Symfony\Component\HttpKernel\Kernel;
1919

20-
class SentryExtensionTest extends TestCase
20+
class SentryExtensionTest extends BaseTestCase
2121
{
2222
private const OPTIONS_TEST_PUBLIC_ALIAS = 'sentry.options.public_alias';
2323

@@ -27,10 +27,10 @@ public function testDataProviderIsMappingTheRightNumberOfOptions(): void
2727
$supportedOptions = \array_unique(\array_column($providerData, 0));
2828

2929
// subtracted one is `integration`, which cannot be tested with the provider
30-
$expectedCount = ConfigurationTest::SUPPORTED_SENTRY_OPTIONS_COUNT - 1;
30+
$expectedCount = $this->getSupportedOptionsCount();
3131

32-
if (PrettyVersions::getVersion('sentry/sentry')->getPrettyVersion() !== '2.0.0') {
33-
++$expectedCount;
32+
if (PrettyVersions::getVersion('sentry/sentry')->getPrettyVersion() === '2.0.0') {
33+
--$expectedCount;
3434
}
3535

3636
$this->assertCount(
@@ -138,6 +138,16 @@ public function optionsValueProvider(): array
138138
$options[] = ['capture_silenced_errors', true, 'shouldCaptureSilencedErrors'];
139139
}
140140

141+
if ($this->classSerializersAreSupported()) {
142+
$options['class_serializer'] = [
143+
'class_serializers',
144+
[
145+
self::class => __NAMESPACE__ . '\mockClassSerializer',
146+
],
147+
'getClassSerializers',
148+
];
149+
}
150+
141151
return $options;
142152
}
143153

@@ -375,6 +385,11 @@ function mockBeforeBreadcrumb(Breadcrumb $breadcrumb): ?Breadcrumb
375385
return null;
376386
}
377387

388+
function mockClassSerializer($object)
389+
{
390+
return ['value' => 'serialized_class'];
391+
}
392+
378393
class CallbackMock
379394
{
380395
public static function callback()

0 commit comments

Comments
 (0)