Skip to content
This repository was archived by the owner on Jul 8, 2023. It is now read-only.

Commit 2df7604

Browse files
committed
Merge branch 'nullable-variadics' into master
2 parents 5fd6b64 + c9101a3 commit 2df7604

File tree

8 files changed

+123
-2
lines changed

8 files changed

+123
-2
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Phony changelog
22

3+
## 4.0.1 (2020-08-29)
4+
5+
- **[FIXED]** Nullable variadics can now be mocked ([#248] - thanks [@keksa]).
6+
7+
[#248]: https://github.com/eloquent/phony/issues/248
8+
39
## 4.0.0 (2019-12-31)
410

511
- **[BC BREAK]** PHP 7.1 is no longer supported.
@@ -592,6 +598,8 @@ and version constraint will need to be updated:
592598

593599
- **[NEW]** Initial implementation.
594600

601+
<!-- Contributors -->
602+
595603
[@jmalloc]: https://github.com/jmalloc
596604
[@keksa]: https://github.com/keksa
597605
[@pmall]: https://github.com/pmall

src/Reflection/FunctionSignatureInspector.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,15 @@ public function signature(ReflectionFunctionAbstract $function): array
9191
}
9292

9393
$byReference = $match[4];
94+
$isVariadic = $parameter->isVariadic();
9495

95-
if ($parameter->isVariadic()) {
96+
if ($isVariadic) {
9697
$variadic = '...';
9798
$optional = false;
99+
100+
if ($match[3]) {
101+
$typehint = '?' . $typehint;
102+
}
98103
} else {
99104
$variadic = '';
100105
$optional = 'optional' === $match[1];
@@ -107,7 +112,7 @@ public function signature(ReflectionFunctionAbstract $function): array
107112
$defaultValue = ' = ' .
108113
var_export($parameter->getDefaultValue(), true);
109114
}
110-
} elseif ($optional || $match[3]) {
115+
} elseif (!$isVariadic && ($optional || $match[3])) {
111116
$defaultValue = ' = null';
112117
} else {
113118
$defaultValue = '';
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?php
2+
3+
$functionName = 'functionName';
4+
$namespace = 'Foo\Bar';
5+
$callback = function ($a, $b, ?stdClass ...$c) {};
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
namespace Foo\Bar;
4+
5+
function functionName(
6+
$a0,
7+
$a1,
8+
?\stdClass ...$a2
9+
) {
10+
$argumentCount = \func_num_args();
11+
$arguments = [];
12+
13+
if ($argumentCount > 0) {
14+
$arguments[] = $a0;
15+
}
16+
if ($argumentCount > 1) {
17+
$arguments[] = $a1;
18+
}
19+
20+
for ($i = 2; $i < $argumentCount; ++$i) {
21+
$arguments[] = $a2[$i - 2];
22+
}
23+
24+
$name = 'foo\\bar\\functionname';
25+
26+
if (
27+
!isset(
28+
\Eloquent\Phony\Hook\FunctionHookManager::$hooks[$name]['callback']
29+
)
30+
) {
31+
return \functionName(...$arguments);
32+
}
33+
34+
$callback =
35+
\Eloquent\Phony\Hook\FunctionHookManager::$hooks[$name]['callback'];
36+
37+
if ($callback instanceof \Eloquent\Phony\Invocation\Invocable) {
38+
return $callback->invokeWith($arguments);
39+
}
40+
41+
return $callback(...$arguments);
42+
}

test/fixture/mock-generator/variadics/builder.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
'methodA' => function ($a, $b, ...$c) {},
66
'methodB' => function ($a, $b, stdClass ...$c) {},
77
'methodC' => function ($a, $b, &...$c) {},
8+
'methodD' => function ($a, $b, ?stdClass...$c) {},
89
]
910
);
1011

test/fixture/mock-generator/variadics/expected.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,38 @@ public function methodC(
101101
return $result;
102102
}
103103

104+
public function methodD(
105+
$a0,
106+
$a1,
107+
?\stdClass ...$a2
108+
) {
109+
$argumentCount = \func_num_args();
110+
$arguments = [];
111+
112+
if ($argumentCount > 0) {
113+
$arguments[] = $a0;
114+
}
115+
if ($argumentCount > 1) {
116+
$arguments[] = $a1;
117+
}
118+
119+
for ($i = 2; $i < $argumentCount; ++$i) {
120+
$arguments[] = $a2[$i - 2];
121+
}
122+
123+
if (!$this->_handle) {
124+
$result = null;
125+
126+
return $result;
127+
}
128+
129+
$result = $this->_handle->spy(__FUNCTION__)->invokeWith(
130+
new \Eloquent\Phony\Call\Arguments($arguments)
131+
);
132+
133+
return $result;
134+
}
135+
104136
private static $_uncallableMethods = [];
105137
private static $_traitMethods = [];
106138
private static $_customMethods = [];
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Eloquent\Phony\Test;
6+
7+
use stdClass;
8+
9+
interface TestInterfaceWithVariadicParameterWithNullableType
10+
{
11+
public function method(?stdClass ...$arguments);
12+
}

test/suite/FunctionalTest.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
use Eloquent\Phony\Test\TestInterfaceWithScalarTypeHint;
4646
use Eloquent\Phony\Test\TestInterfaceWithVariadicParameter;
4747
use Eloquent\Phony\Test\TestInterfaceWithVariadicParameterByReference;
48+
use Eloquent\Phony\Test\TestInterfaceWithVariadicParameterWithNullableType;
4849
use Eloquent\Phony\Test\TestInterfaceWithVariadicParameterWithType;
4950
use Eloquent\Phony\Test\TestInvocable;
5051
use Eloquent\Phony\Test\TestTraitA;
@@ -171,6 +172,21 @@ function () {
171172
$this->assertSame([$a, $b], $handle->get()->method($a, $b));
172173
}
173174

175+
public function testVariadicParameterMockingWithNullableType()
176+
{
177+
$handle = mock(TestInterfaceWithVariadicParameterWithNullableType::class);
178+
$handle->method->does(
179+
function () {
180+
return func_get_args();
181+
}
182+
);
183+
$a = (object) [];
184+
$b = null;
185+
$c = (object) [];
186+
187+
$this->assertSame([$a, $b, $c], $handle->get()->method($a, $b, $c));
188+
}
189+
174190
public function testVariadicParameterMockingByReference()
175191
{
176192
$handle = mock(TestInterfaceWithVariadicParameterByReference::class);

0 commit comments

Comments
 (0)