testWillInterceptAndReturnEarlyOnVoidMethod()   A
last analyzed

Complexity

Conditions 3
Paths 1

Size

Total Lines 50

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 50
rs 9.0909
c 0
b 0
f 0
cc 3
nc 1
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace ProxyManagerTest\Functional;
6
7
use PHPUnit\Framework\ExpectationFailedException;
8
use PHPUnit\Framework\TestCase;
9
use ProxyManager\Configuration;
10
use ProxyManager\Factory\AccessInterceptorScopeLocalizerFactory;
11
use ProxyManager\Proxy\AccessInterceptorInterface;
12
use ProxyManager\ProxyGenerator\Util\Properties;
13
use ProxyManagerTest\Assert;
14
use ProxyManagerTestAsset\BaseClass;
15
use ProxyManagerTestAsset\CallableInterface;
16
use ProxyManagerTestAsset\ClassWithCounterConstructor;
17
use ProxyManagerTestAsset\ClassWithDynamicArgumentsMethod;
18
use ProxyManagerTestAsset\ClassWithMethodWithByRefVariadicFunction;
19
use ProxyManagerTestAsset\ClassWithMethodWithVariadicFunction;
20
use ProxyManagerTestAsset\ClassWithParentHint;
21
use ProxyManagerTestAsset\ClassWithPublicArrayPropertyAccessibleViaMethod;
22
use ProxyManagerTestAsset\ClassWithPublicProperties;
23
use ProxyManagerTestAsset\ClassWithSelfHint;
24
use ProxyManagerTestAsset\EmptyClass;
25
use ProxyManagerTestAsset\VoidCounter;
26
use ReflectionClass;
27
use stdClass;
28
use function array_values;
29
use function get_class;
30
use function random_int;
31
use function serialize;
32
use function uniqid;
33
use function unserialize;
34
35
/**
36
 * Tests for {@see \ProxyManager\ProxyGenerator\AccessInterceptorScopeLocalizerGenerator} produced objects
37
 *
38
 * @group Functional
39
 * @coversNothing
40
 */
