Skip to content

Commit f23fe9d

Browse files
authored
Merge pull request #64 from laravel/fix/unsigned-serializable-closures
[1.x] Fixes and tests unsigned closures
2 parents 1d62a02 + 937e135 commit f23fe9d

File tree

6 files changed

+87
-18
lines changed

6 files changed

+87
-18
lines changed

src/SerializableClosure.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,17 @@ public function getClosure()
6262
return $this->serializable->getClosure();
6363
}
6464

65+
/**
66+
* Create a new unsigned serializable closure instance.
67+
*
68+
* @param Closure $closure
69+
* @return \Laravel\SerializableClosure\UnsignedSerializableClosure
70+
*/
71+
public static function unsigned(Closure $closure)
72+
{
73+
return new UnsignedSerializableClosure($closure);
74+
}
75+
6576
/**
6677
* Sets the serializable closure secret key.
6778
*

src/Serializers/Native.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use Laravel\SerializableClosure\Support\ClosureStream;
1111
use Laravel\SerializableClosure\Support\ReflectionClosure;
1212
use Laravel\SerializableClosure\Support\SelfReference;
13+
use Laravel\SerializableClosure\UnsignedSerializableClosure;
1314
use ReflectionObject;
1415
use UnitEnum;
1516

@@ -379,7 +380,7 @@ protected function mapPointers(&$data)
379380

380381
$item = $property->getValue($data);
381382

382-
if ($item instanceof SerializableClosure || ($item instanceof SelfReference && $item->hash === $this->code['self'])) {
383+
if ($item instanceof SerializableClosure || $item instanceof UnsignedSerializableClosure || ($item instanceof SelfReference && $item->hash === $this->code['self'])) {
383384
$this->code['objects'][] = [
384385
'instance' => $data,
385386
'property' => $property,
@@ -452,7 +453,7 @@ protected function mapByReference(&$data)
452453
}
453454

454455
unset($value);
455-
} elseif (is_object($data) && ! $data instanceof SerializableClosure) {
456+
} elseif (is_object($data) && ! $data instanceof SerializableClosure && ! $data instanceof UnsignedSerializableClosure) {
456457
if (isset($this->scope[$data])) {
457458
$data = $this->scope[$data];
458459

tests/Datasets/Serializers.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
11
<?php
22

33
use Laravel\SerializableClosure\Serializers;
4+
use Laravel\SerializableClosure\UnsignedSerializableClosure;
45

56
dataset('serializers', function () {
6-
foreach ([Serializers\Native::class, Serializers\Signed::class] as $serializer) {
7-
yield (new ReflectionClass($serializer))->getShortName() => function () use ($serializer) {
7+
foreach ([Serializers\Native::class, Serializers\Signed::class, UnsignedSerializableClosure::class] as $serializer) {
8+
$serializerShortName = (new ReflectionClass($serializer))->getShortName();
9+
10+
if ($serializer != UnsignedSerializableClosure::class) {
11+
$serializerShortName = 'SerializableClosure > '.$serializerShortName;
12+
}
13+
14+
yield $serializerShortName => function () use ($serializer) {
815
$this->serializer = $serializer;
916
};
1017
}

tests/Pest.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use Laravel\SerializableClosure\SerializableClosure;
44
use Laravel\SerializableClosure\Serializers;
55
use Laravel\SerializableClosure\Support\ReflectionClosure;
6+
use Laravel\SerializableClosure\UnsignedSerializableClosure;
67

78
/*
89
|--------------------------------------------------------------------------
@@ -69,6 +70,9 @@ function s($closure)
6970
SerializableClosure::setSecretKey('secret');
7071
$closure = new SerializableClosure($closure);
7172
break;
73+
case UnsignedSerializableClosure::class:
74+
$closure = SerializableClosure::unsigned($closure);
75+
break;
7276
default:
7377
throw new Exception('Please use the [serializers] dataset.');
7478
}

tests/Php73Test.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,14 @@
33
use Laravel\SerializableClosure\Exceptions\PhpVersionNotSupportedException;
44
use Laravel\SerializableClosure\SerializableClosure;
55

6-
it('does not support PHP 7.3', function () {
6+
test('serializable closure does not support PHP 7.3', function () {
77
new SerializableClosure(function () {
88
return 'foo';
99
});
1010
})->throws(PhpVersionNotSupportedException::class);
11+
12+
test('unsigned serializable closure does not support PHP 7.3', function () {
13+
SerializableClosure::unsigned(function () {
14+
return 'foo';
15+
});
16+
})->throws(PhpVersionNotSupportedException::class);

tests/SerializerTest.php

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Laravel\SerializableClosure\SerializableClosure;
66
use Laravel\SerializableClosure\Serializers\Signed;
77
use Laravel\SerializableClosure\Support\ReflectionClosure;
8+
use Laravel\SerializableClosure\UnsignedSerializableClosure;
89
use Tests\Fixtures\Model;
910

1011
test('closure use return value', function () {
@@ -37,12 +38,18 @@
3738
return $data;
3839
});
3940

40-
$c = unserialize(serialize(new SerializableClosure(function () use ($a) {
41-
return $a;
42-
})));
41+
if ($this->serializer == UnsignedSerializableClosure::class) {
42+
$c = unserialize(serialize(SerializableClosure::unsigned(function () use ($a) {
43+
return $a;
44+
})));
45+
} else {
46+
$c = unserialize(serialize(new SerializableClosure(function () use ($a) {
47+
return $a;
48+
})));
49+
}
4350

4451
expect($c())->toEqual(50);
45-
})->skip((float) phpversion() < '7.4');
52+
})->with('serializers')->skip((float) phpversion() < '7.4');
4653

4754
test('closure use transformation with Signed', function () {
4855
$a = 100;
@@ -64,12 +71,18 @@
6471
return $data;
6572
});
6673

67-
$c = unserialize(serialize(new SerializableClosure(function () use ($a) {
68-
return $a;
69-
})));
74+
if ($this->serializer == UnsignedSerializableClosure::class) {
75+
$c = unserialize(serialize(SerializableClosure::unsigned(function () use ($a) {
76+
return $a;
77+
})));
78+
} else {
79+
$c = unserialize(serialize(new SerializableClosure(function () use ($a) {
80+
return $a;
81+
})));
82+
}
7083

7184
expect($c())->toEqual(50);
72-
})->skip((float) phpversion() < '7.4');
85+
})->with('serializers')->skip((float) phpversion() < '7.4');
7386

7487
test('closure use return closure', function () {
7588
$a = function ($p) {
@@ -204,7 +217,6 @@
204217

205218
test('closure nested', function () {
206219
$o = function ($a) {
207-
208220
// this should never happen
209221
if ($a === false) {
210222
return false;
@@ -330,7 +342,7 @@ function () {
330342
expect($r[1])->toEqual($b);
331343
})->with('serializers');
332344

333-
test('serialization string content dont change', function () {
345+
test('serializable closure serialization string content dont change', function () {
334346
$a = 100;
335347

336348
SerializableClosure::setSecretKey('foo');
@@ -349,16 +361,41 @@ function () {
349361
);
350362
});
351363

364+
test('unsigned serializable closure serialization string content dont change', function () {
365+
$a = 100;
366+
367+
SerializableClosure::setSecretKey('foo');
368+
369+
$c = SerializableClosure::unsigned(function () use ($a) {
370+
return $a;
371+
});
372+
373+
$actual = explode('s:32:', serialize($c))[0];
374+
375+
expect($actual)->toBe(<<<OEF
376+
O:55:"Laravel\SerializableClosure\UnsignedSerializableClosure":1:{s:12:"serializable";O:46:"Laravel\SerializableClosure\Serializers\Native":5:{s:3:"use";a:1:{s:1:"a";i:100;}s:8:"function";s:47:"function () use (\$a) {
377+
return \$a;
378+
}";s:5:"scope";s:22:"P\Tests\SerializerTest";s:4:"this";N;s:4:"self";
379+
OEF
380+
);
381+
});
382+
352383
test('use objects with serializable closures properties', function () {
353384
$a = new stdClass();
354385

355386
if ($this->serializer == Signed::class) {
356387
SerializableClosure::setSecretKey('secret');
357388
}
358389

359-
$a->b = new SerializableClosure(function () {
360-
return 'Hi';
361-
});
390+
if ($this->serializer == UnsignedSerializableClosure::class) {
391+
$a->b = SerializableClosure::unsigned(function () {
392+
return 'Hi';
393+
});
394+
} else {
395+
$a->b = new SerializableClosure(function () {
396+
return 'Hi';
397+
});
398+
}
362399

363400
$closure = function () use ($a) {
364401
return ($a->b)();
@@ -459,8 +496,11 @@ public function aPublic()
459496
class A2
460497
{
461498
private $phrase = 'Hello, World!';
499+
462500
private $closure1;
501+
463502
private $closure2;
503+
464504
private $closure3;
465505

466506
public function __construct()

0 commit comments

Comments
 (0)