Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle string callable in case of non-static method #821

Merged
merged 16 commits into from
Oct 14, 2019
Merged
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## Unreleased

- Fix deprecation raised when serializing callable in certain circumstances (#821)

## 2.2.0 (2019-09-23)

- Change type hint for both parameter and return value of `HubInterface::getCurrentHub` and `HubInterface::setCurrentHub()` methods (#849)
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@
},
"extra": {
"branch-alias": {
"dev-develop": "2.2-dev"
"dev-develop": "2.3-dev"
Jean85 marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
51 changes: 47 additions & 4 deletions src/Serializer/AbstractSerializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

namespace Sentry\Serializer;

use Sentry\Exception\InvalidArgumentException;
use Sentry\Options;

/**
Expand Down Expand Up @@ -102,7 +103,7 @@ protected function serializeRecursively($value, int $_depth = 0)
}

if (\is_callable($value)) {
return $this->serializeCallable($value);
return $this->serializeCallableWithoutTypeHint($value);
}

if (\is_array($value)) {
Expand Down Expand Up @@ -250,7 +251,7 @@ protected function serializeValue($value)
}

if (\is_callable($value)) {
return $this->serializeCallable($value);
return $this->serializeCallableWithoutTypeHint($value);
}

if (\is_array($value)) {
Expand All @@ -261,17 +262,42 @@ protected function serializeValue($value)
}

/**
* This method is provided as a non-BC upgrade of serializeCallable,
* since using the callable type raises a deprecation in some cases.
*
* @param callable $callable
*
* @return string
*/
protected function serializeCallableWithoutTypeHint($callable): string
{
$this->assertIsValidCallable($callable);

if (\is_string($callable) && !\function_exists($callable)) {
return $callable;
}

return $this->serializeCallable($callable);
}

/**
* Use serializeCallableWithoutTypeHint instead (no type in argument).
*
* @see https://github.com/getsentry/sentry-php/pull/821
*
* @param callable $callable
*
* @return string
*/
protected function serializeCallable(callable $callable): string
protected function serializeCallable(/* callable type to be removed in 3.0, see #821 => */callable $callable): string
Jean85 marked this conversation as resolved.
Show resolved Hide resolved
{
$this->assertIsValidCallable($callable);

try {
if (\is_array($callable)) {
$reflection = new \ReflectionMethod($callable[0], $callable[1]);
$class = $reflection->getDeclaringClass();
} elseif ($callable instanceof \Closure || \is_string($callable)) {
} elseif ($callable instanceof \Closure || (\is_string($callable) && \function_exists($callable))) {
$reflection = new \ReflectionFunction($callable);
$class = null;
} elseif (\is_object($callable) && method_exists($callable, '__invoke')) {
Expand Down Expand Up @@ -357,4 +383,21 @@ public function getSerializeAllObjects(): bool
{
return $this->serializeAllObjects;
}

/**
* @param mixed $callable
*
* @throws InvalidArgumentException
*/
private function assertIsValidCallable($callable): void
Jean85 marked this conversation as resolved.
Show resolved Hide resolved
{
if (!\is_callable($callable)) {
throw new InvalidArgumentException(sprintf(
'Expecting callable, got %s',
\is_object($callable)
? \get_class($callable)
: \gettype($callable)
));
}
}
}
6 changes: 5 additions & 1 deletion tests/Serializer/AbstractSerializerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -455,13 +455,17 @@ public function serializableCallableProvider(): array
'callable' => $callableWithoutNamespaces,
'expected' => 'Lambda void {closure} [int|null param1_70ns]',
],
[
'callable' => __METHOD__,
'expected' => __METHOD__,
],
];
}

/**
* @dataProvider serializableCallableProvider
*/
public function testSerializeCallable(callable $callable, string $expected): void
public function testSerializeCallable($callable, string $expected): void
{
$serializer = $this->createSerializer();
$actual = $this->invokeSerialization($serializer, $callable);
Expand Down