isPropertyInitialized()   A
last analyzed

Complexity

Conditions 3
Paths 1

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 9
rs 9.9666
c 0
b 0
f 0
cc 3
nc 1
nop 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace ProxyManagerTest\Functional;
6
7
use BadMethodCallException;
8
use Closure;
9
use PHPUnit\Framework\MockObject\MockObject as Mock;
10
use PHPUnit\Framework\TestCase;
11
use ProxyManager\Factory\LazyLoadingGhostFactory;
12
use ProxyManager\Proxy\GhostObjectInterface;
13
use ProxyManager\Proxy\LazyLoadingInterface;
14
use ProxyManager\ProxyGenerator\Util\Properties;
15
use ProxyManagerTestAsset\BaseClass;
16
use ProxyManagerTestAsset\CallableInterface;
17
use ProxyManagerTestAsset\ClassWithAbstractPublicMethod;
18
use ProxyManagerTestAsset\ClassWithCollidingPrivateInheritedProperties;
19
use ProxyManagerTestAsset\ClassWithCounterConstructor;
20
use ProxyManagerTestAsset\ClassWithDynamicArgumentsMethod;
21
use ProxyManagerTestAsset\ClassWithMethodWithByRefVariadicFunction;
22
use ProxyManagerTestAsset\ClassWithMethodWithVariadicFunction;
23
use ProxyManagerTestAsset\ClassWithMixedProperties;
24
use ProxyManagerTestAsset\ClassWithMixedPropertiesAndAccessorMethods;
25
use ProxyManagerTestAsset\ClassWithMixedTypedProperties;
26
use ProxyManagerTestAsset\ClassWithParentHint;
27
use ProxyManagerTestAsset\ClassWithPrivateProperties;
28
use ProxyManagerTestAsset\ClassWithProtectedProperties;
29
use ProxyManagerTestAsset\ClassWithPublicArrayProperty;
30
use ProxyManagerTestAsset\ClassWithPublicProperties;
31
use ProxyManagerTestAsset\ClassWithSelfHint;
32
use ProxyManagerTestAsset\EmptyClass;
33
use ProxyManagerTestAsset\OtherObjectAccessClass;
34
use ProxyManagerTestAsset\VoidCounter;
35
use ReflectionClass;
36
use ReflectionProperty;
37
use stdClass;
38
use function array_key_exists;
39
use function array_values;
40
use function get_class;
41
use function get_parent_class;
42
use function random_int;
43
use function serialize;
44
use function sprintf;
45
use function str_replace;
46
use function uniqid;
47
use function unserialize;
48
49
/**
50
 * Tests for {@see \ProxyManager\ProxyGenerator\LazyLoadingGhostGenerator} produced objects
51
 *
52
 * @group Functional
53
 * @coversNothing
54
 */
