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 c5f82d0
Show file tree
Hide file tree
Showing 4 changed files with 70 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
30 changes: 25 additions & 5 deletions src/Serializers/Native.php
Original file line number Diff line number Diff line change
Expand Up @@ -194,15 +194,35 @@ 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
15 changes: 15 additions & 0 deletions tests/Fixtures/ClassWithPublicProperty.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace Tests\Fixtures;

class ClassWithPublicProperty
{
public $closure;

public function __construct($closure)
{
$this->closure = $closure;
}
}
29 changes: 29 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,34 @@ 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 c5f82d0

Please sign in to comment.