41
final class AccessInterceptorScopeLocalizerFunctionalTest extends TestCase
42
{
43
    /**
44
     * @param mixed[] $params
45
     * @param mixed   $expectedValue
46
     *
47
     * @dataProvider getProxyMethods
48
     */
49
    public function testMethodCalls(object $instance, string $method, array $params, $expectedValue) : void
50
    {
51
        $proxy = (new AccessInterceptorScopeLocalizerFactory())->createProxy($instance);
52
53
        $this->assertProxySynchronized($instance, $proxy);
54
55
        $callback = [$proxy, $method];
56
57
        self::assertIsCallable($callback);
0 ignored issues
show
Bug introduced by
The method assertIsCallable() does not seem to exist on object<ProxyManagerTest\...ocalizerFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
58
        self::assertSame($expectedValue, $callback(...array_values($params)));
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ocalizerFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
59
60
        $listener = $this->createMock(CallableInterface::class);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $listener is correct as $this->createMock(\Proxy...llableInterface::class) (which targets PHPUnit\Framework\TestCase::createMock()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
61
        $listener
0 ignored issues
show
Bug introduced by
The method expects cannot be called on $listener (of type null).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
62
            ->expects(self::once())
0 ignored issues
show
Bug introduced by
The method once() does not seem to exist on object<ProxyManagerTest\...ocalizerFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
63
            ->method('__invoke')
64
            ->with($proxy, $proxy, $method, $params, false);
65
66
        $proxy->setMethodPrefixInterceptor(
67
            $method,
68
            static function (
69
                AccessInterceptorInterface $proxy,
70
                object $instance,
71
                string $method,
72
                array $params,
73
                bool & $returnEarly
74
            ) use ($listener) : void {
75
                $listener->__invoke($proxy, $instance, $method, $params, $returnEarly);
0 ignored issues
show
Bug introduced by
The method __invoke cannot be called on $listener (of type null).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
76
            }
77
        );
78
79
        self::assertSame($expectedValue, $callback(...array_values($params)));
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ocalizerFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
80
81
        $random = uniqid('', true);
82
83
        $proxy->setMethodPrefixInterceptor(
84
            $method,
85
            static function (
86
                AccessInterceptorInterface $proxy,
87
                object $instance,
88
                string $method,
89
                array $params,
90
                bool & $returnEarly
91
            ) use ($random) : string {
92
                $returnEarly = true;
93
94
                return $random;
95
            }
96
        );
97
98
        self::assertSame($random, $callback(...array_values($params)));
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ocalizerFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
99
100
        $this->assertProxySynchronized($instance, $proxy);
101
    }
102
103
    /**
104
     * @param mixed[] $params
105
     * @param mixed   $expectedValue
106
     *
107
     * @dataProvider getProxyMethods
108
     */
109
    public function testMethodCallsWithSuffixListener(
110
        object $instance,
111
        string $method,
112
        array $params,
113
        $expectedValue
114
    ) : void {
115
        $proxy    = (new AccessInterceptorScopeLocalizerFactory())->createProxy($instance);
116
        $callback = [$proxy, $method];
117
118
        self::assertIsCallable($callback);
0 ignored issues
show
Bug introduced by
The method assertIsCallable() does not seem to exist on object<ProxyManagerTest\...ocalizerFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
119
120
        $listener = $this->createMock(CallableInterface::class);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $listener is correct as $this->createMock(\Proxy...llableInterface::class) (which targets PHPUnit\Framework\TestCase::createMock()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
121
        $listener
0 ignored issues
show
Bug introduced by
The method expects cannot be called on $listener (of type null).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
122
            ->expects(self::once())
0 ignored issues
show
Bug introduced by
The method once() does not seem to exist on object<ProxyManagerTest\...ocalizerFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
123
            ->method('__invoke')
124
            ->with($proxy, $proxy, $method, $params, $expectedValue, false);
125
126
        $proxy->setMethodSuffixInterceptor(
127
            $method,
128
            /** @param mixed $returnValue */
129
            static function (
130
                AccessInterceptorInterface $proxy,
131
                object $instance,
132
                string $method,
133
                array $params,
134
                $returnValue,
135
                bool & $returnEarly
136
            ) use ($listener) : void {
137
                $listener->__invoke($proxy, $instance, $method, $params, $returnValue, $returnEarly);
0 ignored issues
show
Bug introduced by
The method __invoke cannot be called on $listener (of type null).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
138
            }
139
        );
140
141
        self::assertSame($expectedValue, $callback(...array_values($params)));
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ocalizerFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
142
143
        $random = uniqid('', true);
144
145
        $proxy->setMethodSuffixInterceptor(
146
            $method,
147
            /** @param mixed $returnValue */
148
            static function (
149
                AccessInterceptorInterface $proxy,
150
                object $instance,
151
                string $method,
152
                array $params,
153
                $returnValue,
154
                bool & $returnEarly
155
            ) use ($random) : string {
156
                $returnEarly = true;
157
158
                return $random;
159
            }
160
        );
161
162
        self::assertSame($random, $callback(...array_values($params)));
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ocalizerFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
163
164
        $this->assertProxySynchronized($instance, $proxy);
165
    }
166
167
    /**
168
     * @param mixed[] $params
169
     * @param mixed   $expectedValue
170
     *
171
     * @dataProvider getProxyMethods
172
     */
173
    public function testMethodCallsAfterUnSerialization(
174
        object $instance,
175
        string $method,
176
        array $params,
177
        $expectedValue
178
    ) : void {
179
        /** @var AccessInterceptorInterface $proxy */
180
        $proxy = unserialize(serialize((new AccessInterceptorScopeLocalizerFactory())->createProxy($instance)));
181
182
        $callback = [$proxy, $method];
183
184
        self::assertIsCallable($callback);
0 ignored issues
show
Bug introduced by
The method assertIsCallable() does not seem to exist on object<ProxyManagerTest\...ocalizerFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
185
        self::assertSame($expectedValue, $callback(...array_values($params)));
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ocalizerFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
186
        $this->assertProxySynchronized($instance, $proxy);
187
    }
188
189
    /**
190
     * @param mixed[] $params
191
     * @param mixed   $expectedValue
192
     *
193
     * @dataProvider getProxyMethods
194
     */
195
    public function testMethodCallsAfterCloning(
196
        object $instance,
197
        string $method,
198
        array $params,
199
        $expectedValue
200
    ) : void {
201
        $proxy    = (new AccessInterceptorScopeLocalizerFactory())->createProxy($instance);
202
        $cloned   = clone $proxy;
203
        $callback = [$cloned, $method];
204
205
        $this->assertProxySynchronized($instance, $proxy);
206
        self::assertIsCallable($callback);
0 ignored issues
show
Bug introduced by
The method assertIsCallable() does not seem to exist on object<ProxyManagerTest\...ocalizerFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
207
        self::assertSame($expectedValue, $callback(...array_values($params)));
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ocalizerFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
208
        $this->assertProxySynchronized($instance, $proxy);
209
    }
210
211
    /**
212
     * @param mixed $propertyValue
213
     *
214
     * @dataProvider getPropertyAccessProxies
215
     */
216
    public function testPropertyReadAccess(
217
        object $instance,
218
        AccessInterceptorInterface $proxy,
219
        string $publicProperty,
220
        $propertyValue
221
    ) : void {
222
        self::assertSame($propertyValue, $proxy->$publicProperty);
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ocalizerFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
223
        $this->assertProxySynchronized($instance, $proxy);
224
    }
225
226
    /**
227
     * @dataProvider getPropertyAccessProxies
228
     */
229
    public function testPropertyWriteAccess(object $instance, AccessInterceptorInterface $proxy, string $publicProperty) : void
230
    {
231
        $newValue               = uniqid('value', true);
232
        $proxy->$publicProperty = $newValue;
233
234
        self::assertSame($newValue, $proxy->$publicProperty);
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ocalizerFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
235
        $this->assertProxySynchronized($instance, $proxy);
236
    }
237
238
    /**
239
     * @dataProvider getPropertyAccessProxies
240
     */
241
    public function testPropertyExistence(object $instance, AccessInterceptorInterface $proxy, string $publicProperty) : void
242
    {
243
        self::assertSame(isset($instance->$publicProperty), isset($proxy->$publicProperty));
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ocalizerFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
244
        $this->assertProxySynchronized($instance, $proxy);
245
246
        $instance->$publicProperty = null;
247
        self::assertFalse(isset($proxy->$publicProperty));
0 ignored issues
show
Bug introduced by
The method assertFalse() does not seem to exist on object<ProxyManagerTest\...ocalizerFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
248
        $this->assertProxySynchronized($instance, $proxy);
249
    }
250
251
    /**
252
     * @dataProvider getPropertyAccessProxies
253
     */
254
    public function testPropertyUnset(object $instance, AccessInterceptorInterface $proxy, string $publicProperty) : void
255
    {
256
        self::markTestSkipped('It is currently not possible to synchronize properties un-setting');
0 ignored issues
show
Bug introduced by
The method markTestSkipped() does not seem to exist on object<ProxyManagerTest\...ocalizerFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
257
        unset($proxy->$publicProperty);
258
259
        self::assertFalse(isset($instance->$publicProperty));
0 ignored issues
show
Bug introduced by
The method assertFalse() does not seem to exist on object<ProxyManagerTest\...ocalizerFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
260
        self::assertFalse(isset($proxy->$publicProperty));
0 ignored issues
show
Bug introduced by
The method assertFalse() does not seem to exist on object<ProxyManagerTest\...ocalizerFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
261
        $this->assertProxySynchronized($instance, $proxy);
262
    }
263
264
    /**
265
     * Verifies that accessing a public property containing an array behaves like in a normal context
266
     */
267
    public function testCanWriteToArrayKeysInPublicProperty() : void
268
    {
269
        $instance = new ClassWithPublicArrayPropertyAccessibleViaMethod();
270
        $proxy    = (new AccessInterceptorScopeLocalizerFactory())->createProxy($instance);
271
272
        $proxy->arrayProperty['foo'] = 'bar';
273
274
        self::assertSame('bar', $proxy->getArrayProperty()['foo']);
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ocalizerFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
275
276
        $proxy->arrayProperty = ['tab' => 'taz'];
277
278
        self::assertSame(['tab' => 'taz'], $proxy->arrayProperty);
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ocalizerFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
279
280
        $this->assertProxySynchronized($instance, $proxy);
0 ignored issues
show
Documentation introduced by
$instance is of type object<ProxyManagerTestA...rtyAccessibleViaMethod>, but the function expects a object<ProxyManagerTest\Functional\object>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
281
    }
282
283
    /**
284
     * Verifies that public properties retrieved via `__get` don't get modified in the object state
285
     */
286
    public function testWillNotModifyRetrievedPublicProperties() : void
287
    {
288
        $instance = new ClassWithPublicProperties();
289
        $proxy    = (new AccessInterceptorScopeLocalizerFactory())->createProxy($instance);
290
291
        $variable = $proxy->property0;
292
293
        self::assertByRefVariableValueSame('property0', $variable);
294
295
        $variable = 'foo';
296
297
        self::assertSame('property0', $proxy->property0);
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ocalizerFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
298
299
        $this->assertProxySynchronized($instance, $proxy);
0 ignored issues
show
Documentation introduced by
$instance is of type object<ProxyManagerTestA...ssWithPublicProperties>, but the function expects a object<ProxyManagerTest\Functional\object>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
300
301
        self::assertByRefVariableValueSame('foo', $variable);
302
    }
303
304
    /**
305
     * Verifies that public properties references retrieved via `__get` modify in the object state
306
     */
307
    public function testWillModifyByRefRetrievedPublicProperties() : void
308
    {
309
        $instance = new ClassWithPublicProperties();
310
        $proxy    = (new AccessInterceptorScopeLocalizerFactory())->createProxy($instance);
311
312
        $variable = & $proxy->property0;
313
314
        self::assertByRefVariableValueSame('property0', $variable);
315
316
        $variable = 'foo';
317
318
        self::assertSame('foo', $proxy->property0);
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ocalizerFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
319
320
        $this->assertProxySynchronized($instance, $proxy);
0 ignored issues
show
Documentation introduced by
$instance is of type object<ProxyManagerTestA...ssWithPublicProperties>, but the function expects a object<ProxyManagerTest\Functional\object>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
321
322
        self::assertByRefVariableValueSame('foo', $variable);
323
    }
324
325
    /**
326
     * @group 115
327
     * @group 175
328
     */
329
    public function testWillBehaveLikeObjectWithNormalConstructor() : void
330
    {
331
        $instance = new ClassWithCounterConstructor(10);
332
333
        self::assertSame(10, $instance->amount, 'Verifying that test asset works as expected');
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ocalizerFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
334
        self::assertSame(10, $instance->getAmount(), 'Verifying that test asset works as expected');
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ocalizerFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
335
        $instance->__construct(3);
336
        self::assertSame(13, $instance->amount, 'Verifying that test asset works as expected');
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ocalizerFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
337
        self::assertSame(13, $instance->getAmount(), 'Verifying that test asset works as expected');
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ocalizerFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
338
339
        $proxyName = get_class(
340
            (new AccessInterceptorScopeLocalizerFactory())
341
                ->createProxy(new ClassWithCounterConstructor(0))
342
        );
343
344
        $proxy = new $proxyName(15);
345
346
        self::assertSame(15, $proxy->amount, 'Verifying that the proxy constructor works as expected');
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ocalizerFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
347
        self::assertSame(15, $proxy->getAmount(), 'Verifying that the proxy constructor works as expected');
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ocalizerFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
348
        $proxy->__construct(5);
349
        self::assertSame(20, $proxy->amount, 'Verifying that the proxy constructor works as expected');
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ocalizerFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
350
        self::assertSame(20, $proxy->getAmount(), 'Verifying that the proxy constructor works as expected');
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ocalizerFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
351
    }
352
353
    /**
354
     * Generates a list of object | invoked method | parameters | expected result
355
     *
356
     * @return array<int, array<object|array<string, mixed>|string>>
0 ignored issues
show
Documentation introduced by
The doc-type array<int, could not be parsed: Expected ">" at position 5, but found "end of type". (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
357
     */
358
    public static function getProxyMethods() : array
359
    {
360
        $selfHintParam = new ClassWithSelfHint();
361
        $empty         = new EmptyClass();
362
363
        return [
364
            [
365
                new BaseClass(),
366
                'publicMethod',
367
                [],
368
                'publicMethodDefault',
369
            ],
370
            [
371
                new BaseClass(),
372
                'publicTypeHintedMethod',
373
                ['param' => new stdClass()],
374
                'publicTypeHintedMethodDefault',
375
            ],
376
            [
377
                new BaseClass(),
378
                'publicByReferenceMethod',
379
                [],
380
                'publicByReferenceMethodDefault',
381
            ],
382
            [
383
                new ClassWithSelfHint(),
384
                'selfHintMethod',
385
                ['parameter' => $selfHintParam],
386
                $selfHintParam,
387
            ],
388
            [
389
                new ClassWithParentHint(),
390
                'parentHintMethod',
391
                ['parameter' => $empty],
392
                $empty,
393
            ],
394
        ];
395
    }
396
397
    /**
398
     * Generates proxies and instances with a public property to feed to the property accessor methods
399
     *
400
     * @return array<int, array<int, object|AccessInterceptorInterface|string>>
0 ignored issues
show
Documentation introduced by
The doc-type array<int, could not be parsed: Expected ">" at position 5, but found "end of type". (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
401
     */
402
    public function getPropertyAccessProxies() : array
403
    {
404
        $instance = new BaseClass();
405
406
        return [
407
            [
408
                $instance,
409
                (new AccessInterceptorScopeLocalizerFactory())->createProxy($instance),
410
                'publicProperty',
411
                'publicPropertyDefault',
412
            ],
413
        ];
414
    }
415
416
    private function assertProxySynchronized(object $instance, AccessInterceptorInterface $proxy) : void
417
    {
418
        $reflectionClass = new ReflectionClass($instance);
419
420
        foreach (Properties::fromReflectionClass($reflectionClass)->getInstanceProperties() as $property) {
421
            $property->setAccessible(true);
422
423
            self::assertSame(
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ocalizerFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
424
                $property->getValue($instance),
425
                $property->getValue($proxy),
426
                'Property "' . $property->getName() . '" is synchronized between instance and proxy'
427
            );
428
        }
429
    }
430
431
    public function testWillForwardVariadicArguments() : void
432
    {
433
        $configuration = new Configuration();
434
        $factory       = new AccessInterceptorScopeLocalizerFactory($configuration);
435
        $targetObject  = new ClassWithMethodWithVariadicFunction();
436
437
        $object = $factory->createProxy(
438
            $targetObject,
439
            [
440
                'bar' => static function () : string {
441
                    return 'Foo Baz';
442
                },
443
            ]
444
        );
445
446
        self::assertNull($object->bar);
0 ignored issues
show
Bug introduced by
The method assertNull() does not seem to exist on object<ProxyManagerTest\...ocalizerFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
447
        self::assertNull($object->baz);
0 ignored issues
show
Bug introduced by
The method assertNull() does not seem to exist on object<ProxyManagerTest\...ocalizerFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
448
449
        $object->foo('Ocramius', 'Malukenho', 'Danizord');
450
        self::assertSame('Ocramius', $object->bar);
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ocalizerFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
451
        self::assertSame(['Malukenho', 'Danizord'], Assert::readAttribute($object, 'baz'));
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ocalizerFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
452
    }
453
454
    /**
455
     * @group 265
456
     */
457
    public function testWillForwardVariadicByRefArguments() : void
458
    {
459
        $configuration = new Configuration();
460
        $factory       = new AccessInterceptorScopeLocalizerFactory($configuration);
461
        $targetObject  = new ClassWithMethodWithByRefVariadicFunction();
462
463
        $object = $factory->createProxy(
464
            $targetObject,
465
            [
466
                'bar' => static function () : string {
467
                    return 'Foo Baz';
468
                },
469
            ]
470
        );
471
472
        $parameters = ['a', 'b', 'c'];
473
474
        // first, testing normal variadic behavior (verifying we didn't screw up in the test asset)
475
        self::assertSame(['a', 'changed', 'c'], (new ClassWithMethodWithByRefVariadicFunction())->tuz(...$parameters));
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ocalizerFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
476
        self::assertSame(['a', 'changed', 'c'], $object->tuz(...$parameters));
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ocalizerFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
477
        self::assertSame(['a', 'changed', 'c'], $parameters, 'by-ref variadic parameter was changed');
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ocalizerFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
478
    }
479
480
    /**
481
     * This test documents a known limitation: `func_get_args()` (and similar) don't work in proxied APIs.
482
     * If you manage to make this test pass, then please do send a patch
483
     *
484
     * @group 265
485
     */
486
    public function testWillNotForwardDynamicArguments() : void
487
    {
488
        $object = (new AccessInterceptorScopeLocalizerFactory())
489
            ->createProxy(
490
                new ClassWithDynamicArgumentsMethod(),
491
                [
492
                    'dynamicArgumentsMethod' => static function () : string {
493
                        return 'Foo Baz';
494
                    },
495
                ]
496
            );
497
498
        self::assertSame(['a', 'b'], (new ClassWithDynamicArgumentsMethod())->dynamicArgumentsMethod('a', 'b'));
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ocalizerFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
499
500
        $this->expectException(ExpectationFailedException::class);
0 ignored issues
show
Bug introduced by
The method expectException() does not seem to exist on object<ProxyManagerTest\...ocalizerFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
501
502
        self::assertSame(['a', 'b'], $object->dynamicArgumentsMethod('a', 'b'));
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ocalizerFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
503
    }
504
505
    /**
506
     * @group 327
507
     */
508
    public function testWillInterceptAndReturnEarlyOnVoidMethod() : void
509
    {
510
        $skip      = random_int(100, 200);
511
        $addMore   = random_int(201, 300);
512
        $increment = random_int(301, 400);
513
514
        $object = (new AccessInterceptorScopeLocalizerFactory())
515
            ->createProxy(
516
                new VoidCounter(),
517
                [
518
                    'increment' => static function (
519
                        AccessInterceptorInterface $proxy,
520
                        VoidCounter $instance,
521
                        string $method,
522
                        array $params,
523
                        ?bool & $returnEarly
524
                    ) use ($skip) : void {
525
                        if ($skip !== $params['amount']) {
526
                            return;
527
                        }
528
529
                        $returnEarly = true;
530
                    },
531
                ],
532
                [
533
                    'increment' => static function (
534
                        AccessInterceptorInterface $proxy,
535
                        VoidCounter $instance,
536
                        string $method,
537
                        array $params,
538
                        ?bool & $returnEarly
0 ignored issues
show
Unused Code introduced by
The parameter $returnEarly is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
539
                    ) use ($addMore) : void {
540
                        if ($addMore !== $params['amount']) {
541
                            return;
542
                        }
543
544
                        $instance->counter += 1;
545
                    },
546
                ]
547
            );
548
549
        $object->increment($skip);
550
        self::assertSame(0, $object->counter);
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ocalizerFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
551
552
        $object->increment($increment);
553
        self::assertSame($increment, $object->counter);
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ocalizerFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
554
555
        $object->increment($addMore);
556
        self::assertSame($increment + $addMore + 1, $object->counter);
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ocalizerFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
557
    }
558
559
    /**
560
     * @param mixed $expected
561
     * @param mixed $actual
562
     *
563
     * @psalm-template ExpectedType
564
     * @psalm-param ExpectedType $expected
565
     * @psalm-assert ExpectedType $actual
566
     */
567
    private static function assertByRefVariableValueSame($expected, & $actual) : void
568
    {
569
        self::assertSame($expected, $actual);
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ocalizerFunctionalTest>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
570
    }
571
}
572