55
final class LazyLoadingGhostFunctionalTest extends TestCase
56
{
57
    /**
58
     * @param mixed[] $params
59
     * @param mixed   $expectedValue
60
     *
61
     * @dataProvider getProxyInitializingMethods
62
     *
63
     * @psalm-template OriginalClass
64
     * @psalm-param class-string<OriginalClass> $className
65
     * @psalm-param OriginalClass $instance
66
     */
67
    public function testMethodCallsThatLazyLoadTheObject(
68
        string $className,
69
        object $instance,
70
        string $method,
71
        array $params,
72
        $expectedValue
73
    ) : void {
74
        $proxy = (new LazyLoadingGhostFactory())
75
            ->createProxy($className, $this->createInitializer($className, $instance));
76
77
        self::assertFalse($proxy->isProxyInitialized());
0 ignored issues
show
Bug introduced by
The method assertFalse() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
78
79
        $callProxyMethod = [$proxy, $method];
80
        $parameterValues = array_values($params);
81
82
        self::assertIsCallable($callProxyMethod);
0 ignored issues
show
Bug introduced by
The method assertIsCallable() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
83
        self::assertSame($expectedValue, $callProxyMethod(...$parameterValues));
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
84
        self::assertTrue($proxy->isProxyInitialized());
0 ignored issues
show
Bug introduced by
The method assertTrue() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
85
    }
86
87
    /**
88
     * @param mixed[] $params
89
     * @param mixed   $expectedValue
90
     *
91
     * @dataProvider getProxyNonInitializingMethods
92
     *
93
     * @psalm-template OriginalClass
94
     * @psalm-param class-string<OriginalClass> $className
95
     * @psalm-param OriginalClass $instance
96
     */
97
    public function testMethodCallsThatDoNotLazyLoadTheObject(
98
        string $className,
99
        object $instance,
100
        string $method,
101
        array $params,
102
        $expectedValue
103
    ) : void {
104
        $initializeMatcher = $this->createMock(CallableInterface::class);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $initializeMatcher 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...
105
106
        $initializeMatcher->expects(self::never())->method('__invoke'); // should not initialize the proxy
0 ignored issues
show
Bug introduced by
The method never() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
Bug introduced by
The method expects cannot be called on $initializeMatcher (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...
107
108
        $proxy = (new LazyLoadingGhostFactory())->createProxy(
109
            $className,
110
            $this->createInitializer($className, $instance, $initializeMatcher)
111
        );
112
113
        self::assertFalse($proxy->isProxyInitialized());
0 ignored issues
show
Bug introduced by
The method assertFalse() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
114
115
        $callProxyMethod = [$proxy, $method];
116
        $parameterValues = array_values($params);
117
118
        self::assertIsCallable($callProxyMethod);
0 ignored issues
show
Bug introduced by
The method assertIsCallable() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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
        self::assertSame($expectedValue, $callProxyMethod(...$parameterValues));
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
120
        self::assertFalse($proxy->isProxyInitialized());
0 ignored issues
show
Bug introduced by
The method assertFalse() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
121
    }
122
123
    /**
124
     * @param mixed[] $params
125
     * @param mixed   $expectedValue
126
     *
127
     * @dataProvider getProxyMethods
128
     *
129
     * @psalm-template OriginalClass
130
     * @psalm-param class-string<OriginalClass> $className
131
     * @psalm-param OriginalClass $instance
132
     */
133
    public function testMethodCallsAfterUnSerialization(
134
        string $className,
135
        object $instance,
136
        string $method,
137
        array $params,
138
        $expectedValue
139
    ) : void {
140
        /** @var GhostObjectInterface $proxy */
141
        $proxy = unserialize(serialize((new LazyLoadingGhostFactory())->createProxy(
142
            $className,
143
            $this->createInitializer($className, $instance)
144
        )));
145
146
        self::assertTrue($proxy->isProxyInitialized());
0 ignored issues
show
Bug introduced by
The method assertTrue() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
147
148
        $callProxyMethod = [$proxy, $method];
149
        $parameterValues = array_values($params);
150
151
        self::assertIsCallable($callProxyMethod);
0 ignored issues
show
Bug introduced by
The method assertIsCallable() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
152
        self::assertSame($expectedValue, $callProxyMethod(...$parameterValues));
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
153
    }
154
155
    /**
156
     * @param mixed[] $params
157
     * @param mixed   $expectedValue
158
     *
159
     * @dataProvider getProxyMethods
160
     *
161
     * @psalm-template OriginalClass
162
     * @psalm-param class-string<OriginalClass> $className
163
     * @psalm-param OriginalClass $instance
164
     */
165
    public function testMethodCallsAfterCloning(
166
        string $className,
167
        object $instance,
168
        string $method,
169
        array $params,
170
        $expectedValue
171
    ) : void {
172
        $proxy  = (new LazyLoadingGhostFactory())->createProxy(
173
            $className,
174
            $this->createInitializer($className, $instance)
175
        );
176
        $cloned = clone $proxy;
177
178
        self::assertTrue($cloned->isProxyInitialized());
0 ignored issues
show
Bug introduced by
The method assertTrue() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
179
180
        $callProxyMethod = [$proxy, $method];
181
        $parameterValues = array_values($params);
182
183
        self::assertIsCallable($callProxyMethod);
0 ignored issues
show
Bug introduced by
The method assertIsCallable() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
184
        self::assertSame($expectedValue, $callProxyMethod(...$parameterValues));
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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
    }
186
187
    /**
188
     * @param mixed $propertyValue
189
     *
190
     * @dataProvider getPropertyAccessProxies
191
     */
192
    public function testPropertyReadAccess(
193
        object $instance,
0 ignored issues
show
Unused Code introduced by
The parameter $instance 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...
194
        GhostObjectInterface $proxy,
195
        string $publicProperty,
196
        $propertyValue
197
    ) : void {
198
        self::assertSame($propertyValue, $proxy->$publicProperty);
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
199
        self::assertTrue($proxy->isProxyInitialized());
0 ignored issues
show
Bug introduced by
The method assertTrue() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
200
    }
201
202
    /**
203
     * @dataProvider getPropertyAccessProxies
204
     */
205
    public function testPropertyWriteAccess(object $instance, GhostObjectInterface $proxy, string $publicProperty) : void
0 ignored issues
show
Unused Code introduced by
The parameter $instance 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...
206
    {
207
        $newValue               = uniqid('', true);
208
        $proxy->$publicProperty = $newValue;
209
210
        self::assertTrue($proxy->isProxyInitialized());
0 ignored issues
show
Bug introduced by
The method assertTrue() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
211
        self::assertSame($newValue, $proxy->$publicProperty);
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
212
    }
213
214
    /**
215
     * @dataProvider getPropertyAccessProxies
216
     */
217
    public function testPropertyExistence(object $instance, GhostObjectInterface $proxy, string $publicProperty) : void
218
    {
219
        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\...ingGhostFunctionalTest>.

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...
220
        self::assertTrue($proxy->isProxyInitialized());
0 ignored issues
show
Bug introduced by
The method assertTrue() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
221
    }
222
223
    /**
224
     * @dataProvider getPropertyAccessProxies
225
     */
226
    public function testPropertyAbsence(object $instance, GhostObjectInterface $proxy, string $publicProperty) : void
0 ignored issues
show
Unused Code introduced by
The parameter $instance 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...
227
    {
228
        $proxy->$publicProperty = null;
229
        self::assertFalse(isset($proxy->$publicProperty));
0 ignored issues
show
Bug introduced by
The method assertFalse() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
230
        self::assertTrue($proxy->isProxyInitialized());
0 ignored issues
show
Bug introduced by
The method assertTrue() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
231
    }
232
233
    /**
234
     * @dataProvider getPropertyAccessProxies
235
     */
236
    public function testPropertyUnset(object $instance, GhostObjectInterface $proxy, string $publicProperty) : void
237
    {
238
        unset($proxy->$publicProperty);
239
240
        self::assertTrue($proxy->isProxyInitialized());
0 ignored issues
show
Bug introduced by
The method assertTrue() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
241
        self::assertTrue(isset($instance->$publicProperty));
0 ignored issues
show
Bug introduced by
The method assertTrue() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
242
        self::assertFalse(isset($proxy->$publicProperty));
0 ignored issues
show
Bug introduced by
The method assertFalse() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
243
    }
244
245
    /**
246
     * Verifies that accessing a public property containing an array behaves like in a normal context
247
     */
248
    public function testCanWriteToArrayKeysInPublicProperty() : void
249
    {
250
        $proxy = (new LazyLoadingGhostFactory())->createProxy(
251
            ClassWithPublicArrayProperty::class,
252
            $this->createInitializer(ClassWithPublicArrayProperty::class, new ClassWithPublicArrayProperty())
0 ignored issues
show
Documentation introduced by
new \ProxyManagerTestAss...thPublicArrayProperty() is of type object<ProxyManagerTestA...ithPublicArrayProperty>, 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...
253
        );
254
255
        $proxy->arrayProperty['foo'] = 'bar';
256
257
        self::assertByRefVariableValueSame('bar', $proxy->arrayProperty['foo']);
258
259
        $proxy->arrayProperty = ['tab' => 'taz'];
260
261
        self::assertSame(['tab' => 'taz'], $proxy->arrayProperty);
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
262
    }
263
264
    /**
265
     * Verifies that public properties retrieved via `__get` don't get modified in the object itself
266
     */
267
    public function testWillNotModifyRetrievedPublicProperties() : void
268
    {
269
        $proxy    = (new LazyLoadingGhostFactory())->createProxy(
270
            ClassWithPublicProperties::class,
271
            $this->createInitializer(ClassWithPublicProperties::class, new ClassWithPublicProperties())
0 ignored issues
show
Documentation introduced by
new \ProxyManagerTestAss...sWithPublicProperties() 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...
272
        );
273
        $variable = $proxy->property0;
274
275
        self::assertByRefVariableValueSame('property0', $variable);
276
277
        $variable = 'foo';
278
279
        self::assertSame('property0', $proxy->property0);
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
280
        self::assertByRefVariableValueSame('foo', $variable);
281
    }
282
283
    /**
284
     * Verifies that public properties references retrieved via `__get` modify in the object state
285
     */
286
    public function testWillModifyByRefRetrievedPublicProperties() : void
287
    {
288
        $instance = new ClassWithPublicProperties();
289
        $proxy    = (new LazyLoadingGhostFactory())->createProxy(
290
            ClassWithPublicProperties::class,
291
            $this->createInitializer(ClassWithPublicProperties::class, $instance)
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...
292
        );
293
        $variable = & $proxy->property0;
294
295
        self::assertByRefVariableValueSame('property0', $variable);
296
297
        $variable = 'foo';
298
299
        self::assertSame('foo', $proxy->property0);
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
300
        self::assertByRefVariableValueSame('foo', $variable);
301
    }
302
303
    public function testKeepsInitializerWhenNotOverwitten() : void
304
    {
305
        $initializer = static function () : bool {
306
            return true;
307
        };
308
309
        $proxy = (new LazyLoadingGhostFactory())->createProxy(
310
            BaseClass::class,
311
            $initializer
312
        );
313
314
        $proxy->initializeProxy();
315
316
        self::assertSame($initializer, $proxy->getProxyInitializer());
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
317
    }
318
319
    /**
320
     * Verifies that public properties are not being initialized multiple times
321
     */
322
    public function testKeepsInitializedPublicProperties() : void
323
    {
324
        $proxy = (new LazyLoadingGhostFactory())->createProxy(
325
            BaseClass::class,
326
            static function (
327
                object $proxy,
328
                string $method,
329
                array $parameters,
330
                ?Closure & $initializer
331
            ) : bool {
332
                $initializer           = null;
333
                $proxy->publicProperty = 'newValue';
334
335
                return true;
336
            }
337
        );
338
339
        $proxy->initializeProxy();
340
        self::assertSame('newValue', $proxy->publicProperty);
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
341
342
        $proxy->publicProperty = 'otherValue';
343
344
        $proxy->initializeProxy();
345
346
        self::assertSame('otherValue', $proxy->publicProperty);
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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
    }
348
349
    /**
350
     * Verifies that properties' default values are preserved
351
     */
352
    public function testPublicPropertyDefaultWillBePreserved() : void
353
    {
354
        $proxy = (new LazyLoadingGhostFactory())->createProxy(
355
            ClassWithPublicProperties::class,
356
            static function () : bool {
357
                return true;
358
            }
359
        );
360
361
        self::assertSame('property0', $proxy->property0);
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
362
    }
363
364
    /**
365
     * Verifies that protected properties' default values are preserved
366
     */
367
    public function testProtectedPropertyDefaultWillBePreserved() : void
368
    {
369
        $proxy = (new LazyLoadingGhostFactory())->createProxy(
370
            ClassWithProtectedProperties::class,
371
            static function () : bool {
372
                return true;
373
            }
374
        );
375
376
        // Check protected property via reflection
377
        $reflectionProperty = new ReflectionProperty(ClassWithProtectedProperties::class, 'property0');
378
        $reflectionProperty->setAccessible(true);
379
380
        self::assertSame('property0', $reflectionProperty->getValue($proxy));
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
381
    }
382
383
    /**
384
     * Verifies that private properties' default values are preserved
385
     */
386
    public function testPrivatePropertyDefaultWillBePreserved() : void
387
    {
388
        $proxy = (new LazyLoadingGhostFactory())->createProxy(
389
            ClassWithPrivateProperties::class,
390
            static function () : bool {
391
                return true;
392
            }
393
        );
394
395
        // Check protected property via reflection
396
        $reflectionProperty = new ReflectionProperty(ClassWithPrivateProperties::class, 'property0');
397
        $reflectionProperty->setAccessible(true);
398
399
        self::assertSame('property0', $reflectionProperty->getValue($proxy));
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
400
    }
401
402
    /**
403
     * @group 159
404
     * @group 192
405
     */
406
    public function testMultiLevelPrivatePropertiesDefaultsWillBePreserved() : void
407
    {
408
        $proxy = (new LazyLoadingGhostFactory())->createProxy(
409
            ClassWithCollidingPrivateInheritedProperties::class,
410
            static function () : bool {
411
                return true;
412
            }
413
        );
414
415
        $childProperty  = new ReflectionProperty(ClassWithCollidingPrivateInheritedProperties::class, 'property0');
416
        $parentProperty = new ReflectionProperty(get_parent_class(ClassWithCollidingPrivateInheritedProperties::class), 'property0');
417
418
        $childProperty->setAccessible(true);
419
        $parentProperty->setAccessible(true);
420
421
        self::assertSame('childClassProperty0', $childProperty->getValue($proxy));
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
422
        self::assertSame('property0', $parentProperty->getValue($proxy));
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
423
    }
424
425
    /**
426
     * @group 159
427
     * @group 192
428
     */
429
    public function testMultiLevelPrivatePropertiesByRefInitialization() : void
430
    {
431
        $proxy = (new LazyLoadingGhostFactory())->createProxy(
432
            ClassWithCollidingPrivateInheritedProperties::class,
433
            static function (
434
                GhostObjectInterface $proxy,
435
                string $method,
436
                array $params,
437
                ?Closure & $initializer,
438
                array $properties
439
            ) : bool {
440
                $initializer                                                                                              = null;
441
                $properties["\0" . ClassWithCollidingPrivateInheritedProperties::class . "\0property0"]                   = 'foo';
442
                $properties["\0" . get_parent_class(ClassWithCollidingPrivateInheritedProperties::class) . "\0property0"] = 'bar';
443
444
                return true;
445
            }
446
        );
447
448
        $childProperty  = new ReflectionProperty(ClassWithCollidingPrivateInheritedProperties::class, 'property0');
449
        $parentProperty = new ReflectionProperty(get_parent_class(ClassWithCollidingPrivateInheritedProperties::class), 'property0');
450
451
        $childProperty->setAccessible(true);
452
        $parentProperty->setAccessible(true);
453
454
        self::assertSame('foo', $childProperty->getValue($proxy));
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
455
        self::assertSame('bar', $parentProperty->getValue($proxy));
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
456
    }
457
458
    /**
459
     * @group 159
460
     * @group 192
461
     *
462
     * Test designed to verify that the cached logic does take into account the fact that
463
     * proxies are different instances
464
     */
465
    public function testGetPropertyFromDifferentProxyInstances() : void
466
    {
467
        $factory = new LazyLoadingGhostFactory();
468
        $proxy1  = $factory->createProxy(
469
            ClassWithCollidingPrivateInheritedProperties::class,
470
            static function (
471
                GhostObjectInterface $proxy,
472
                string $method,
473
                array $params,
474
                ?Closure & $initializer,
475
                array $properties
476
            ) : bool {
477
                $initializer                                                                                              = null;
478
                $properties["\0" . ClassWithCollidingPrivateInheritedProperties::class . "\0property0"]                   = 'foo';
479
                $properties["\0" . get_parent_class(ClassWithCollidingPrivateInheritedProperties::class) . "\0property0"] = 'bar';
480
481
                return true;
482
            }
483
        );
484
        $proxy2  = $factory->createProxy(
485
            ClassWithCollidingPrivateInheritedProperties::class,
486
            static function (
487
                GhostObjectInterface $proxy,
488
                string $method,
489
                array $params,
490
                ?Closure & $initializer,
491
                array $properties
492
            ) : bool {
493
                $initializer                                                                                              = null;
494
                $properties["\0" . ClassWithCollidingPrivateInheritedProperties::class . "\0property0"]                   = 'baz';
495
                $properties["\0" . get_parent_class(ClassWithCollidingPrivateInheritedProperties::class) . "\0property0"] = 'tab';
496
497
                return true;
498
            }
499
        );
500
501
        $childProperty  = new ReflectionProperty(ClassWithCollidingPrivateInheritedProperties::class, 'property0');
502
        $parentProperty = new ReflectionProperty(get_parent_class(ClassWithCollidingPrivateInheritedProperties::class), 'property0');
503
504
        $childProperty->setAccessible(true);
505
        $parentProperty->setAccessible(true);
506
507
        self::assertSame('foo', $childProperty->getValue($proxy1));
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
508
        self::assertSame('bar', $parentProperty->getValue($proxy1));
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
509
510
        self::assertSame('baz', $childProperty->getValue($proxy2));
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
511
        self::assertSame('tab', $parentProperty->getValue($proxy2));
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
512
    }
513
514
    /**
515
     * @group 159
516
     * @group 192
517
     *
518
     * Test designed to verify that the cached logic does take into account the fact that
519
     * proxies are different instances
520
     */
521
    public function testSetPrivatePropertyOnDifferentProxyInstances() : void
522
    {
523
        $factory = new LazyLoadingGhostFactory();
524
        $proxy1  = $factory->createProxy(
525
            ClassWithMixedPropertiesAndAccessorMethods::class,
526
            static function (
527
                GhostObjectInterface $proxy,
528
                string $method,
529
                array $params,
530
                ?Closure & $initializer
531
            ) : bool {
532
                $initializer = null;
533
534
                return true;
535
            }
536
        );
537
        $proxy2  = $factory->createProxy(
538
            ClassWithMixedPropertiesAndAccessorMethods::class,
539
            static function (
540
                GhostObjectInterface $proxy,
541
                string $method,
542
                array $params,
543
                ?Closure & $initializer
544
            ) : bool {
545
                $initializer = null;
546
547
                return true;
548
            }
549
        );
550
551
        $proxy1->set('privateProperty', 'private1');
552
        $proxy2->set('privateProperty', 'private2');
553
        self::assertSame('private1', $proxy1->get('privateProperty'));
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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
        self::assertSame('private2', $proxy2->get('privateProperty'));
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
555
    }
556
557
    /**
558
     * @group 159
559
     * @group 192
560
     *
561
     * Test designed to verify that the cached logic does take into account the fact that
562
     * proxies are different instances
563
     */
564
    public function testIssetPrivatePropertyOnDifferentProxyInstances() : void
565
    {
566
        $factory = new LazyLoadingGhostFactory();
567
        $proxy1  = $factory->createProxy(
568
            ClassWithMixedPropertiesAndAccessorMethods::class,
569
            static function (
570
                GhostObjectInterface $proxy,
571
                string $method,
572
                array $params,
573
                ?Closure & $initializer
574
            ) : bool {
575
                $initializer = null;
576
577
                return true;
578
            }
579
        );
580
        $proxy2  = $factory->createProxy(
581
            ClassWithMixedPropertiesAndAccessorMethods::class,
582
            static function (
583
                GhostObjectInterface $proxy,
584
                string $method,
585
                array $params,
586
                ?Closure & $initializer,
587
                array $properties
588
            ) : bool {
589
                $initializer                                                                                = null;
590
                $properties["\0" . ClassWithMixedPropertiesAndAccessorMethods::class . "\0privateProperty"] = null;
591
592
                return true;
593
            }
594
        );
595
596
        self::assertTrue($proxy1->has('privateProperty'));
0 ignored issues
show
Bug introduced by
The method assertTrue() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
597
        self::assertFalse($proxy2->has('privateProperty'));
0 ignored issues
show
Bug introduced by
The method assertFalse() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
598
        self::assertTrue($proxy1->has('privateProperty'));
0 ignored issues
show
Bug introduced by
The method assertTrue() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
599
        self::assertFalse($proxy2->has('privateProperty'));
0 ignored issues
show
Bug introduced by
The method assertFalse() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
600
    }
601
602
    /**
603
     * @group 159
604
     * @group 192
605
     *
606
     * Test designed to verify that the cached logic does take into account the fact that
607
     * proxies are different instances
608
     */
609
    public function testUnsetPrivatePropertyOnDifferentProxyInstances() : void
610
    {
611
        $factory = new LazyLoadingGhostFactory();
612
        $proxy1  = $factory->createProxy(
613
            ClassWithMixedPropertiesAndAccessorMethods::class,
614
            static function (
615
                GhostObjectInterface $proxy,
616
                string $method,
617
                array $params,
618
                ?Closure & $initializer
619
            ) : bool {
620
                $initializer = null;
621
622
                return true;
623
            }
624
        );
625
        $proxy2  = $factory->createProxy(
626
            ClassWithMixedPropertiesAndAccessorMethods::class,
627
            static function (
628
                GhostObjectInterface $proxy,
629
                string $method,
630
                array $params,
631
                ?Closure & $initializer
632
            ) : bool {
633
                $initializer = null;
634
635
                return true;
636
            }
637
        );
638
639
        self::assertTrue($proxy1->has('privateProperty'));
0 ignored issues
show
Bug introduced by
The method assertTrue() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
640
        $proxy2->remove('privateProperty');
641
        self::assertFalse($proxy2->has('privateProperty'));
0 ignored issues
show
Bug introduced by
The method assertFalse() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
642
        self::assertTrue($proxy1->has('privateProperty'));
0 ignored issues
show
Bug introduced by
The method assertTrue() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
643
        $proxy1->remove('privateProperty');
644
        self::assertFalse($proxy1->has('privateProperty'));
0 ignored issues
show
Bug introduced by
The method assertFalse() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
645
        self::assertFalse($proxy2->has('privateProperty'));
0 ignored issues
show
Bug introduced by
The method assertFalse() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
646
    }
647
648
    /**
649
     * @group 159
650
     * @group 192
651
     *
652
     * Test designed to verify that the cached logic does take into account the fact that
653
     * proxies are different instances
654
     */
655
    public function testIssetPrivateAndProtectedPropertiesDoesCheckAgainstBooleanFalse() : void
656
    {
657
        $factory = new LazyLoadingGhostFactory();
658
        $proxy1  = $factory->createProxy(
659
            ClassWithMixedPropertiesAndAccessorMethods::class,
660
            static function (
661
                GhostObjectInterface $proxy,
662
                string $method,
663
                array $params,
664
                ?Closure & $initializer,
665
                array $properties
666
            ) : bool {
667
                $initializer                                                                                = null;
668
                $properties['publicProperty']                                                               = false;
669
                $properties["\0*\0protectedProperty"]                                                       = false;
670
                $properties["\0" . ClassWithMixedPropertiesAndAccessorMethods::class . "\0privateProperty"] = false;
671
672
                return true;
673
            }
674
        );
675
        $proxy2  = $factory->createProxy(
676
            ClassWithMixedPropertiesAndAccessorMethods::class,
677
            static function (
678
                GhostObjectInterface $proxy,
679
                string $method,
680
                array $params,
681
                ?Closure & $initializer,
682
                array $properties
683
            ) : bool {
684
                $initializer                                                                                = null;
685
                $properties['publicProperty']                                                               = null;
686
                $properties["\0*\0protectedProperty"]                                                       = null;
687
                $properties["\0" . ClassWithMixedPropertiesAndAccessorMethods::class . "\0privateProperty"] = null;
688
689
                return true;
690
            }
691
        );
692
693
        self::assertTrue($proxy1->has('protectedProperty'));
0 ignored issues
show
Bug introduced by
The method assertTrue() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
694
        self::assertTrue($proxy1->has('publicProperty'));
0 ignored issues
show
Bug introduced by
The method assertTrue() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
695
        self::assertTrue($proxy1->has('privateProperty'));
0 ignored issues
show
Bug introduced by
The method assertTrue() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
696
697
        self::assertFalse($proxy2->has('protectedProperty'));
0 ignored issues
show
Bug introduced by
The method assertFalse() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
698
        self::assertFalse($proxy2->has('publicProperty'));
0 ignored issues
show
Bug introduced by
The method assertFalse() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
699
        self::assertFalse($proxy2->has('privateProperty'));
0 ignored issues
show
Bug introduced by
The method assertFalse() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
700
    }
701
702
    public function testByRefInitialization() : void
703
    {
704
        $proxy = (new LazyLoadingGhostFactory())->createProxy(
705
            ClassWithMixedProperties::class,
706
            static function (
707
                GhostObjectInterface $proxy,
708
                string $method,
709
                array $params,
710
                ?Closure & $initializer,
711
                array $properties
712
            ) : bool {
713
                $initializer                                                               = null;
714
                $properties["\0" . ClassWithMixedProperties::class . "\0privateProperty0"] = 'private0';
715
                $properties["\0" . ClassWithMixedProperties::class . "\0privateProperty1"] = 'private1';
716
                $properties["\0" . ClassWithMixedProperties::class . "\0privateProperty2"] = 'private2';
717
                $properties["\0*\0protectedProperty0"]                                     = 'protected0';
718
                $properties["\0*\0protectedProperty1"]                                     = 'protected1';
719
                $properties["\0*\0protectedProperty2"]                                     = 'protected2';
720
                $properties['publicProperty0']                                             = 'public0';
721
                $properties['publicProperty1']                                             = 'public1';
722
                $properties['publicProperty2']                                             = 'public2';
723
724
                return true;
725
            }
726
        );
727
728
        $reflectionClass = new ReflectionClass(ClassWithMixedProperties::class);
729
730
        foreach (Properties::fromReflectionClass($reflectionClass)->getInstanceProperties() as $property) {
731
            $property->setAccessible(true);
732
733
            self::assertSame(str_replace('Property', '', $property->getName()), $property->getValue($proxy));
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
734
        }
735
    }
736
737
    public function testByRefInitializationOfTypedProperties() : void
738
    {
739
        $proxy = (new LazyLoadingGhostFactory())->createProxy(
740
            ClassWithMixedTypedProperties::class,
741
            static function (
742
                GhostObjectInterface $proxy,
743
                string $method,
744
                array $params,
745
                ?Closure & $initializer,
746
                array $properties
747
            ) : bool {
748
                $initializer                                                                         = null;
749
                $properties["\0" . ClassWithMixedTypedProperties::class . "\0privateStringProperty"] = 'private0';
750
                $properties["\0*\0protectedStringProperty"]                                          = 'protected0';
751
                $properties['publicStringProperty']                                                  = 'public0';
752
753
                return true;
754
            }
755
        );
756
757
        $reflectionClass = new ReflectionClass(ClassWithMixedTypedProperties::class);
758
759
        $properties = Properties::fromReflectionClass($reflectionClass)->getInstanceProperties();
760
761
        $privateProperty   = $properties["\0" . ClassWithMixedTypedProperties::class . "\0privateStringProperty"];
762
        $protectedProperty = $properties["\0*\0protectedStringProperty"];
763
764
        $privateProperty->setAccessible(true);
765
        $protectedProperty->setAccessible(true);
766
767
        self::assertSame('private0', $privateProperty->getValue($proxy));
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
768
        self::assertSame('protected0', $properties["\0*\0protectedStringProperty"]->getValue($proxy));
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
769
        self::assertSame('public0', $proxy->publicStringProperty);
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
770
    }
771
772
    /**
773
     * @group 115
774
     * @group 175
775
     */
776
    public function testWillBehaveLikeObjectWithNormalConstructor() : void
777
    {
778
        $instance = new ClassWithCounterConstructor(10);
779
780
        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\...ingGhostFunctionalTest>.

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...
781
        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\...ingGhostFunctionalTest>.

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...
782
        $instance->__construct(3);
783
        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\...ingGhostFunctionalTest>.

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...
784
        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\...ingGhostFunctionalTest>.

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...
785
786
        $proxyName = get_class(
787
            (new LazyLoadingGhostFactory())
788
                ->createProxy(
789
                    ClassWithCounterConstructor::class,
790
                    static function () : bool {
791
                        return true;
792
                    }
793
                )
794
        );
795
796
        $proxy = new $proxyName(15);
797
798
        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\...ingGhostFunctionalTest>.

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...
799
        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\...ingGhostFunctionalTest>.

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...
800
        $proxy->__construct(5);
801
        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\...ingGhostFunctionalTest>.

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...
802
        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\...ingGhostFunctionalTest>.

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...
803
    }
804
805
    public function testInitializeProxyWillReturnTrueOnSuccessfulInitialization() : void
806
    {
807
        $proxy = (new LazyLoadingGhostFactory())->createProxy(
808
            ClassWithMixedTypedProperties::class,
809
            $this->createInitializer(
810
                ClassWithMixedTypedProperties::class,
811
                new ClassWithMixedTypedProperties()
812
            )
813
        );
814
815
        self::assertTrue($proxy->initializeProxy());
0 ignored issues
show
Bug introduced by
The method assertTrue() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
816
        self::assertTrue($proxy->isProxyInitialized());
0 ignored issues
show
Bug introduced by
The method assertTrue() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
817
        self::assertFalse($proxy->initializeProxy());
0 ignored issues
show
Bug introduced by
The method assertFalse() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
818
    }
819
820
    /**
821
     * @psalm-param (CallableInterface&Mock)|null $initializerMatcher
822
     * @psalm-return Closure(
823
     *   GhostObjectInterface,
824
     *   string,
825
     *   array,
826
     *   ?Closure
827
     * ) : bool
828
     */
829
    private function createInitializer(string $className, object $realInstance, ?Mock $initializerMatcher = null) : Closure
830
    {
831
        if (! $initializerMatcher) {
832
            $initializerMatcher = $this->createMock(CallableInterface::class);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $initializerMatcher 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...
833
834
            $initializerMatcher
0 ignored issues
show
Bug introduced by
The method expects cannot be called on $initializerMatcher (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...
835
                ->expects(self::once())
0 ignored issues
show
Bug introduced by
The method once() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
836
                ->method('__invoke')
837
                ->with(self::logicalAnd(
0 ignored issues
show
Bug introduced by
The method logicalAnd() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
838
                    self::isInstanceOf(GhostObjectInterface::class),
0 ignored issues
show
Bug introduced by
The method isInstanceOf() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
839
                    self::isInstanceOf($className)
0 ignored issues
show
Bug introduced by
The method isInstanceOf() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
840
                ));
841
        }
842
843
        return static function (
844
            GhostObjectInterface $proxy,
845
            string $method,
846
            array $params,
847
            ?Closure & $initializer
848
        ) use (
849
            $initializerMatcher,
850
            $realInstance
851
        ) : bool {
852
            $initializer = null;
853
854
            $reflectionClass = new ReflectionClass($realInstance);
855
856
            foreach (Properties::fromReflectionClass($reflectionClass)->getInstanceProperties() as $property) {
857
                if (! self::isPropertyInitialized($realInstance, $property)) {
858
                    continue;
859
                }
860
861
                $property->setAccessible(true);
862
                $property->setValue($proxy, $property->getValue($realInstance));
863
            }
864
865
            $initializerMatcher->__invoke($proxy, $method, $params);
866
867
            return true;
868
        };
869
    }
870
871
    /**
872
     * Generates a list of object | invoked method | parameters | expected result
873
     *
874
     * @return null[][]|string[][]|object[][]|mixed[][][]
875
     */
876
    public function getProxyMethods() : array
877
    {
878
        $selfHintParam = new ClassWithSelfHint();
879
        $empty         = new EmptyClass();
880
881
        return [
882
            [
883
                BaseClass::class,
884
                new BaseClass(),
885
                'publicMethod',
886
                [],
887
                'publicMethodDefault',
888
            ],
889
            [
890
                BaseClass::class,
891
                new BaseClass(),
892
                'publicTypeHintedMethod',
893
                [new stdClass()],
894
                'publicTypeHintedMethodDefault',
895
            ],
896
            [
897
                BaseClass::class,
898
                new BaseClass(),
899
                'publicByReferenceMethod',
900
                [],
901
                'publicByReferenceMethodDefault',
902
            ],
903
            [
904
                ClassWithSelfHint::class,
905
                new ClassWithSelfHint(),
906
                'selfHintMethod',
907
                ['parameter' => $selfHintParam],
908
                $selfHintParam,
909
            ],
910
            [
911
                ClassWithParentHint::class,
912
                new ClassWithParentHint(),
913
                'parentHintMethod',
914
                ['parameter' => $empty],
915
                $empty,
916
            ],
917
            [
918
                ClassWithAbstractPublicMethod::class,
919
                new EmptyClass(), // EmptyClass just used to not make reflection explode when synchronizing properties
920
                'publicAbstractMethod',
921
                [],
922
                null,
923
            ],
924
            [
925
                ClassWithMethodWithByRefVariadicFunction::class,
926
                new ClassWithMethodWithByRefVariadicFunction(),
927
                'tuz',
928
                ['Ocramius', 'Malukenho'],
929
                ['Ocramius', 'changed'],
930
            ],
931
        ];
932
    }
933
934
    /**
935
     * Generates a list of object | invoked method | parameters | expected result for methods that cause lazy-loading
936
     * of a ghost object
937
     *
938
     * @return string[][]|object[][]|mixed[][][]|null[][]
939
     */
940
    public function getProxyInitializingMethods() : array
941
    {
942
        return [
943
            [
944
                BaseClass::class,
945
                new BaseClass(),
946
                'publicPropertyGetter',
947
                [],
948
                'publicPropertyDefault',
949
            ],
950
            [
951
                BaseClass::class,
952
                new BaseClass(),
953
                'protectedPropertyGetter',
954
                [],
955
                'protectedPropertyDefault',
956
            ],
957
            [
958
                BaseClass::class,
959
                new BaseClass(),
960
                'privatePropertyGetter',
961
                [],
962
                'privatePropertyDefault',
963
            ],
964
            [
965
                ClassWithMethodWithVariadicFunction::class,
966
                new ClassWithMethodWithVariadicFunction(),
967
                'foo',
968
                ['Ocramius', 'Malukenho'],
969
                null,
970
            ],
971
        ];
972
    }
973
974
    /**
975
     * Generates a list of object | invoked method | parameters | expected result for methods DON'T cause lazy-loading
976
     *
977
     * @return null[][]|string[][]|object[][]|mixed[][][]
978
     */
979
    public function getProxyNonInitializingMethods() : array
980
    {
981
        return $this->getProxyMethods();
982
    }
983
984
    /**
985
     * Generates proxies and instances with a public property to feed to the property accessor methods
986
     *
987
     * @return string[][]|object[][]
988
     */
989
    public function getPropertyAccessProxies() : array
990
    {
991
        $instance1 = new BaseClass();
992
        $instance2 = new BaseClass();
993
994
        $factory = new LazyLoadingGhostFactory();
995
996
        /** @var GhostObjectInterface $serialized */
997
        $serialized = unserialize(serialize($factory->createProxy(
998
            BaseClass::class,
999
            $this->createInitializer(BaseClass::class, $instance2)
0 ignored issues
show
Documentation introduced by
$instance2 is of type object<ProxyManagerTestAsset\BaseClass>, 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...
1000
        )));
1001
1002
        return [
1003
            [
1004
                $instance1,
1005
                $factory->createProxy(
1006
                    BaseClass::class,
1007
                    $this->createInitializer(BaseClass::class, $instance1)
0 ignored issues
show
Documentation introduced by
$instance1 is of type object<ProxyManagerTestAsset\BaseClass>, 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...
1008
                ),
1009
                'publicProperty',
1010
                'publicPropertyDefault',
1011
            ],
1012
            [
1013
                $instance2,
1014
                $serialized,
1015
                'publicProperty',
1016
                'publicPropertyDefault',
1017
            ],
1018
        ];
1019
    }
1020
1021
    /**
1022
     * @param mixed   $expected
1023
     * @param mixed[] $proxyOptions
1024
     *
1025
     * @dataProvider skipPropertiesFixture
1026
     *
1027
     * @psalm-param class-string $className
1028
     * @psalm-param array{skippedProperties?: array<int, string>} $proxyOptions
1029
     */
1030
    public function testInitializationIsSkippedForSkippedProperties(
1031
        string $className,
1032
        string $propertyClass,
1033
        string $propertyName,
1034
        array $proxyOptions,
1035
        $expected
1036
    ) : void {
1037
        $ghostObject = (new LazyLoadingGhostFactory())->createProxy(
1038
            $className,
1039
            static function () use ($propertyName) : bool {
1040
                self::fail(sprintf('The Property "%s" was not expected to be lazy-loaded', $propertyName));
0 ignored issues
show
Bug introduced by
The method fail() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
1041
1042
                return true;
1043
            },
1044
            $proxyOptions
1045
        );
1046
1047
        $property = new ReflectionProperty($propertyClass, $propertyName);
1048
        $property->setAccessible(true);
1049
1050
        self::assertSame($expected, $property->getValue($ghostObject));
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
1051
    }
1052
1053
    /**
1054
     * @param array<string, mixed> $proxyOptions
1055
     *
1056
     * @dataProvider skipPropertiesFixture
1057
     *
1058
     * @psalm-param class-string $className
1059
     * @psalm-param array{skippedProperties?: array<int, string>} $proxyOptions
1060
     */
1061
    public function testSkippedPropertiesAreNotOverwrittenOnInitialization(
1062
        string $className,
1063
        string $propertyClass,
1064
        string $propertyName,
1065
        array $proxyOptions
1066
    ) : void {
1067
        $ghostObject = (new LazyLoadingGhostFactory())->createProxy(
1068
            $className,
1069
            static function (
1070
                GhostObjectInterface $proxy,
1071
                string $method,
1072
                array $params,
1073
                ?Closure & $initializer
1074
            ) : bool {
1075
                $initializer = null;
1076
1077
                return true;
1078
            },
1079
            $proxyOptions
1080
        );
1081
1082
        $property = new ReflectionProperty($propertyClass, $propertyName);
1083
1084
        $property->setAccessible(true);
1085
1086
        $value = uniqid('', true);
1087
1088
        $property->setValue($ghostObject, $value);
1089
1090
        self::assertTrue($ghostObject->initializeProxy());
0 ignored issues
show
Bug introduced by
The method assertTrue() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
1091
1092
        self::assertSame(
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
1093
            $value,
1094
            $property->getValue($ghostObject),
1095
            'Property should not be changed by proxy initialization'
1096
        );
1097
    }
1098
1099
    /**
1100
     * @group 265
1101
     */
1102
    public function testWillForwardVariadicByRefArguments() : void
1103
    {
1104
        $object = (new LazyLoadingGhostFactory())->createProxy(
1105
            ClassWithMethodWithByRefVariadicFunction::class,
1106
            static function (
1107
                GhostObjectInterface $proxy,
1108
                string $method,
1109
                array $params,
1110
                ?Closure & $initializer
1111
            ) : bool {
1112
                $initializer = null;
1113
1114
                return true;
1115
            }
1116
        );
1117
1118
        $parameters = ['a', 'b', 'c'];
1119
1120
        // first, testing normal variadic behavior (verifying we didn't screw up in the test asset)
1121
        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\...ingGhostFunctionalTest>.

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...
1122
        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\...ingGhostFunctionalTest>.

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...
1123
        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\...ingGhostFunctionalTest>.

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...
1124
    }
1125
1126
    /**
1127
     * @group 265
1128
     */
1129
    public function testWillForwardDynamicArguments() : void
1130
    {
1131
        $object = (new LazyLoadingGhostFactory())->createProxy(
1132
            ClassWithDynamicArgumentsMethod::class,
1133
            static function () : bool {
1134
                return true;
1135
            }
1136
        );
1137
1138
        // first, testing normal variadic behavior (verifying we didn't screw up in the test asset)
1139
        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\...ingGhostFunctionalTest>.

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...
1140
        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\...ingGhostFunctionalTest>.

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...
1141
    }
1142
1143
    /**
1144
     * @return mixed[] in order:
1145
     *                  - the class to be proxied
1146
     *                  - the class owning the property to be checked
1147
     *                  - the property name
1148
     *                  - the options to be passed to the generator
1149
     *                  - the expected value of the property
1150
     */
1151
    public function skipPropertiesFixture() : array
1152
    {
1153
        return [
1154
            [
1155
                ClassWithPublicProperties::class,
1156
                ClassWithPublicProperties::class,
1157
                'property9',
1158
                [
1159
                    'skippedProperties' => ['property9'],
1160
                ],
1161
                'property9',
1162
            ],
1163
            [
1164
                ClassWithProtectedProperties::class,
1165
                ClassWithProtectedProperties::class,
1166
                'property9',
1167
                [
1168
                    'skippedProperties' => ["\0*\0property9"],
1169
                ],
1170
                'property9',
1171
            ],
1172
            [
1173
                ClassWithPrivateProperties::class,
1174
                ClassWithPrivateProperties::class,
1175
                'property9',
1176
                [
1177
                    'skippedProperties' => ["\0ProxyManagerTestAsset\\ClassWithPrivateProperties\0property9"],
1178
                ],
1179
                'property9',
1180
            ],
1181
            [
1182
                ClassWithCollidingPrivateInheritedProperties::class,
1183
                ClassWithCollidingPrivateInheritedProperties::class,
1184
                'property0',
1185
                [
1186
                    'skippedProperties' => ["\0ProxyManagerTestAsset\\ClassWithCollidingPrivateInheritedProperties\0property0"],
1187
                ],
1188
                'childClassProperty0',
1189
            ],
1190
            [
1191
                ClassWithCollidingPrivateInheritedProperties::class,
1192
                ClassWithPrivateProperties::class,
1193
                'property0',
1194
                [
1195
                    'skippedProperties' => ["\0ProxyManagerTestAsset\\ClassWithPrivateProperties\0property0"],
1196
                ],
1197
                'property0',
1198
            ],
1199
        ];
1200
    }
1201
1202
    /**
1203
     * @group        276
1204
     * @dataProvider getMethodsThatAccessPropertiesOnOtherObjectsInTheSameScope
1205
     */
1206
    public function testWillLazyLoadMembersOfOtherProxiesWithTheSamePrivateScope(
1207
        object $callerObject,
1208
        string $method,
1209
        string $propertyIndex,
1210
        string $expectedValue
1211
    ) : void {
1212
        $proxy = (new LazyLoadingGhostFactory())->createProxy(
1213
            OtherObjectAccessClass::class,
1214
            static function (
1215
                GhostObjectInterface $proxy,
1216
                string $method,
1217
                array $params,
1218
                ?Closure & $initializer,
1219
                array $properties
1220
            ) use (
1221
                $propertyIndex,
1222
                $expectedValue
1223
            ) : bool {
1224
                $initializer = null;
1225
1226
                $properties[$propertyIndex] = $expectedValue;
1227
1228
                return true;
1229
            }
1230
        );
1231
1232
        $accessor = [$callerObject, $method];
1233
1234
        self::assertIsCallable($accessor);
0 ignored issues
show
Bug introduced by
The method assertIsCallable() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
1235
1236
        self::assertFalse($proxy->isProxyInitialized());
0 ignored issues
show
Bug introduced by
The method assertFalse() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
1237
        self::assertSame($expectedValue, $accessor($proxy));
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
1238
        self::assertTrue($proxy->isProxyInitialized());
0 ignored issues
show
Bug introduced by
The method assertTrue() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
1239
    }
1240
1241
    /**
1242
     * @group        276
1243
     * @dataProvider getMethodsThatAccessPropertiesOnOtherObjectsInTheSameScope
1244
     */
1245
    public function testWillAccessMembersOfOtherDeSerializedProxiesWithTheSamePrivateScope(
1246
        object $callerObject,
1247
        string $method,
1248
        string $propertyIndex,
1249
        string $expectedValue
1250
    ) : void {
1251
        /** @var OtherObjectAccessClass&LazyLoadingInterface $proxy */
0 ignored issues
show
Documentation introduced by
The doc-type OtherObjectAccessClass&LazyLoadingInterface could not be parsed: Unknown type name "OtherObjectAccessClass&LazyLoadingInterface" at position 0. (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...
1252
        $proxy = unserialize(serialize(
1253
            (new LazyLoadingGhostFactory())->createProxy(
1254
                OtherObjectAccessClass::class,
1255
                static function (
1256
                    GhostObjectInterface $proxy,
1257
                    string $method,
1258
                    array $params,
1259
                    ?Closure & $initializer,
1260
                    array $properties
1261
                ) use (
1262
                    $propertyIndex,
1263
                    $expectedValue
1264
                ) : bool {
1265
                    $initializer = null;
1266
1267
                    $properties[$propertyIndex] = $expectedValue;
1268
1269
                    return true;
1270
                }
1271
            )
1272
        ));
1273
1274
        $accessor = [$callerObject, $method];
1275
1276
        self::assertIsCallable($accessor);
0 ignored issues
show
Bug introduced by
The method assertIsCallable() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
1277
1278
        self::assertTrue($proxy->isProxyInitialized());
0 ignored issues
show
Bug introduced by
The method assertTrue() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
1279
        self::assertSame($expectedValue, $accessor($proxy));
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
1280
    }
1281
1282
    /**
1283
     * @group        276
1284
     * @dataProvider getMethodsThatAccessPropertiesOnOtherObjectsInTheSameScope
1285
     */
1286
    public function testWillAccessMembersOfOtherClonedProxiesWithTheSamePrivateScope(
1287
        object $callerObject,
1288
        string $method,
1289
        string $propertyIndex,
1290
        string $expectedValue
1291
    ) : void {
1292
        $proxy = clone (new LazyLoadingGhostFactory())->createProxy(
1293
            OtherObjectAccessClass::class,
1294
            static function (
1295
                GhostObjectInterface $proxy,
1296
                string $method,
1297
                array $params,
1298
                ?Closure & $initializer,
1299
                array $properties
1300
            ) use (
1301
                $propertyIndex,
1302
                $expectedValue
1303
            ) : bool {
1304
                $initializer = null;
1305
1306
                $properties[$propertyIndex] = $expectedValue;
1307
1308
                return true;
1309
            }
1310
        );
1311
1312
        $accessor = [$callerObject, $method];
1313
1314
        self::assertIsCallable($accessor);
0 ignored issues
show
Bug introduced by
The method assertIsCallable() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
1315
1316
        self::assertTrue($proxy->isProxyInitialized());
0 ignored issues
show
Bug introduced by
The method assertTrue() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
1317
        self::assertSame($expectedValue, $accessor($proxy));
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
1318
    }
1319
1320
    /** @return string[][]|object[][] */
1321
    public function getMethodsThatAccessPropertiesOnOtherObjectsInTheSameScope() : array
1322
    {
1323
        $factory = new LazyLoadingGhostFactory();
1324
1325
        return [
1326
            OtherObjectAccessClass::class . '#$privateProperty'                => [
1327
                new OtherObjectAccessClass(),
1328
                'getPrivateProperty',
1329
                "\0" . OtherObjectAccessClass::class . "\0privateProperty",
1330
                uniqid('', true),
1331
            ],
1332
            OtherObjectAccessClass::class . '#$protectedProperty'              => [
1333
                new OtherObjectAccessClass(),
1334
                'getProtectedProperty',
1335
                "\0*\0protectedProperty",
1336
                uniqid('', true),
1337
            ],
1338
            OtherObjectAccessClass::class . '#$publicProperty'                 => [
1339
                new OtherObjectAccessClass(),
1340
                'getPublicProperty',
1341
                'publicProperty',
1342
                uniqid('', true),
1343
            ],
1344
            '(proxy) ' . OtherObjectAccessClass::class . '#$privateProperty'   => [
1345
                $factory->createProxy(
1346
                    OtherObjectAccessClass::class,
1347
                    static function () : bool {
1348
                        self::fail('Should never be initialized, as its values aren\'t accessed');
0 ignored issues
show
Bug introduced by
The method fail() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
1349
1350
                        return true;
1351
                    }
1352
                ),
1353
                'getPrivateProperty',
1354
                "\0" . OtherObjectAccessClass::class . "\0privateProperty",
1355
                uniqid('', true),
1356
            ],
1357
            '(proxy) ' . OtherObjectAccessClass::class . '#$protectedProperty' => [
1358
                $factory->createProxy(
1359
                    OtherObjectAccessClass::class,
1360
                    static function () : bool {
1361
                        self::fail('Should never be initialized, as its values aren\'t accessed');
0 ignored issues
show
Bug introduced by
The method fail() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
1362
1363
                        return true;
1364
                    }
1365
                ),
1366
                'getProtectedProperty',
1367
                "\0*\0protectedProperty",
1368
                uniqid('', true),
1369
            ],
1370
            '(proxy) ' . OtherObjectAccessClass::class . '#$publicProperty'    => [
1371
                $factory->createProxy(
1372
                    OtherObjectAccessClass::class,
1373
                    static function () : bool {
1374
                        self::fail('Should never be initialized, as its values aren\'t accessed');
0 ignored issues
show
Bug introduced by
The method fail() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
1375
1376
                        return true;
1377
                    }
1378
                ),
1379
                'getPublicProperty',
1380
                'publicProperty',
1381
                uniqid('', true),
1382
            ],
1383
        ];
1384
    }
1385
1386
    /**
1387
     * @group 276
1388
     */
1389
    public function testFriendObjectWillNotCauseLazyLoadingOnSkippedProperty() : void
1390
    {
1391
        $proxy = (new LazyLoadingGhostFactory())
1392
            ->createProxy(
1393
                OtherObjectAccessClass::class,
1394
                static function () : bool {
1395
                    throw new BadMethodCallException('The proxy should never be initialized, as all properties are skipped');
1396
                },
1397
                [
1398
                    'skippedProperties' => [
1399
                        "\0" . OtherObjectAccessClass::class . "\0privateProperty",
1400
                        "\0*\0protectedProperty",
1401
                        'publicProperty',
1402
                    ],
1403
                ]
1404
            );
1405
1406
        $privatePropertyValue   = uniqid('', true);
1407
        $protectedPropertyValue = uniqid('', true);
1408
        $publicPropertyValue    = uniqid('', true);
1409
1410
        $reflectionPrivateProperty = new ReflectionProperty(OtherObjectAccessClass::class, 'privateProperty');
1411
1412
        $reflectionPrivateProperty->setAccessible(true);
1413
        $reflectionPrivateProperty->setValue($proxy, $privatePropertyValue);
1414
1415
        $reflectionProtectedProperty = new ReflectionProperty(OtherObjectAccessClass::class, 'protectedProperty');
1416
1417
        $reflectionProtectedProperty->setAccessible(true);
1418
        $reflectionProtectedProperty->setValue($proxy, $protectedPropertyValue);
1419
1420
        $proxy->publicProperty = $publicPropertyValue;
1421
1422
        $friendObject = new OtherObjectAccessClass();
1423
1424
        self::assertSame($privatePropertyValue, $friendObject->getPrivateProperty($proxy));
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
1425
        self::assertSame($protectedPropertyValue, $friendObject->getProtectedProperty($proxy));
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
1426
        self::assertSame($publicPropertyValue, $friendObject->getPublicProperty($proxy));
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
1427
    }
1428
1429
    public function testClonedSkippedPropertiesArePreserved() : void
1430
    {
1431
        $proxy = (new LazyLoadingGhostFactory())
1432
            ->createProxy(
1433
                BaseClass::class,
1434
                static function (GhostObjectInterface $proxy) : bool {
1435
                    $proxy->setProxyInitializer(null);
1436
1437
                    return true;
1438
                },
1439
                [
1440
                    'skippedProperties' => [
1441
                        "\0" . BaseClass::class . "\0privateProperty",
1442
                        "\0*\0protectedProperty",
1443
                        'publicProperty',
1444
                    ],
1445
                ]
1446
            );
1447
1448
        $reflectionPrivate   = new ReflectionProperty(BaseClass::class, 'privateProperty');
1449
        $reflectionProtected = new ReflectionProperty(BaseClass::class, 'protectedProperty');
1450
1451
        $reflectionPrivate->setAccessible(true);
1452
        $reflectionProtected->setAccessible(true);
1453
1454
        $privateValue   = uniqid('', true);
1455
        $protectedValue = uniqid('', true);
1456
        $publicValue    = uniqid('', true);
1457
1458
        $reflectionPrivate->setValue($proxy, $privateValue);
1459
        $reflectionProtected->setValue($proxy, $protectedValue);
1460
        $proxy->publicProperty = $publicValue;
1461
1462
        self::assertFalse($proxy->isProxyInitialized());
0 ignored issues
show
Bug introduced by
The method assertFalse() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
1463
1464
        $clone = clone $proxy;
1465
1466
        self::assertFalse($proxy->isProxyInitialized());
0 ignored issues
show
Bug introduced by
The method assertFalse() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
1467
        self::assertTrue($clone->isProxyInitialized());
0 ignored issues
show
Bug introduced by
The method assertTrue() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
1468
1469
        self::assertSame($privateValue, $reflectionPrivate->getValue($proxy));
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
1470
        self::assertSame($privateValue, $reflectionPrivate->getValue($clone));
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
1471
        self::assertSame($protectedValue, $reflectionProtected->getValue($proxy));
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
1472
        self::assertSame($protectedValue, $reflectionProtected->getValue($clone));
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
1473
        self::assertSame($publicValue, $proxy->publicProperty);
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
1474
        self::assertSame($publicValue, $clone->publicProperty);
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
1475
    }
1476
1477
    /**
1478
     * @group 327
1479
     */
1480
    public function testWillExecuteLogicInAVoidMethod() : void
1481
    {
1482
        $initialCounter = random_int(10, 1000);
1483
1484
        $proxy = (new LazyLoadingGhostFactory())->createProxy(
1485
            VoidCounter::class,
1486
            static function (
1487
                LazyLoadingInterface $proxy,
1488
                string $method,
1489
                array $params,
1490
                ?Closure & $initializer,
1491
                array $properties
1492
            ) use ($initialCounter) : bool {
1493
                $initializer = null;
1494
1495
                $properties['counter'] = $initialCounter;
1496
1497
                return true;
1498
            }
1499
        );
1500
1501
        $increment = random_int(1001, 10000);
1502
1503
        $proxy->increment($increment);
1504
1505
        self::assertSame($initialCounter + $increment, $proxy->counter);
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
1506
    }
1507
1508
    private static function isPropertyInitialized(object $object, ReflectionProperty $property) : bool
1509
    {
1510
        return array_key_exists(
1511
            ($property->isProtected() ? "\0*\0" : '')
1512
            . ($property->isPrivate() ? "\0" . $property->getDeclaringClass()->getName() . "\0" : '')
1513
            . $property->getName(),
1514
            (array) $object
1515
        );
1516
    }
1517
1518
    /**
1519
     * @param mixed $expected
1520
     * @param mixed $actual
1521
     */
1522
    private static function assertByRefVariableValueSame($expected, & $actual) : void
1523
    {
1524
        self::assertSame($expected, $actual);
0 ignored issues
show
Bug introduced by
The method assertSame() does not seem to exist on object<ProxyManagerTest\...ingGhostFunctionalTest>.

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...
1525
    }
1526
}
1527