Skip to content

Commit

Permalink
Fix case when SerializableClosure uses as class property
Browse files Browse the repository at this point in the history
  • Loading branch information
Dry7 committed Jun 30, 2024
1 parent d715a63 commit 1d33df7
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 5 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
composer.lock
/phpunit.xml
.phpunit.result.cache
.idea
26 changes: 21 additions & 5 deletions src/Serializers/Native.php
Original file line number Diff line number Diff line change
Expand Up @@ -194,15 +194,31 @@ public function __unserialize($data)

$this->closure = $this->closure->bindTo($this->code['this'], $this->code['scope']);

if (! empty($this->code['objects'])) {
foreach ($this->code['objects'] as $item) {
$item['property']->setValue($item['instance'], $item['object']->getClosure());
}
}
$this->bindObjectsIfNeeded();

$this->code = $this->code['function'];
}

private function bindObjectsIfNeeded() {
if (!empty($this->code['objects'])) {
$this->bindObjects();
}
}

private function bindObjects() {
foreach ($this->code['objects'] as $item) {
$item['property']->setValue($item['instance'], $this->calculateObjectValue($item));
}
}

private function calculateObjectValue($item) {
return $this->isSerializableClosure($item['object']) ? $item['object'] : $item['object']->getClosure();
}

private function isSerializableClosure($object): bool {
return $object instanceof SerializableClosure || $object instanceof UnsignedSerializableClosure;
}

/**
* Ensures the given closures are serializable.
*
Expand Down
14 changes: 14 additions & 0 deletions tests/Fixtures/ClassWithPublicProperty.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

declare(strict_types=1);

namespace Tests\Fixtures;

class ClassWithPublicProperty {
public $closure;

public function __construct($closure)
{
$this->closure = $closure;
}
}
27 changes: 27 additions & 0 deletions tests/SerializerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Laravel\SerializableClosure\Serializers\Signed;
use Laravel\SerializableClosure\Support\ReflectionClosure;
use Laravel\SerializableClosure\UnsignedSerializableClosure;
use Tests\Fixtures\ClassWithPublicProperty;
use Tests\Fixtures\Model;

test('closure with simple const', function () {
Expand Down Expand Up @@ -485,6 +486,32 @@ function () {
new CarbonImmutable,
]);

test('SerializableClosure in the class property', function () {
SerializableClosure::setSecretKey('foo');

$innerClosure = new ClassWithPublicProperty(new SerializableClosure(function () {}));
$outerClosure = new SerializableClosure(function () use ($innerClosure) {
return $innerClosure->closure;
});

$unSerializedOuterClosure = unserialize(serialize($outerClosure));

expect($outerClosure())->toBeInstanceOf(SerializableClosure::class);
expect($unSerializedOuterClosure())->toBeInstanceOf(SerializableClosure::class);
});

test('UnsignedSerializableClosure in the class property', function () {
$innerClosure = new ClassWithPublicProperty(SerializableClosure::unsigned(function () {}));
$outerClosure = SerializableClosure::unsigned(function () use ($innerClosure) {
return $innerClosure->closure;
});

$unSerializedOuterClosure = unserialize(serialize($outerClosure));

expect($outerClosure())->toBeInstanceOf(UnsignedSerializableClosure::class);
expect($unSerializedOuterClosure())->toBeInstanceOf(UnsignedSerializableClosure::class);
});

function serializer_php_74_switch_statement_test_is_two($a)
{
return $a === 2;
Expand Down

0 comments on commit 1d33df7

Please sign in to comment.