Completed
Pull Request — master (#564)
by Michał
07:58
created

testHydrateOneToManyAssociationByReferenceUsingIdentifiersForRelations()   A

Complexity

Conditions 4
Paths 2

Size

Total Lines 56
Code Lines 36

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 0 Features 0
Metric Value
c 4
b 0
f 0
dl 0
loc 56
rs 9.0544
cc 4
eloc 36
nc 2
nop 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace DoctrineModuleTest\Stdlib\Hydrator;
4
5
use Doctrine\Common\Collections\ArrayCollection;
6
use Doctrine\Common\Collections\Collection;
7
use Doctrine\Common\Persistence\Mapping\ClassMetadata;
8
use Doctrine\Common\Persistence\ObjectManager;
9
use DoctrineModule\Stdlib\Hydrator\DoctrineObject as DoctrineObjectHydrator;
10
use DoctrineModule\Stdlib\Hydrator\Filter;
11
use DoctrineModule\Stdlib\Hydrator\Strategy;
12
use Zend\Hydrator\NamingStrategy\UnderscoreNamingStrategy;
13
14
class DoctrineObjectTest extends \PHPUnit_Framework_TestCase
15
{
16
    /**
17
     * @var DoctrineObjectHydrator
18
     */
19
    protected $hydratorByValue;
20
21
    /**
22
     * @var DoctrineObjectHydrator
23
     */
24
    protected $hydratorByReference;
25
26
    /**
27
     * @var ClassMetadata|\PHPUnit_Framework_MockObject_MockObject
28
     */
29
    protected $metadata;
30
31
    /**
32
     * @var ObjectManager|\PHPUnit_Framework_MockObject_MockObject
33
     */
34
    protected $objectManager;
35
36
    protected function setUp()
37
    {
38
        parent::setUp();
39
40
        $this->metadata      = $this->createMock(ClassMetadata::class);
41
        $this->objectManager = $this->createMock(ObjectManager::class);
42
43
        $this->objectManager->expects($this->any())
44
                            ->method('getClassMetadata')
45
                            ->will($this->returnValue($this->metadata));
46
    }
47
48
    public function configureObjectManagerForSimpleEntity()
49
    {
50
        $refl = new \ReflectionClass(Asset\SimpleEntity::class);
51
52
        $this
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\Common\Persistence\Mapping\ClassMetadata.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
53
            ->metadata
54
            ->expects($this->any())
55
            ->method('getName')
56
            ->will($this->returnValue(Asset\SimpleEntity::class));
57
        $this
58
            ->metadata
59
            ->expects($this->any())
60
            ->method('getAssociationNames')
61
            ->will($this->returnValue([]));
62
63
        $this
64
            ->metadata
65
            ->expects($this->any())
66
            ->method('getFieldNames')
67
            ->will($this->returnValue(['id', 'field']));
68
69
        $this
70
            ->metadata
71
            ->expects($this->any())
72
            ->method('getTypeOfField')
73
            ->with($this->logicalOr($this->equalTo('id'), $this->equalTo('field')))
74
            ->will(
75
                $this->returnCallback(
76
                    function ($arg) {
77
                        if ('id' === $arg) {
78
                            return 'integer';
79
                        } elseif ('field' === $arg) {
80
                            return 'string';
81
                        }
82
83
                        throw new \InvalidArgumentException();
84
                    }
85
                )
86
            );
87
88
        $this
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\Common\Persistence\Mapping\ClassMetadata.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
89
            ->metadata
90
            ->expects($this->any())
91
            ->method('hasAssociation')
92
            ->will($this->returnValue(false));
93
94
        $this
95
            ->metadata
96
            ->expects($this->any())
97
            ->method('getIdentifierFieldNames')
98
            ->will($this->returnValue(['id']));
99
100
        $this
101
            ->metadata
102
            ->expects($this->any())
103
            ->method('getReflectionClass')
104
            ->will($this->returnValue($refl));
105
106
        $this->hydratorByValue     = new DoctrineObjectHydrator(
107
            $this->objectManager,
108
            true
109
        );
110
        $this->hydratorByReference = new DoctrineObjectHydrator(
111
            $this->objectManager,
112
            false
113
        );
114
    }
115
116
    public function configureObjectManagerForNamingStrategyEntity()
117
    {
118
        $refl = new \ReflectionClass(Asset\NamingStrategyEntity::class);
119
120
        $this
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\Common\Persistence\Mapping\ClassMetadata.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
121
            ->metadata
122
            ->expects($this->any())
123
            ->method('getName')
124
            ->will($this->returnValue(Asset\NamingStrategyEntity::class));
125
        $this
126
            ->metadata
127
            ->expects($this->any())
128
            ->method('getAssociationNames')
129
            ->will($this->returnValue([]));
130
131
        $this
132
            ->metadata
133
            ->expects($this->any())
134
            ->method('getFieldNames')
135
            ->will($this->returnValue(['camelCase']));
136
137
        $this
138
            ->metadata
139
            ->expects($this->any())
140
            ->method('getTypeOfField')
141
            ->with($this->equalTo('camelCase'))
142
            ->will($this->returnValue('string'));
143
144
        $this
145
            ->metadata
146
            ->expects($this->any())
147
            ->method('hasAssociation')
148
            ->will($this->returnValue(false));
149
150
        $this
151
            ->metadata
152
            ->expects($this->any())
153
            ->method('getIdentifierFieldNames')
154
            ->will($this->returnValue(['camelCase']));
155
156
        $this
157
            ->metadata
158
            ->expects($this->any())
159
            ->method('getReflectionClass')
160
            ->will($this->returnValue($refl));
161
162
        $this->hydratorByValue     = new DoctrineObjectHydrator(
163
            $this->objectManager,
164
            true
165
        );
166
        $this->hydratorByReference = new DoctrineObjectHydrator(
167
            $this->objectManager,
168
            false
169
        );
170
    }
171
172
    public function configureObjectManagerForSimpleIsEntity()
173
    {
174
        $refl = new \ReflectionClass(Asset\SimpleIsEntity::class);
175
176
        $this
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\Common\Persistence\Mapping\ClassMetadata.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
177
            ->metadata
178
            ->expects($this->any())
179
            ->method('getName')
180
            ->will($this->returnValue(Asset\SimpleIsEntity::class));
181
        $this
182
            ->metadata
183
            ->expects($this->any())
184
            ->method('getAssociationNames')
185
            ->will($this->returnValue([]));
186
187
        $this
188
            ->metadata
189
            ->expects($this->any())
190
            ->method('getFieldNames')
191
            ->will($this->returnValue(['id', 'done']));
192
193
        $this
194
            ->metadata
195
            ->expects($this->any())
196
            ->method('getTypeOfField')
197
            ->with($this->logicalOr($this->equalTo('id'), $this->equalTo('done')))
198
            ->will(
199
                $this->returnCallback(
200
                    function ($arg) {
201
                        if ('id' === $arg) {
202
                            return 'integer';
203
                        } elseif ('done' === $arg) {
204
                            return 'boolean';
205
                        }
206
207
                        throw new \InvalidArgumentException();
208
                    }
209
                )
210
            );
211
212
        $this
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\Common\Persistence\Mapping\ClassMetadata.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
213
            ->metadata
214
            ->expects($this->any())
215
            ->method('hasAssociation')
216
            ->will($this->returnValue(false));
217
218
        $this
219
            ->metadata
220
            ->expects($this->any())
221
            ->method('getIdentifierFieldNames')
222
            ->will($this->returnValue(['id']));
223
224
        $this
225
            ->metadata
226
            ->expects($this->any())
227
            ->method('getReflectionClass')
228
            ->will($this->returnValue($refl));
229
230
        $this->hydratorByValue     = new DoctrineObjectHydrator(
231
            $this->objectManager,
232
            true
233
        );
234
        $this->hydratorByReference = new DoctrineObjectHydrator(
235
            $this->objectManager,
236
            false
237
        );
238
    }
239
240
    public function configureObjectManagerForSimpleEntityWithIsBoolean()
241
    {
242
        $refl = new \ReflectionClass(Asset\SimpleEntityWithIsBoolean::class);
243
244
        $this
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\Common\Persistence\Mapping\ClassMetadata.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
245
            ->metadata
246
            ->expects($this->any())
247
            ->method('getName')
248
            ->will($this->returnValue(Asset\SimpleEntityWithIsBoolean::class));
249
        $this
250
            ->metadata
251
            ->expects($this->any())
252
            ->method('getAssociationNames')
253
            ->will($this->returnValue([]));
254
255
        $this
256
            ->metadata
257
            ->expects($this->any())
258
            ->method('getFieldNames')
259
            ->will($this->returnValue(['id', 'isActive']));
260
261
        $this
262
            ->metadata
263
            ->expects($this->any())
264
            ->method('getTypeOfField')
265
            ->with($this->logicalOr($this->equalTo('id'), $this->equalTo('isActive')))
266
            ->will(
267
                $this->returnCallback(
268
                    function ($arg) {
269
                        if ('id' === $arg) {
270
                            return 'integer';
271
                        } elseif ('isActive' === $arg) {
272
                            return 'boolean';
273
                        }
274
275
                        throw new \InvalidArgumentException();
276
                    }
277
                )
278
            );
279
280
        $this
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\Common\Persistence\Mapping\ClassMetadata.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
281
            ->metadata
282
            ->expects($this->any())
283
            ->method('hasAssociation')
284
            ->will($this->returnValue(false));
285
286
        $this
287
            ->metadata
288
            ->expects($this->any())
289
            ->method('getIdentifierFieldNames')
290
            ->will($this->returnValue(['id']));
291
292
        $this
293
            ->metadata
294
            ->expects($this->any())
295
            ->method('getReflectionClass')
296
            ->will($this->returnValue($refl));
297
298
        $this->hydratorByValue     = new DoctrineObjectHydrator(
299
            $this->objectManager,
300
            true
301
        );
302
        $this->hydratorByReference = new DoctrineObjectHydrator(
303
            $this->objectManager,
304
            false
305
        );
306
    }
307
308
    public function configureObjectManagerForSimpleEntityWithStringId()
309
    {
310
        $refl = new \ReflectionClass(Asset\SimpleEntity::class);
311
312
        $this
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\Common\Persistence\Mapping\ClassMetadata.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
313
            ->metadata
314
            ->expects($this->any())
315
            ->method('getName')
316
            ->will($this->returnValue(Asset\SimpleEntity::class));
317
        $this
318
            ->metadata
319
            ->expects($this->any())
320
            ->method('getAssociationNames')
321
            ->will($this->returnValue([]));
322
323
        $this
324
            ->metadata
325
            ->expects($this->any())
326
            ->method('getFieldNames')
327
            ->will($this->returnValue(['id', 'field']));
328
329
        $this
330
            ->metadata
331
            ->expects($this->any())
332
            ->method('getTypeOfField')
333
            ->with($this->logicalOr($this->equalTo('id'), $this->equalTo('field')))
334
            ->will($this->returnValue('string'));
335
336
        $this
337
            ->metadata
338
            ->expects($this->any())
339
            ->method('hasAssociation')
340
            ->will($this->returnValue(false));
341
342
        $this
343
            ->metadata
344
            ->expects($this->any())
345
            ->method('getIdentifierFieldNames')
346
            ->will($this->returnValue(['id']));
347
348
        $this
349
            ->metadata
350
            ->expects($this->any())
351
            ->method('getReflectionClass')
352
            ->will($this->returnValue($refl));
353
354
        $this->hydratorByValue     = new DoctrineObjectHydrator(
355
            $this->objectManager,
356
            true
357
        );
358
        $this->hydratorByReference = new DoctrineObjectHydrator(
359
            $this->objectManager,
360
            false
361
        );
362
    }
363
364
    public function configureObjectManagerForSimpleEntityWithDateTime()
365
    {
366
        $refl = new \ReflectionClass(Asset\SimpleEntityWithDateTime::class);
367
368
        $this
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\Common\Persistence\Mapping\ClassMetadata.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
369
            ->metadata
370
            ->expects($this->any())
371
            ->method('getAssociationNames')
372
            ->will($this->returnValue([]));
373
374
        $this
375
            ->metadata
376
            ->expects($this->any())
377
            ->method('getFieldNames')
378
            ->will($this->returnValue(['id', 'date']));
379
380
        $this
381
            ->metadata
382
            ->expects($this->any())
383
            ->method('getTypeOfField')
384
            ->with($this->logicalOr($this->equalTo('id'), $this->equalTo('date')))
385
            ->will(
386
                $this->returnCallback(
387
                    function ($arg) {
388
                        if ($arg === 'id') {
389
                            return 'integer';
390
                        } elseif ($arg === 'date') {
391
                            return 'datetime';
392
                        }
393
394
                        throw new \InvalidArgumentException();
395
                    }
396
                )
397
            );
398
399
        $this
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\Common\Persistence\Mapping\ClassMetadata.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
400
            ->metadata
401
            ->expects($this->any())
402
            ->method('hasAssociation')
403
            ->will($this->returnValue(false));
404
405
        $this
406
            ->metadata
407
            ->expects($this->any())
408
            ->method('getIdentifierFieldNames')
409
            ->will($this->returnValue(['id']));
410
411
        $this
412
            ->metadata
413
            ->expects($this->any())
414
            ->method('getReflectionClass')
415
            ->will($this->returnValue($refl));
416
417
        $this->hydratorByValue     = new DoctrineObjectHydrator(
418
            $this->objectManager,
419
            true
420
        );
421
        $this->hydratorByReference = new DoctrineObjectHydrator(
422
            $this->objectManager,
423
            false
424
        );
425
    }
426
427
    public function configureObjectManagerForOneToOneEntity()
428
    {
429
        $refl = new \ReflectionClass(Asset\OneToOneEntity::class);
430
431
        $this
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\Common\Persistence\Mapping\ClassMetadata.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
432
            ->metadata
433
            ->expects($this->any())
434
            ->method('getFieldNames')
435
            ->will($this->returnValue(['id']));
436
437
        $this
438
            ->metadata
439
            ->expects($this->any())
440
            ->method('getAssociationNames')
441
            ->will($this->returnValue(['toOne']));
442
443
        $this
444
            ->metadata
445
            ->expects($this->any())
446
            ->method('getTypeOfField')
447
            ->with($this->logicalOr($this->equalTo('id'), $this->equalTo('toOne')))
448
            ->will(
449
                $this->returnCallback(
450
                    function ($arg) {
451
                        if ($arg === 'id') {
452
                            return 'integer';
453
                        } elseif ($arg === 'toOne') {
454
                            return Asset\SimpleEntity::class;
455
                        }
456
457
                        throw new \InvalidArgumentException();
458
                    }
459
                )
460
            );
461
462
        $this
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\Common\Persistence\Mapping\ClassMetadata.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
463
            ->metadata
464
            ->expects($this->any())
465
            ->method('hasAssociation')
466
            ->with($this->logicalOr($this->equalTo('id'), $this->equalTo('toOne')))
467
            ->will(
468
                $this->returnCallback(
469
                    function ($arg) {
470
                        if ($arg === 'id') {
471
                            return false;
472
                        } elseif ($arg === 'toOne') {
473
                            return true;
474
                        }
475
476
                        throw new \InvalidArgumentException();
477
                    }
478
                )
479
            );
480
481
        $this
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\Common\Persistence\Mapping\ClassMetadata.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
482
            ->metadata
483
            ->expects($this->any())
484
            ->method('isSingleValuedAssociation')
485
            ->with('toOne')
486
            ->will($this->returnValue(true));
487
488
        $this
489
            ->metadata
490
            ->expects($this->any())
491
            ->method('getAssociationTargetClass')
492
            ->with('toOne')
493
            ->will($this->returnValue(Asset\SimpleEntity::class));
494
495
        $this
496
            ->metadata
497
            ->expects($this->any())
498
            ->method('getReflectionClass')
499
            ->will($this->returnValue($refl));
500
501
        $this
502
            ->metadata
503
            ->expects($this->any())
504
            ->method('getIdentifier')
505
            ->will($this->returnValue(["id"]));
506
507
        $this->hydratorByValue     = new DoctrineObjectHydrator(
508
            $this->objectManager,
509
            true
510
        );
511
        $this->hydratorByReference = new DoctrineObjectHydrator(
512
            $this->objectManager,
513
            false
514
        );
515
    }
516
517
    public function configureObjectManagerForOneToOneEntityNotNullable()
518
    {
519
        $refl = new \ReflectionClass(Asset\OneToOneEntityNotNullable::class);
520
521
        $this
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\Common\Persistence\Mapping\ClassMetadata.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
522
            ->metadata
523
            ->expects($this->any())
524
            ->method('getFieldNames')
525
            ->will($this->returnValue(['id']));
526
527
        $this
528
            ->metadata
529
            ->expects($this->any())
530
            ->method('getAssociationNames')
531
            ->will($this->returnValue(['toOne']));
532
533
        $this
534
            ->metadata
535
            ->expects($this->any())
536
            ->method('getTypeOfField')
537
            ->with(
538
                $this->logicalOr(
539
                    $this->equalTo('id'),
540
                    $this->equalTo('toOne'),
541
                    $this->equalTo('field')
542
                )
543
            )
544
            ->will(
545
                $this->returnCallback(
546
                    function ($arg) {
547
                        if ($arg === 'id') {
548
                            return 'integer';
549
                        } elseif ($arg === 'toOne') {
550
                            return Asset\SimpleEntity::class;
551
                        } elseif ($arg === 'field') {
552
                            return 'string';
553
                        }
554
555
                        throw new \InvalidArgumentException();
556
                    }
557
                )
558
            );
559
560
        $this
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\Common\Persistence\Mapping\ClassMetadata.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
561
            ->metadata
562
            ->expects($this->any())
563
            ->method('hasAssociation')
564
            ->with(
565
                $this->logicalOr(
566
                    $this->equalTo('id'),
567
                    $this->equalTo('toOne'),
568
                    $this->equalTo('field')
569
                )
570
            )
571
            ->will(
572
                $this->returnCallback(
573
                    function ($arg) {
574
                        if ($arg === 'id' || $arg === 'field') {
575
                            return false;
576
                        } elseif ($arg === 'toOne') {
577
                            return true;
578
                        }
579
580
                        throw new \InvalidArgumentException();
581
                    }
582
                )
583
            );
584
585
        $this
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\Common\Persistence\Mapping\ClassMetadata.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
586
            ->metadata
587
            ->expects($this->any())
588
            ->method('isSingleValuedAssociation')
589
            ->with('toOne')
590
            ->will($this->returnValue(true));
591
592
        $this
593
            ->metadata
594
            ->expects($this->any())
595
            ->method('getAssociationTargetClass')
596
            ->with('toOne')
597
            ->will($this->returnValue(Asset\SimpleEntity::class));
598
599
        $this
600
            ->metadata
601
            ->expects($this->any())
602
            ->method('getReflectionClass')
603
            ->will($this->returnValue($refl));
604
605
        $this
606
            ->metadata
607
            ->expects($this->any())
608
            ->method('getIdentifier')
609
            ->will($this->returnValue(["id"]));
610
611
        $this->hydratorByValue     = new DoctrineObjectHydrator(
612
            $this->objectManager,
613
            true
614
        );
615
        $this->hydratorByReference = new DoctrineObjectHydrator(
616
            $this->objectManager,
617
            false
618
        );
619
    }
620
621
    public function configureObjectManagerForOneToManyEntity()
622
    {
623
        $refl = new \ReflectionClass(Asset\OneToManyEntity::class);
624
625
        $this
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\Common\Persistence\Mapping\ClassMetadata.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
626
            ->metadata
627
            ->expects($this->any())
628
            ->method('getFieldNames')
629
            ->will($this->returnValue(['id']));
630
631
        $this
632
            ->metadata
633
            ->expects($this->any())
634
            ->method('getAssociationNames')
635
            ->will($this->returnValue(['entities']));
636
637
        $this
638
            ->metadata
639
            ->expects($this->any())
640
            ->method('getTypeOfField')
641
            ->with(
642
                $this->logicalOr(
643
                    $this->equalTo('id'),
644
                    $this->equalTo('entities'),
645
                    $this->equalTo('field')
646
                )
647
            )
648
            ->will(
649
                $this->returnCallback(
650
                    function ($arg) {
651
                        if ($arg === 'id') {
652
                            return 'integer';
653
                        } elseif ($arg === 'field') {
654
                            return 'string';
655
                        } elseif ($arg === 'entities') {
656
                            return ArrayCollection::class;
657
                        }
658
659
                        throw new \InvalidArgumentException();
660
                    }
661
                )
662
            );
663
664
        $this
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\Common\Persistence\Mapping\ClassMetadata.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
665
            ->metadata
666
            ->expects($this->any())
667
            ->method('hasAssociation')
668
            ->with($this->logicalOr($this->equalTo('id'), $this->equalTo('entities'), $this->equalTo('field')))
669
            ->will(
670
                $this->returnCallback(
671
                    function ($arg) {
672
                        if ($arg === 'id') {
673
                            return false;
674
                        } elseif ($arg === 'field') {
675
                            return false;
676
                        } elseif ($arg === 'entities') {
677
                            return true;
678
                        }
679
680
                        throw new \InvalidArgumentException();
681
                    }
682
                )
683
            );
684
685
        $this
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\Common\Persistence\Mapping\ClassMetadata.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
686
            ->metadata
687
            ->expects($this->any())
688
            ->method('isSingleValuedAssociation')
689
            ->with('entities')
690
            ->will($this->returnValue(false));
691
692
        $this
693
            ->metadata
694
            ->expects($this->any())
695
            ->method('isCollectionValuedAssociation')
696
            ->with('entities')
697
            ->will($this->returnValue(true));
698
699
        $this
700
            ->metadata
701
            ->expects($this->any())
702
            ->method('getAssociationTargetClass')
703
            ->with('entities')
704
            ->will($this->returnValue(Asset\SimpleEntity::class));
705
706
        $this
707
            ->metadata
708
            ->expects($this->any())
709
            ->method('getReflectionClass')
710
            ->will($this->returnValue($refl));
711
712
        $this->metadata
713
            ->expects($this->any())
714
            ->method('getIdentifier')
715
            ->will($this->returnValue(["id"]));
716
717
        $this->hydratorByValue     = new DoctrineObjectHydrator(
718
            $this->objectManager,
719
            true
720
        );
721
        $this->hydratorByReference = new DoctrineObjectHydrator(
722
            $this->objectManager,
723
            false
724
        );
725
    }
726
727
    public function configureObjectManagerForOneToManyArrayEntity()
728
    {
729
        $refl = new \ReflectionClass(Asset\OneToManyArrayEntity::class);
730
731
        $this
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\Common\Persistence\Mapping\ClassMetadata.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
732
            ->metadata
733
            ->expects($this->any())
734
            ->method('getFieldNames')
735
            ->will($this->returnValue(['id']));
736
737
        $this
738
            ->metadata
739
            ->expects($this->any())
740
            ->method('getAssociationNames')
741
            ->will($this->returnValue(['entities']));
742
743
        $this
744
            ->metadata
745
            ->expects($this->any())
746
            ->method('getTypeOfField')
747
            ->with(
748
                $this->logicalOr(
749
                    $this->equalTo('id'),
750
                    $this->equalTo('entities'),
751
                    $this->equalTo('field')
752
                )
753
            )
754
            ->will(
755
                $this->returnCallback(
756
                    function ($arg) {
757
                        if ($arg === 'id') {
758
                            return 'integer';
759
                        } elseif ($arg === 'field') {
760
                            return 'string';
761
                        } elseif ($arg === 'entities') {
762
                            return ArrayCollection::class;
763
                        }
764
765
                        throw new \InvalidArgumentException();
766
                    }
767
                )
768
            );
769
770
        $this
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\Common\Persistence\Mapping\ClassMetadata.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
771
            ->metadata
772
            ->expects($this->any())
773
            ->method('hasAssociation')
774
            ->with($this->logicalOr($this->equalTo('id'), $this->equalTo('entities')))
775
            ->will(
776
                $this->returnCallback(
777
                    function ($arg) {
778
                        if ($arg === 'id') {
779
                            return false;
780
                        } elseif ($arg === 'field') {
781
                            return 'string';
782
                        } elseif ($arg === 'entities') {
783
                            return true;
784
                        }
785
786
                        throw new \InvalidArgumentException();
787
                    }
788
                )
789
            );
790
791
        $this
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\Common\Persistence\Mapping\ClassMetadata.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
792
            ->metadata
793
            ->expects($this->any())
794
            ->method('isSingleValuedAssociation')
795
            ->with('entities')
796
            ->will($this->returnValue(false));
797
798
        $this
799
            ->metadata
800
            ->expects($this->any())
801
            ->method('isCollectionValuedAssociation')
802
            ->with('entities')
803
            ->will($this->returnValue(true));
804
805
        $this
806
            ->metadata
807
            ->expects($this->any())
808
            ->method('getAssociationTargetClass')
809
            ->with('entities')
810
            ->will($this->returnValue(Asset\SimpleEntity::class));
811
812
        $this
813
            ->metadata
814
            ->expects($this->any())
815
            ->method('getReflectionClass')
816
            ->will($this->returnValue($refl));
817
818
        $this->metadata
819
            ->expects($this->any())
820
            ->method('getIdentifier')
821
            ->will($this->returnValue(["id"]));
822
823
        $this->hydratorByValue     = new DoctrineObjectHydrator(
824
            $this->objectManager,
825
            true
826
        );
827
        $this->hydratorByReference = new DoctrineObjectHydrator(
828
            $this->objectManager,
829
            false
830
        );
831
    }
832
833
    public function testObjectIsPassedForContextToStrategies()
834
    {
835
        $entity = new Asset\ContextEntity();
836
        $entity->setId(2);
837
        $entity->setField('foo');
838
839
        $this->configureObjectManagerForSimpleEntity();
840
841
        $hydrator = $this->hydratorByValue;
842
        $entity   = $hydrator->hydrate(['id' => 3, 'field' => 'bar'], $entity);
843
        $this->assertEquals(['id' => 3, 'field' => 'bar'], $hydrator->extract($entity));
844
845
        $hydrator->addStrategy('id', new Asset\ContextStrategy());
846
        $entity = $hydrator->hydrate(['id' => 3, 'field' => 'bar'], $entity);
847
        $this->assertEquals(['id' => '3barbar', 'field' => 'bar'], $hydrator->extract($entity));
848
    }
849
850
    public function testCanExtractSimpleEntityByValue()
851
    {
852
        // When using extraction by value, it will use the public API of the entity to retrieve values (getters)
853
        $entity = new Asset\SimpleEntity();
854
        $entity->setId(2);
855
        $entity->setField('foo', false);
856
857
        $this->configureObjectManagerForSimpleEntity();
858
859
        $data = $this->hydratorByValue->extract($entity);
860
        $this->assertEquals(['id' => 2, 'field' => 'From getter: foo'], $data);
861
    }
862
863
    public function testCanExtractSimpleEntityByReference()
864
    {
865
        // When using extraction by reference, it won't use the public API of entity (getters won't be called)
866
        $entity = new Asset\SimpleEntity();
867
        $entity->setId(2);
868
        $entity->setField('foo', false);
869
870
        $this->configureObjectManagerForSimpleEntity();
871
872
        $data = $this->hydratorByReference->extract($entity);
873
        $this->assertEquals(['id' => 2, 'field' => 'foo'], $data);
874
    }
875
876
    public function testCanHydrateSimpleEntityByValue()
877
    {
878
        // When using hydration by value, it will use the public API of the entity to set values (setters)
879
        $entity = new Asset\SimpleEntity();
880
        $this->configureObjectManagerForSimpleEntity();
881
        $data = ['field' => 'foo'];
882
883
        $entity = $this->hydratorByValue->hydrate($data, $entity);
884
885
        $this->assertInstanceOf(Asset\SimpleEntity::class, $entity);
886
        $this->assertEquals('From setter: foo', $entity->getField(false));
887
    }
888
889
    /**
890
     * When using hydration by value, it will use the public API of the entity to set values (setters)
891
     *
892
     * @covers \DoctrineModule\Stdlib\Hydrator\DoctrineObject::hydrateByValue
893
     */
894
    public function testCanHydrateSimpleEntityWithStringIdByValue()
895
    {
896
        $entity = new Asset\SimpleEntity();
897
        $data   = ['id' => 'bar', 'field' => 'foo'];
898
899
        $this->configureObjectManagerForSimpleEntityWithStringId();
900
901
        $entity = $this->hydratorByValue->hydrate($data, $entity);
902
903
        $this->assertInstanceOf(Asset\SimpleEntity::class, $entity);
904
        $this->assertEquals('From setter: foo', $entity->getField(false));
905
    }
906
907
    public function testCanHydrateSimpleEntityByReference()
908
    {
909
        // When using hydration by reference, it won't use the public API of the entity to set values (setters)
910
        $entity = new Asset\SimpleEntity();
911
        $this->configureObjectManagerForSimpleEntity();
912
        $data = ['field' => 'foo'];
913
914
        $entity = $this->hydratorByReference->hydrate($data, $entity);
915
916
        $this->assertInstanceOf(Asset\SimpleEntity::class, $entity);
917
        $this->assertEquals('foo', $entity->getField(false));
918
    }
919
920
    /**
921
     * When using hydration by reference, it won't use the public API of the entity to set values (getters)
922
     *
923
     * @covers \DoctrineModule\Stdlib\Hydrator\DoctrineObject::hydrateByReference
924
     */
925
    public function testCanHydrateSimpleEntityWithStringIdByReference()
926
    {
927
        $entity = new Asset\SimpleEntity();
928
        $data   = ['id' => 'bar', 'field' => 'foo'];
929
930
        $this->configureObjectManagerForSimpleEntityWithStringId();
931
932
        $entity = $this->hydratorByReference->hydrate($data, $entity);
933
934
        $this->assertInstanceOf(Asset\SimpleEntity::class, $entity);
935
        $this->assertEquals('foo', $entity->getField(false));
936
    }
937
938
    public function testReuseExistingEntityIfDataArrayContainsIdentifier()
939
    {
940
        // When using hydration by reference, it won't use the public API of the entity to set values (setters)
941
        $entity = new Asset\SimpleEntity();
942
943
        $this->configureObjectManagerForSimpleEntity();
944
        $data = ['id' => 1];
945
946
        $entityInDatabaseWithIdOfOne = new Asset\SimpleEntity();
947
        $entityInDatabaseWithIdOfOne->setId(1);
948
        $entityInDatabaseWithIdOfOne->setField('bar', false);
949
950
        $this
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\Common\Persistence\ObjectManager.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
951
            ->objectManager
952
            ->expects($this->once())
953
            ->method('find')
954
            ->with(Asset\SimpleEntity::class, ['id' => 1])
955
            ->will($this->returnValue($entityInDatabaseWithIdOfOne));
956
957
        $entity = $this->hydratorByValue->hydrate($data, $entity);
958
959
        $this->assertInstanceOf(Asset\SimpleEntity::class, $entity);
960
        $this->assertEquals('bar', $entity->getField(false));
961
    }
962
963
    /**
964
     * Test for https://github.com/doctrine/DoctrineModule/issues/456
965
     */
966
    public function testReuseExistingEntityIfDataArrayContainsIdentifierWithZeroIdentifier()
967
    {
968
        // When using hydration by reference, it won't use the public API of the entity to set values (setters)
969
        $entity = new Asset\SimpleEntity();
970
971
        $this->configureObjectManagerForSimpleEntity();
972
        $data = ['id' => 0];
973
974
        $entityInDatabaseWithIdOfOne = new Asset\SimpleEntity();
975
        $entityInDatabaseWithIdOfOne->setId(0);
976
        $entityInDatabaseWithIdOfOne->setField('bar', false);
977
978
        $this
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\Common\Persistence\ObjectManager.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
979
            ->objectManager
980
            ->expects($this->once())
981
            ->method('find')
982
            ->with(Asset\SimpleEntity::class, ['id' => 0])
983
            ->will($this->returnValue($entityInDatabaseWithIdOfOne));
984
985
        $entity = $this->hydratorByValue->hydrate($data, $entity);
986
987
        $this->assertInstanceOf(Asset\SimpleEntity::class, $entity);
988
        $this->assertEquals('bar', $entity->getField(false));
989
    }
990
991
    public function testExtractOneToOneAssociationByValue()
992
    {
993
        // When using extraction by value, it will use the public API of the entity to retrieve values (getters)
994
        $toOne = new Asset\SimpleEntity();
995
        $toOne->setId(2);
996
        $toOne->setField('foo', false);
997
998
        $entity = new Asset\OneToOneEntity();
999
        $entity->setId(2);
1000
        $entity->setToOne($toOne);
1001
1002
        $this->configureObjectManagerForOneToOneEntity();
1003
1004
        $data = $this->hydratorByValue->extract($entity);
1005
1006
        $this->assertEquals(2, $data['id']);
1007
        $this->assertInstanceOf(Asset\SimpleEntity::class, $data['toOne']);
1008
        $this->assertEquals('Modified from getToOne getter', $data['toOne']->getField(false));
1009
        $this->assertSame($toOne, $data['toOne']);
1010
    }
1011
1012
    public function testExtractOneToOneAssociationByReference()
1013
    {
1014
        // When using extraction by value, it will use the public API of the entity to retrieve values (getters)
1015
        $toOne = new Asset\SimpleEntity();
1016
        $toOne->setId(2);
1017
        $toOne->setField('foo', false);
1018
1019
        $entity = new Asset\OneToOneEntity();
1020
        $entity->setId(2);
1021
        $entity->setToOne($toOne, false);
1022
1023
        $this->configureObjectManagerForOneToOneEntity();
1024
1025
        $data = $this->hydratorByReference->extract($entity);
1026
1027
        $this->assertEquals(2, $data['id']);
1028
        $this->assertInstanceOf(Asset\SimpleEntity::class, $data['toOne']);
1029
        $this->assertEquals('foo', $data['toOne']->getField(false));
1030
        $this->assertSame($toOne, $data['toOne']);
1031
    }
1032
1033
    public function testHydrateOneToOneAssociationByValue()
1034
    {
1035
        // When using hydration by value, it will use the public API of the entity to set values (setters)
1036
        $toOne = new Asset\SimpleEntity();
1037
        $toOne->setId(2);
1038
        $toOne->setField('foo', false);
1039
1040
        $entity = new Asset\OneToOneEntity();
1041
        $this->configureObjectManagerForOneToOneEntity();
1042
1043
        $data = ['toOne' => $toOne];
1044
1045
        $entity = $this->hydratorByValue->hydrate($data, $entity);
1046
1047
        $this->assertInstanceOf(Asset\OneToOneEntity::class, $entity);
1048
        $this->assertInstanceOf(Asset\SimpleEntity::class, $entity->getToOne(false));
1049
        $this->assertEquals('Modified from setToOne setter', $entity->getToOne(false)->getField(false));
1050
    }
1051
1052
    public function testHydrateOneToOneAssociationByReference()
1053
    {
1054
        // When using hydration by value, it will use the public API of the entity to set values (setters)
1055
        $toOne = new Asset\SimpleEntity();
1056
        $toOne->setId(2);
1057
        $toOne->setField('foo', false);
1058
1059
        $entity = new Asset\OneToOneEntity();
1060
        $this->configureObjectManagerForOneToOneEntity();
1061
1062
        $data = ['toOne' => $toOne];
1063
1064
        $entity = $this->hydratorByReference->hydrate($data, $entity);
1065
1066
        $this->assertInstanceOf(Asset\OneToOneEntity::class, $entity);
1067
        $this->assertInstanceOf(Asset\SimpleEntity::class, $entity->getToOne(false));
1068
        $this->assertEquals('foo', $entity->getToOne(false)->getField(false));
1069
    }
1070
1071
    public function testHydrateOneToOneAssociationByValueUsingIdentifierForRelation()
1072
    {
1073
        // When using hydration by value, it will use the public API of the entity to set values (setters)
1074
        $entity = new Asset\OneToOneEntity();
1075
        $this->configureObjectManagerForOneToOneEntity();
1076
1077
        // Use entity of id 1 as relation
1078
        $data = ['toOne' => 1];
1079
1080
        $entityInDatabaseWithIdOfOne = new Asset\SimpleEntity();
1081
        $entityInDatabaseWithIdOfOne->setId(1);
1082
        $entityInDatabaseWithIdOfOne->setField('bar', false);
1083
1084
        $this
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\Common\Persistence\ObjectManager.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
1085
            ->objectManager
1086
            ->expects($this->once())
1087
            ->method('find')
1088
            ->with(Asset\SimpleEntity::class, 1)
1089
            ->will($this->returnValue($entityInDatabaseWithIdOfOne));
1090
1091
        $entity = $this->hydratorByValue->hydrate($data, $entity);
1092
1093
        $this->assertInstanceOf(Asset\OneToOneEntity::class, $entity);
1094
        $this->assertInstanceOf(Asset\SimpleEntity::class, $entity->getToOne(false));
1095
        $this->assertSame($entityInDatabaseWithIdOfOne, $entity->getToOne(false));
1096
    }
1097
1098
    public function testHydrateOneToOneAssociationByReferenceUsingIdentifierForRelation()
1099
    {
1100
        // When using hydration by reference, it won't use the public API of the entity to set values (setters)
1101
        $entity = new Asset\OneToOneEntity();
1102
        $this->configureObjectManagerForOneToOneEntity();
1103
1104
        // Use entity of id 1 as relation
1105
        $data = ['toOne' => 1];
1106
1107
        $entityInDatabaseWithIdOfOne = new Asset\SimpleEntity();
1108
        $entityInDatabaseWithIdOfOne->setId(1);
1109
        $entityInDatabaseWithIdOfOne->setField('bar', false);
1110
1111
        $this
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\Common\Persistence\ObjectManager.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
1112
            ->objectManager
1113
            ->expects($this->once())
1114
            ->method('find')
1115
            ->with(Asset\SimpleEntity::class, 1)
1116
            ->will($this->returnValue($entityInDatabaseWithIdOfOne));
1117
1118
        $entity = $this->hydratorByReference->hydrate($data, $entity);
1119
1120
        $this->assertInstanceOf(Asset\OneToOneEntity::class, $entity);
1121
        $this->assertInstanceOf(Asset\SimpleEntity::class, $entity->getToOne(false));
1122
        $this->assertSame($entityInDatabaseWithIdOfOne, $entity->getToOne(false));
1123
    }
1124
1125
    public function testHydrateOneToOneAssociationByValueUsingIdentifierArrayForRelation()
1126
    {
1127
        // When using hydration by value, it will use the public API of the entity to set values (setters)
1128
        $entity = new Asset\OneToOneEntity();
1129
        $this->configureObjectManagerForOneToOneEntity();
1130
1131
        // Use entity of id 1 as relation
1132
        $data = ['toOne' => ['id' => 1]];
1133
1134
        $entityInDatabaseWithIdOfOne = new Asset\SimpleEntity();
1135
        $entityInDatabaseWithIdOfOne->setId(1);
1136
        $entityInDatabaseWithIdOfOne->setField('bar', false);
1137
1138
        $this
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\Common\Persistence\ObjectManager.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
1139
            ->objectManager
1140
            ->expects($this->once())
1141
            ->method('find')
1142
            ->with(Asset\SimpleEntity::class, ['id' => 1])
1143
            ->will($this->returnValue($entityInDatabaseWithIdOfOne));
1144
1145
        $entity = $this->hydratorByValue->hydrate($data, $entity);
1146
1147
        $this->assertInstanceOf(Asset\OneToOneEntity::class, $entity);
1148
        $this->assertInstanceOf(Asset\SimpleEntity::class, $entity->getToOne(false));
1149
        $this->assertSame($entityInDatabaseWithIdOfOne, $entity->getToOne(false));
1150
    }
1151
1152
    public function testHydrateOneToOneAssociationByValueUsingFullArrayForRelation()
1153
    {
1154
        $entity = new Asset\OneToOneEntityNotNullable();
1155
        $this->configureObjectManagerForOneToOneEntityNotNullable();
1156
1157
        // Use entity of id 1 as relation
1158
        $data = ['toOne' => ['id' => 1, 'field' => 'foo']];
1159
1160
        $entityInDatabaseWithIdOfOne = new Asset\SimpleEntity();
1161
        $entityInDatabaseWithIdOfOne->setId(1);
1162
        $entityInDatabaseWithIdOfOne->setField('bar', false);
1163
1164
        $this
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\Common\Persistence\ObjectManager.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
1165
            ->objectManager
1166
            ->expects($this->once())
1167
            ->method('find')
1168
            ->with(Asset\SimpleEntity::class, ['id' => 1])
1169
            ->will($this->returnValue($entityInDatabaseWithIdOfOne));
1170
1171
        $entity = $this->hydratorByValue->hydrate($data, $entity);
1172
1173
        $this->assertInstanceOf(Asset\OneToOneEntityNotNullable::class, $entity);
1174
        $this->assertInstanceOf(Asset\SimpleEntity::class, $entity->getToOne(false));
1175
        $this->assertSame($entityInDatabaseWithIdOfOne, $entity->getToOne(false));
1176
        $this->assertEquals(
1177
            'From getter: Modified from setToOne setter',
1178
            $entityInDatabaseWithIdOfOne->getField()
1179
        );
1180
    }
1181
1182
    public function testHydrateOneToOneAssociationByReferenceUsingIdentifierArrayForRelation()
1183
    {
1184
        // When using hydration by reference, it won't use the public API of the entity to set values (setters)
1185
        $entity = new Asset\OneToOneEntity();
1186
        $this->configureObjectManagerForOneToOneEntity();
1187
1188
        // Use entity of id 1 as relation
1189
        $data = ['toOne' => ['id' => 1]];
1190
1191
        $entityInDatabaseWithIdOfOne = new Asset\SimpleEntity();
1192
        $entityInDatabaseWithIdOfOne->setId(1);
1193
        $entityInDatabaseWithIdOfOne->setField('bar', false);
1194
1195
        $this
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\Common\Persistence\ObjectManager.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
1196
            ->objectManager
1197
            ->expects($this->once())
1198
            ->method('find')
1199
            ->with(Asset\SimpleEntity::class, ['id' => 1])
1200
            ->will($this->returnValue($entityInDatabaseWithIdOfOne));
1201
1202
        $entity = $this->hydratorByReference->hydrate($data, $entity);
1203
1204
        $this->assertInstanceOf(Asset\OneToOneEntity::class, $entity);
1205
        $this->assertInstanceOf(Asset\SimpleEntity::class, $entity->getToOne(false));
1206
        $this->assertSame($entityInDatabaseWithIdOfOne, $entity->getToOne(false));
1207
    }
1208
1209
    public function testCanHydrateOneToOneAssociationByValueWithNullableRelation()
1210
    {
1211
        // When using hydration by value, it will use the public API of the entity to retrieve values (setters)
1212
        $entity = new Asset\OneToOneEntity();
1213
        $this->configureObjectManagerForOneToOneEntity();
1214
1215
        $data = ['toOne' => null];
1216
1217
        $this->metadata->expects($this->once())
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\Common\Persistence\Mapping\ClassMetadata.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
1218
                       ->method('hasAssociation');
1219
1220
        $object = $this->hydratorByValue->hydrate($data, $entity);
1221
        $this->assertNull($object->getToOne(false));
1222
    }
1223
1224
    public function testCanHydrateOneToOneAssociationByReferenceWithNullableRelation()
1225
    {
1226
        // When using hydration by reference, it won't use the public API of the entity to retrieve values (setters)
1227
        $entity = new Asset\OneToOneEntity();
1228
1229
        $this->configureObjectManagerForOneToOneEntity();
1230
        $this->objectManager->expects($this->never())->method('find');
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\Common\Persistence\ObjectManager.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
1231
        $this->metadata->expects($this->once())->method('hasAssociation');
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\Common\Persistence\Mapping\ClassMetadata.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
1232
1233
        $data = ['toOne' => null];
1234
1235
        $object = $this->hydratorByReference->hydrate($data, $entity);
1236
        $this->assertNull($object->getToOne(false));
1237
    }
1238
1239
    public function testExtractOneToManyAssociationByValue()
1240
    {
1241
        // When using extraction by value, it will use the public API of the entity to retrieve values (getters)
1242
        $toMany1 = new Asset\SimpleEntity();
1243
        $toMany1->setId(2);
1244
        $toMany1->setField('foo', false);
1245
1246
        $toMany2 = new Asset\SimpleEntity();
1247
        $toMany2->setId(3);
1248
        $toMany2->setField('bar', false);
1249
1250
        $collection = new ArrayCollection([$toMany1, $toMany2]);
1251
1252
        $entity = new Asset\OneToManyEntity();
1253
        $entity->setId(4);
1254
        $entity->addEntities($collection);
1255
1256
        $this->configureObjectManagerForOneToManyEntity();
1257
1258
        $data = $this->hydratorByValue->extract($entity);
1259
1260
        $this->assertEquals(4, $data['id']);
1261
        $this->assertInstanceOf(Collection::class, $data['entities']);
1262
1263
        $this->assertEquals($toMany1->getId(), $data['entities'][0]->getId());
1264
        $this->assertSame($toMany1, $data['entities'][0]);
1265
        $this->assertEquals($toMany2->getId(), $data['entities'][1]->getId());
1266
        $this->assertSame($toMany2, $data['entities'][1]);
1267
    }
1268
1269
    /**
1270
     * @depends testExtractOneToManyAssociationByValue
1271
     */
1272
    public function testExtractOneToManyByValueWithArray()
1273
    {
1274
        // When using extraction by value, it will use the public API of the entity to retrieve values (getters)
1275
        $toMany1 = new Asset\SimpleEntity();
1276
        $toMany1->setId(2);
1277
        $toMany1->setField('foo', false);
1278
1279
        $toMany2 = new Asset\SimpleEntity();
1280
        $toMany2->setId(3);
1281
        $toMany2->setField('bar', false);
1282
1283
        $collection = new ArrayCollection([$toMany1, $toMany2]);
1284
1285
        $entity = new Asset\OneToManyArrayEntity();
1286
        $entity->setId(4);
1287
        $entity->addEntities($collection);
1288
1289
        $this->configureObjectManagerForOneToManyArrayEntity();
1290
1291
        $data = $this->hydratorByValue->extract($entity);
1292
1293
        $this->assertEquals(4, $data['id']);
1294
        $this->assertInternalType('array', $data['entities']);
1295
1296
        $this->assertEquals($toMany1->getId(), $data['entities'][0]->getId());
1297
        $this->assertSame($toMany1, $data['entities'][0]);
1298
        $this->assertEquals($toMany2->getId(), $data['entities'][1]->getId());
1299
        $this->assertSame($toMany2, $data['entities'][1]);
1300
    }
1301
1302
    public function testExtractOneToManyAssociationByReference()
1303
    {
1304
        // When using extraction by reference, it won't use the public API of the entity to retrieve values (getters)
1305
        $toMany1 = new Asset\SimpleEntity();
1306
        $toMany1->setId(2);
1307
        $toMany1->setField('foo', false);
1308
1309
        $toMany2 = new Asset\SimpleEntity();
1310
        $toMany2->setId(3);
1311
        $toMany2->setField('bar', false);
1312
1313
        $collection = new ArrayCollection([$toMany1, $toMany2]);
1314
1315
        $entity = new Asset\OneToManyEntity();
1316
        $entity->setId(4);
1317
        $entity->addEntities($collection);
1318
1319
        $this->configureObjectManagerForOneToManyEntity();
1320
1321
        $data = $this->hydratorByReference->extract($entity);
1322
1323
        $this->assertEquals(4, $data['id']);
1324
        $this->assertInstanceOf(Collection::class, $data['entities']);
1325
1326
        $this->assertEquals($toMany1->getId(), $data['entities'][0]->getId());
1327
        $this->assertSame($toMany1, $data['entities'][0]);
1328
        $this->assertEquals($toMany2->getId(), $data['entities'][1]->getId());
1329
        $this->assertSame($toMany2, $data['entities'][1]);
1330
    }
1331
1332
    /**
1333
     * @depends testExtractOneToManyAssociationByReference
1334
     */
1335
    public function testExtractOneToManyArrayByReference()
1336
    {
1337
        // When using extraction by reference, it won't use the public API of the entity to retrieve values (getters)
1338
        $toMany1 = new Asset\SimpleEntity();
1339
        $toMany1->setId(2);
1340
        $toMany1->setField('foo', false);
1341
1342
        $toMany2 = new Asset\SimpleEntity();
1343
        $toMany2->setId(3);
1344
        $toMany2->setField('bar', false);
1345
1346
        $collection = new ArrayCollection([$toMany1, $toMany2]);
1347
1348
        $entity = new Asset\OneToManyArrayEntity();
1349
        $entity->setId(4);
1350
        $entity->addEntities($collection);
1351
1352
        $this->configureObjectManagerForOneToManyArrayEntity();
1353
1354
        $data = $this->hydratorByReference->extract($entity);
1355
1356
        $this->assertEquals(4, $data['id']);
1357
        $this->assertInstanceOf(Collection::class, $data['entities']);
1358
1359
        $this->assertEquals($toMany1->getId(), $data['entities'][0]->getId());
1360
        $this->assertSame($toMany1, $data['entities'][0]);
1361
        $this->assertEquals($toMany2->getId(), $data['entities'][1]->getId());
1362
        $this->assertSame($toMany2, $data['entities'][1]);
1363
    }
1364
1365
    public function testHydrateOneToManyAssociationByValue()
1366
    {
1367
        // When using hydration by value, it will use the public API of the entity to set values (setters)
1368
        $toMany1 = new Asset\SimpleEntity();
1369
        $toMany1->setId(2);
1370
        $toMany1->setField('foo', false);
1371
1372
        $toMany2 = new Asset\SimpleEntity();
1373
        $toMany2->setId(3);
1374
        $toMany2->setField('bar', false);
1375
1376
        $entity = new Asset\OneToManyEntity();
1377
        $this->configureObjectManagerForOneToManyEntity();
1378
1379
        $data = ['entities' => [$toMany1, $toMany2]];
1380
1381
        $entity = $this->hydratorByValue->hydrate($data, $entity);
1382
1383
        $this->assertInstanceOf(Asset\OneToManyEntity::class, $entity);
1384
1385
        $entities = $entity->getEntities(false);
1386
1387
        foreach ($entities as $en) {
1388
            $this->assertInstanceOf(Asset\SimpleEntity::class, $en);
1389
            $this->assertInternalType('integer', $en->getId());
1390
            $this->assertContains('Modified from addEntities adder', $en->getField(false));
1391
        }
1392
1393
        $this->assertEquals(2, $entities[0]->getId());
1394
        $this->assertSame($toMany1, $entities[0]);
1395
1396
        $this->assertEquals(3, $entities[1]->getId());
1397
        $this->assertSame($toMany2, $entities[1]);
1398
    }
1399
1400
    /**
1401
     * @depends testHydrateOneToManyAssociationByValue
1402
     */
1403
    public function testHydrateOneToManyArrayByValue()
1404
    {
1405
        // When using hydration by value, it will use the public API of the entity to set values (setters)
1406
        $toMany1 = new Asset\SimpleEntity();
1407
        $toMany1->setId(2);
1408
        $toMany1->setField('foo', false);
1409
1410
        $toMany2 = new Asset\SimpleEntity();
1411
        $toMany2->setId(3);
1412
        $toMany2->setField('bar', false);
1413
1414
        $entity = new Asset\OneToManyArrayEntity();
1415
        $this->configureObjectManagerForOneToManyArrayEntity();
1416
1417
        $data = ['entities' => [$toMany1, $toMany2]];
1418
1419
        $entity = $this->hydratorByValue->hydrate($data, $entity);
1420
1421
        $this->assertInstanceOf(Asset\OneToManyArrayEntity::class, $entity);
1422
1423
        $entities = $entity->getEntities(false);
1424
1425
        foreach ($entities as $en) {
1426
            $this->assertInstanceOf(Asset\SimpleEntity::class, $en);
1427
            $this->assertInternalType('integer', $en->getId());
1428
            $this->assertContains('Modified from addEntities adder', $en->getField(false));
1429
        }
1430
1431
        $this->assertEquals(2, $entities[0]->getId());
1432
        $this->assertSame($toMany1, $entities[0]);
1433
1434
        $this->assertEquals(3, $entities[1]->getId());
1435
        $this->assertSame($toMany2, $entities[1]);
1436
    }
1437
1438
    public function testHydrateOneToManyAssociationByReference()
1439
    {
1440
        // When using hydration by value, it will use the public API of the entity to set values (setters)
1441
        $toMany1 = new Asset\SimpleEntity();
1442
        $toMany1->setId(2);
1443
        $toMany1->setField('foo', false);
1444
1445
        $toMany2 = new Asset\SimpleEntity();
1446
        $toMany2->setId(3);
1447
        $toMany2->setField('bar', false);
1448
1449
        $entity = new Asset\OneToManyEntity();
1450
        $this->configureObjectManagerForOneToManyEntity();
1451
1452
        $data = ['entities' => [$toMany1, $toMany2]];
1453
1454
        $entity = $this->hydratorByReference->hydrate($data, $entity);
1455
1456
        $this->assertInstanceOf(Asset\OneToManyEntity::class, $entity);
1457
1458
        $entities = $entity->getEntities(false);
1459
1460
        foreach ($entities as $en) {
1461
            $this->assertInstanceOf(Asset\SimpleEntity::class, $en);
1462
            $this->assertInternalType('integer', $en->getId());
1463
            $this->assertNotContains('Modified from addEntities adder', $en->getField(false));
1464
        }
1465
1466
        $this->assertEquals(2, $entities[0]->getId());
1467
        $this->assertSame($toMany1, $entities[0]);
1468
1469
        $this->assertEquals(3, $entities[1]->getId());
1470
        $this->assertSame($toMany2, $entities[1]);
1471
    }
1472
1473
    /**
1474
     * @depends testHydrateOneToManyAssociationByReference
1475
     */
1476
    public function testHydrateOneToManyArrayByReference()
1477
    {
1478
        // When using hydration by value, it will use the public API of the entity to set values (setters)
1479
        $toMany1 = new Asset\SimpleEntity();
1480
        $toMany1->setId(2);
1481
        $toMany1->setField('foo', false);
1482
1483
        $toMany2 = new Asset\SimpleEntity();
1484
        $toMany2->setId(3);
1485
        $toMany2->setField('bar', false);
1486
1487
        $entity = new Asset\OneToManyArrayEntity();
1488
        $this->configureObjectManagerForOneToManyArrayEntity();
1489
1490
        $data = ['entities' => [$toMany1, $toMany2]];
1491
1492
        $entity = $this->hydratorByReference->hydrate($data, $entity);
1493
1494
        $this->assertInstanceOf(Asset\OneToManyArrayEntity::class, $entity);
1495
1496
        $entities = $entity->getEntities(false);
1497
1498
        foreach ($entities as $en) {
1499
            $this->assertInstanceOf(Asset\SimpleEntity::class, $en);
1500
            $this->assertInternalType('integer', $en->getId());
1501
            $this->assertNotContains('Modified from addEntities adder', $en->getField(false));
1502
        }
1503
1504
        $this->assertEquals(2, $entities[0]->getId());
1505
        $this->assertSame($toMany1, $entities[0]);
1506
1507
        $this->assertEquals(3, $entities[1]->getId());
1508
        $this->assertSame($toMany2, $entities[1]);
1509
    }
1510
1511
    public function testHydrateOneToManyAssociationByValueUsingIdentifiersForRelations()
1512
    {
1513
        // When using hydration by value, it will use the public API of the entity to set values (setters)
1514
        $entity = new Asset\OneToManyEntity();
1515
        $this->configureObjectManagerForOneToManyEntity();
1516
1517
        $data = ['entities' => [2, 3]];
1518
1519
        $entityInDatabaseWithIdOfTwo = new Asset\SimpleEntity();
1520
        $entityInDatabaseWithIdOfTwo->setId(2);
1521
        $entityInDatabaseWithIdOfTwo->setField('foo', false);
1522
1523
        $entityInDatabaseWithIdOfThree = new Asset\SimpleEntity();
1524
        $entityInDatabaseWithIdOfThree->setId(3);
1525
        $entityInDatabaseWithIdOfThree->setField('bar', false);
1526
1527
        $this
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\Common\Persistence\ObjectManager.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
1528
            ->objectManager
1529
            ->expects($this->exactly(2))
1530
            ->method('find')
1531
            ->with(
1532
                Asset\SimpleEntity::class,
1533
                $this->logicalOr($this->equalTo(['id' => 2]), $this->equalTo(['id' => 3]))
1534
            )
1535
            ->will(
1536
                $this->returnCallback(
1537
                    function ($target, $arg) use ($entityInDatabaseWithIdOfTwo, $entityInDatabaseWithIdOfThree) {
1538
                        if ($arg['id'] === 2) {
1539
                            return $entityInDatabaseWithIdOfTwo;
1540
                        } elseif ($arg['id'] === 3) {
1541
                            return $entityInDatabaseWithIdOfThree;
1542
                        }
1543
1544
                        throw new \InvalidArgumentException();
1545
                    }
1546
                )
1547
            );
1548
1549
        $entity = $this->hydratorByValue->hydrate($data, $entity);
1550
1551
        $this->assertInstanceOf(Asset\OneToManyEntity::class, $entity);
1552
1553
        /** @var $entity Asset\OneToManyEntity */
1554
        $entities = $entity->getEntities(false);
1555
1556
        foreach ($entities as $en) {
1557
            $this->assertInstanceOf(Asset\SimpleEntity::class, $en);
1558
            $this->assertInternalType('integer', $en->getId());
1559
            $this->assertContains('Modified from addEntities adder', $en->getField(false));
1560
        }
1561
1562
        $this->assertEquals(2, $entities[0]->getId());
1563
        $this->assertSame($entityInDatabaseWithIdOfTwo, $entities[0]);
1564
1565
        $this->assertEquals(3, $entities[1]->getId());
1566
        $this->assertSame($entityInDatabaseWithIdOfThree, $entities[1]);
1567
    }
1568
1569
    public function testHydrateOneToManyAssociationByValueUsingIdentifiersArrayForRelations()
1570
    {
1571
        // When using hydration by value, it will use the public API of the entity to set values (setters)
1572
        $entity = new Asset\OneToManyEntity();
1573
        $this->configureObjectManagerForOneToManyEntity();
1574
1575
        $data = ['entities' => [['id' => 2], ['id' => 3]]];
1576
1577
        $entityInDatabaseWithIdOfTwo = new Asset\SimpleEntity();
1578
        $entityInDatabaseWithIdOfTwo->setId(2);
1579
        $entityInDatabaseWithIdOfTwo->setField('foo', false);
1580
1581
        $entityInDatabaseWithIdOfThree = new Asset\SimpleEntity();
1582
        $entityInDatabaseWithIdOfThree->setId(3);
1583
        $entityInDatabaseWithIdOfThree->setField('bar', false);
1584
1585
        $this
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\Common\Persistence\ObjectManager.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
1586
            ->objectManager
1587
            ->expects($this->exactly(2))
1588
            ->method('find')
1589
            ->with(
1590
                Asset\SimpleEntity::class,
1591
                $this->logicalOr($this->equalTo(['id' => 2]), $this->equalTo(['id' => 3]))
1592
            )
1593
            ->will(
1594
                $this->returnCallback(
1595
                    function ($target, $arg) use ($entityInDatabaseWithIdOfTwo, $entityInDatabaseWithIdOfThree) {
1596
                        if ($arg['id'] === 2) {
1597
                            return $entityInDatabaseWithIdOfTwo;
1598
                        } elseif ($arg['id'] === 3) {
1599
                            return $entityInDatabaseWithIdOfThree;
1600
                        }
1601
1602
                        throw new \InvalidArgumentException();
1603
                    }
1604
                )
1605
            );
1606
1607
        $entity = $this->hydratorByValue->hydrate($data, $entity);
1608
1609
        $this->assertInstanceOf(Asset\OneToManyEntity::class, $entity);
1610
1611
        /** @var $entity Asset\OneToManyEntity */
1612
        $entities = $entity->getEntities(false);
1613
1614
        foreach ($entities as $en) {
1615
            $this->assertInstanceOf(Asset\SimpleEntity::class, $en);
1616
            $this->assertInternalType('integer', $en->getId());
1617
            $this->assertContains('Modified from addEntities adder', $en->getField(false));
1618
        }
1619
1620
        $this->assertEquals(2, $entities[0]->getId());
1621
        $this->assertSame($entityInDatabaseWithIdOfTwo, $entities[0]);
1622
1623
        $this->assertEquals(3, $entities[1]->getId());
1624
        $this->assertSame($entityInDatabaseWithIdOfThree, $entities[1]);
1625
    }
1626
1627
    public function testHydrateOneToManyAssociationByReferenceUsingIdentifiersArrayForRelations()
1628
    {
1629
        // When using hydration by value, it will use the public API of the entity to set values (setters)
1630
        $entity = new Asset\OneToManyEntity();
1631
        $this->configureObjectManagerForOneToManyEntity();
1632
1633
        $data = ['entities' => [['id' => 2], ['id' => 3]]];
1634
1635
        $entityInDatabaseWithIdOfTwo = new Asset\SimpleEntity();
1636
        $entityInDatabaseWithIdOfTwo->setId(2);
1637
        $entityInDatabaseWithIdOfTwo->setField('foo', false);
1638
1639
        $entityInDatabaseWithIdOfThree = new Asset\SimpleEntity();
1640
        $entityInDatabaseWithIdOfThree->setId(3);
1641
        $entityInDatabaseWithIdOfThree->setField('bar', false);
1642
1643
        $this
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\Common\Persistence\ObjectManager.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
1644
            ->objectManager
1645
            ->expects($this->exactly(2))
1646
            ->method('find')
1647
            ->with(
1648
                Asset\SimpleEntity::class,
1649
                $this->logicalOr($this->equalTo(['id' => 2]), $this->equalTo(['id' => 3]))
1650
            )
1651
            ->will(
1652
                $this->returnCallback(
1653
                    function ($target, $arg) use ($entityInDatabaseWithIdOfTwo, $entityInDatabaseWithIdOfThree) {
1654
                        if ($arg['id'] === 2) {
1655
                            return $entityInDatabaseWithIdOfTwo;
1656
                        } elseif ($arg['id'] === 3) {
1657
                            return $entityInDatabaseWithIdOfThree;
1658
                        }
1659
1660
                        throw new \InvalidArgumentException();
1661
                    }
1662
                )
1663
            );
1664
1665
        $entity = $this->hydratorByReference->hydrate($data, $entity);
1666
1667
        $this->assertInstanceOf(Asset\OneToManyEntity::class, $entity);
1668
1669
        $entities = $entity->getEntities(false);
1670
1671
        foreach ($entities as $en) {
1672
            $this->assertInstanceOf(Asset\SimpleEntity::class, $en);
1673
            $this->assertInternalType('integer', $en->getId());
1674
            $this->assertNotContains('Modified from addEntities adder', $en->getField(false));
1675
        }
1676
1677
        $this->assertEquals(2, $entities[0]->getId());
1678
        $this->assertSame($entityInDatabaseWithIdOfTwo, $entities[0]);
1679
1680
        $this->assertEquals(3, $entities[1]->getId());
1681
        $this->assertSame($entityInDatabaseWithIdOfThree, $entities[1]);
1682
    }
1683
1684
    public function testHydrateOneToManyAssociationByReferenceUsingIdentifiersForRelations()
1685
    {
1686
        // When using hydration by reference, it won't use the public API of the entity to set values (setters)
1687
        $entity = new Asset\OneToManyEntity();
1688
        $this->configureObjectManagerForOneToManyEntity();
1689
1690
        $data = ['entities' => [2, 3]];
1691
1692
        $entityInDatabaseWithIdOfTwo = new Asset\SimpleEntity();
1693
        $entityInDatabaseWithIdOfTwo->setId(2);
1694
        $entityInDatabaseWithIdOfTwo->setField('foo', false);
1695
1696
        $entityInDatabaseWithIdOfThree = new Asset\SimpleEntity();
1697
        $entityInDatabaseWithIdOfThree->setId(3);
1698
        $entityInDatabaseWithIdOfThree->setField('bar', false);
1699
1700
        $this
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\Common\Persistence\ObjectManager.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
1701
            ->objectManager
1702
            ->expects($this->any())
1703
            ->method('find')
1704
            ->with(
1705
                Asset\SimpleEntity::class,
1706
                $this->logicalOr($this->equalTo(['id' => 2]), $this->equalTo(['id' => 3]))
1707
            )
1708
            ->will(
1709
                $this->returnCallback(
1710
                    function ($target, $arg) use ($entityInDatabaseWithIdOfTwo, $entityInDatabaseWithIdOfThree) {
1711
                        if ($arg['id'] === 2) {
1712
                            return $entityInDatabaseWithIdOfTwo;
1713
                        } elseif ($arg['id'] === 3) {
1714
                            return $entityInDatabaseWithIdOfThree;
1715
                        }
1716
1717
                        throw new \InvalidArgumentException();
1718
                    }
1719
                )
1720
            );
1721
1722
        $entity = $this->hydratorByReference->hydrate($data, $entity);
1723
1724
        $this->assertInstanceOf(Asset\OneToManyEntity::class, $entity);
1725
1726
        $entities = $entity->getEntities(false);
1727
1728
        foreach ($entities as $en) {
1729
            $this->assertInstanceOf(Asset\SimpleEntity::class, $en);
1730
            $this->assertInternalType('integer', $en->getId());
1731
            $this->assertNotContains('Modified from addEntities adder', $en->getField(false));
1732
        }
1733
1734
        $this->assertEquals(2, $entities[0]->getId());
1735
        $this->assertSame($entityInDatabaseWithIdOfTwo, $entities[0]);
1736
1737
        $this->assertEquals(3, $entities[1]->getId());
1738
        $this->assertSame($entityInDatabaseWithIdOfThree, $entities[1]);
1739
    }
1740
1741
    public function testHydrateOneToManyAssociationByValueUsingDisallowRemoveStrategy()
1742
    {
1743
        // When using hydration by value, it will use the public API of the entity to set values (setters)
1744
        $toMany1 = new Asset\SimpleEntity();
1745
        $toMany1->setId(2);
1746
        $toMany1->setField('foo', false);
1747
1748
        $toMany2 = new Asset\SimpleEntity();
1749
        $toMany2->setId(3);
1750
        $toMany2->setField('bar', false);
1751
1752
        $toMany3 = new Asset\SimpleEntity();
1753
        $toMany3->setId(8);
1754
        $toMany3->setField('baz', false);
1755
1756
        $entity = new Asset\OneToManyEntity();
1757
        $this->configureObjectManagerForOneToManyEntity();
1758
1759
        // Initially add two elements
1760
        $entity->addEntities(new ArrayCollection([$toMany1, $toMany2]));
1761
1762
        // The hydrated collection contains two other elements, one of them is new, and one of them is missing
1763
        // in the new strategy
1764
        $data = ['entities' => [$toMany2, $toMany3]];
1765
1766
        // Use a DisallowRemove strategy
1767
        $this->hydratorByValue->addStrategy('entities', new Strategy\DisallowRemoveByValue());
1768
        $entity = $this->hydratorByValue->hydrate($data, $entity);
1769
1770
        $entities = $entity->getEntities(false);
1771
1772
        // DisallowStrategy should not remove existing entities in Collection even if it's not in the new collection
1773
        $this->assertEquals(3, count($entities));
1774
1775
        foreach ($entities as $en) {
1776
            $this->assertInstanceOf(Asset\SimpleEntity::class, $en);
1777
            $this->assertInternalType('integer', $en->getId());
1778
        }
1779
1780
        $this->assertEquals(2, $entities[0]->getId());
1781
        $this->assertSame($toMany1, $entities[0]);
1782
1783
        $this->assertEquals(3, $entities[1]->getId());
1784
        $this->assertSame($toMany2, $entities[1]);
1785
1786
        $this->assertEquals(8, $entities[2]->getId());
1787
        $this->assertSame($toMany3, $entities[2]);
1788
    }
1789
1790
    public function testHydrateOneToManyAssociationByReferenceUsingDisallowRemoveStrategy()
1791
    {
1792
       // When using hydration by reference, it won't use the public API of the entity to set values (setters)
1793
        $toMany1 = new Asset\SimpleEntity();
1794
        $toMany1->setId(2);
1795
        $toMany1->setField('foo', false);
1796
1797
        $toMany2 = new Asset\SimpleEntity();
1798
        $toMany2->setId(3);
1799
        $toMany2->setField('bar', false);
1800
1801
        $toMany3 = new Asset\SimpleEntity();
1802
        $toMany3->setId(8);
1803
        $toMany3->setField('baz', false);
1804
1805
        $entity = new Asset\OneToManyEntity();
1806
        $this->configureObjectManagerForOneToManyEntity();
1807
1808
        // Initially add two elements
1809
        $entity->addEntities(new ArrayCollection([$toMany1, $toMany2]));
1810
1811
        // The hydrated collection contains two other elements, one of them is new, and one of them is missing
1812
        // in the new strategy
1813
        $data = ['entities' => [$toMany2, $toMany3]];
1814
1815
        // Use a DisallowRemove strategy
1816
        $this->hydratorByReference->addStrategy('entities', new Strategy\DisallowRemoveByReference());
1817
        $entity = $this->hydratorByReference->hydrate($data, $entity);
1818
1819
        $entities = $entity->getEntities(false);
1820
1821
        // DisallowStrategy should not remove existing entities in Collection even if it's not in the new collection
1822
        $this->assertEquals(3, count($entities));
1823
1824
        foreach ($entities as $en) {
1825
            $this->assertInstanceOf(Asset\SimpleEntity::class, $en);
1826
            $this->assertInternalType('integer', $en->getId());
1827
1828
            // Only the third element is new so the adder has not been called on it
1829
            if ($en === $toMany3) {
1830
                $this->assertNotContains('Modified from addEntities adder', $en->getField(false));
1831
            }
1832
        }
1833
1834
        $this->assertEquals(2, $entities[0]->getId());
1835
        $this->assertSame($toMany1, $entities[0]);
1836
1837
        $this->assertEquals(3, $entities[1]->getId());
1838
        $this->assertSame($toMany2, $entities[1]);
1839
1840
        $this->assertEquals(8, $entities[2]->getId());
1841
        $this->assertSame($toMany3, $entities[2]);
1842
    }
1843
1844
    public function testHydrateOneToManyAssociationByValueWithArrayCausingDataModifications()
1845
    {
1846
        // When using hydration by value, it will use the public API of the entity to set values (setters)
1847
        $data = [
1848
            'entities' => [
1849
                ['id' => 2, 'field' => 'Modified By Hydrate'],
1850
                ['id' => 3, 'field' => 'Modified By Hydrate'],
1851
            ],
1852
        ];
1853
1854
        $entityInDatabaseWithIdOfTwo = new Asset\SimpleEntity();
1855
        $entityInDatabaseWithIdOfTwo->setId(2);
1856
        $entityInDatabaseWithIdOfTwo->setField('foo', false);
1857
1858
        $entityInDatabaseWithIdOfThree = new Asset\SimpleEntity();
1859
        $entityInDatabaseWithIdOfThree->setId(3);
1860
        $entityInDatabaseWithIdOfThree->setField('bar', false);
1861
1862
        $entity = new Asset\OneToManyEntityWithEntities(
1863
            new ArrayCollection([
1864
                $entityInDatabaseWithIdOfTwo,
1865
                $entityInDatabaseWithIdOfThree,
1866
            ])
1867
        );
1868
        $this->configureObjectManagerForOneToManyEntity();
1869
1870
        $this
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\Common\Persistence\ObjectManager.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
1871
            ->objectManager
1872
            ->expects($this->exactly(2))
1873
            ->method('find')
1874
            ->with(
1875
                Asset\SimpleEntity::class,
1876
                $this->logicalOr($this->equalTo(['id' => 2]), $this->equalTo(['id' => 3]))
1877
            )
1878
            ->will(
1879
                $this->returnCallback(
1880
                    function ($target, $arg) use ($entityInDatabaseWithIdOfTwo, $entityInDatabaseWithIdOfThree) {
1881
                        if ($arg['id'] === 2) {
1882
                            return $entityInDatabaseWithIdOfTwo;
1883
                        } elseif ($arg['id'] === 3) {
1884
                            return $entityInDatabaseWithIdOfThree;
1885
                        }
1886
1887
                        throw new \InvalidArgumentException();
1888
                    }
1889
                )
1890
            );
1891
1892
        $entity = $this->hydratorByValue->hydrate($data, $entity);
1893
1894
        $this->assertInstanceOf(Asset\OneToManyEntityWithEntities::class, $entity);
1895
1896
        /** @var $entity Asset\OneToManyEntity */
1897
        $entities = $entity->getEntities(false);
1898
1899
        foreach ($entities as $en) {
1900
            $this->assertInstanceOf(Asset\SimpleEntity::class, $en);
1901
            $this->assertInternalType('integer', $en->getId());
1902
            $this->assertInternalType('string', $en->getField());
1903
            $this->assertContains('Modified By Hydrate', $en->getField(false));
1904
        }
1905
1906
        $this->assertEquals(2, $entities[0]->getId());
1907
        $this->assertSame($entityInDatabaseWithIdOfTwo, $entities[0]);
1908
1909
        $this->assertEquals(3, $entities[1]->getId());
1910
        $this->assertSame($entityInDatabaseWithIdOfThree, $entities[1]);
1911
    }
1912
1913
    public function testHydrateOneToManyAssociationByValueWithTraversableCausingDataModifications()
1914
    {
1915
        // When using hydration by value, it will use the public API of the entity to set values (setters)
1916
        $data = [
1917
            'entities' => new ArrayCollection([
1918
                ['id' => 2, 'field' => 'Modified By Hydrate'],
1919
                ['id' => 3, 'field' => 'Modified By Hydrate'],
1920
            ]),
1921
        ];
1922
1923
        $entityInDatabaseWithIdOfTwo = new Asset\SimpleEntity();
1924
        $entityInDatabaseWithIdOfTwo->setId(2);
1925
        $entityInDatabaseWithIdOfTwo->setField('foo', false);
1926
1927
        $entityInDatabaseWithIdOfThree = new Asset\SimpleEntity();
1928
        $entityInDatabaseWithIdOfThree->setId(3);
1929
        $entityInDatabaseWithIdOfThree->setField('bar', false);
1930
1931
        $entity = new Asset\OneToManyEntityWithEntities(
1932
            new ArrayCollection([
1933
                $entityInDatabaseWithIdOfTwo,
1934
                $entityInDatabaseWithIdOfThree,
1935
            ])
1936
        );
1937
        $this->configureObjectManagerForOneToManyEntity();
1938
1939
        $this
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\Common\Persistence\ObjectManager.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
1940
            ->objectManager
1941
            ->expects($this->exactly(2))
1942
            ->method('find')
1943
            ->with(
1944
                Asset\SimpleEntity::class,
1945
                $this->logicalOr($this->equalTo(['id' => 2]), $this->equalTo(['id' => 3]))
1946
            )
1947
            ->will(
1948
                $this->returnCallback(
1949
                    function ($target, $arg) use ($entityInDatabaseWithIdOfTwo, $entityInDatabaseWithIdOfThree) {
1950
                        if ($arg['id'] === 2) {
1951
                            return $entityInDatabaseWithIdOfTwo;
1952
                        } elseif ($arg['id'] === 3) {
1953
                            return $entityInDatabaseWithIdOfThree;
1954
                        }
1955
1956
                        throw new \InvalidArgumentException();
1957
                    }
1958
                )
1959
            );
1960
1961
        $entity = $this->hydratorByValue->hydrate($data, $entity);
1962
1963
        $this->assertInstanceOf(Asset\OneToManyEntityWithEntities::class, $entity);
1964
1965
        /** @var $entity Asset\OneToManyEntity */
1966
        $entities = $entity->getEntities(false);
1967
1968
        foreach ($entities as $en) {
1969
            $this->assertInstanceOf(Asset\SimpleEntity::class, $en);
1970
            $this->assertInternalType('integer', $en->getId());
1971
            $this->assertInternalType('string', $en->getField());
1972
            $this->assertContains('Modified By Hydrate', $en->getField(false));
1973
        }
1974
1975
        $this->assertEquals(2, $entities[0]->getId());
1976
        $this->assertSame($entityInDatabaseWithIdOfTwo, $entities[0]);
1977
1978
        $this->assertEquals(3, $entities[1]->getId());
1979
        $this->assertSame($entityInDatabaseWithIdOfThree, $entities[1]);
1980
    }
1981
1982
    public function testHydrateOneToManyAssociationByValueWithStdClass()
1983
    {
1984
        // When using hydration by value, it will use the public API of the entity to set values (setters)
1985
        $stdClass1     = new \stdClass();
1986
        $stdClass1->id = 2;
1987
1988
        $stdClass2     = new \stdClass();
1989
        $stdClass2->id = 3;
1990
1991
        $data = ['entities' => [$stdClass1, $stdClass2]];
1992
1993
        $entityInDatabaseWithIdOfTwo = new Asset\SimpleEntity();
1994
        $entityInDatabaseWithIdOfTwo->setId(2);
1995
        $entityInDatabaseWithIdOfTwo->setField('foo', false);
1996
1997
        $entityInDatabaseWithIdOfThree = new Asset\SimpleEntity();
1998
        $entityInDatabaseWithIdOfThree->setId(3);
1999
        $entityInDatabaseWithIdOfThree->setField('bar', false);
2000
2001
        $entity = new Asset\OneToManyEntityWithEntities(
2002
            new ArrayCollection([
2003
                $entityInDatabaseWithIdOfTwo,
2004
                $entityInDatabaseWithIdOfThree,
2005
            ])
2006
        );
2007
        $this->configureObjectManagerForOneToManyEntity();
2008
2009
        $this
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\Common\Persistence\ObjectManager.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
2010
            ->objectManager
2011
            ->expects($this->exactly(2))
2012
            ->method('find')
2013
            ->with(
2014
                Asset\SimpleEntity::class,
2015
                $this->logicalOr($this->equalTo(['id' => 2]), $this->equalTo(['id' => 3]))
2016
            )
2017
            ->will(
2018
                $this->returnCallback(
2019
                    function ($target, $arg) use ($entityInDatabaseWithIdOfTwo, $entityInDatabaseWithIdOfThree) {
2020
                        if ($arg['id'] === 2) {
2021
                            return $entityInDatabaseWithIdOfTwo;
2022
                        } elseif ($arg['id'] === 3) {
2023
                            return $entityInDatabaseWithIdOfThree;
2024
                        }
2025
2026
                        throw new \InvalidArgumentException();
2027
                    }
2028
                )
2029
            );
2030
2031
        $entity = $this->hydratorByValue->hydrate($data, $entity);
2032
2033
        $this->assertInstanceOf(Asset\OneToManyEntityWithEntities::class, $entity);
2034
2035
        /** @var $entity Asset\OneToManyEntity */
2036
        $entities = $entity->getEntities(false);
2037
2038
        foreach ($entities as $en) {
2039
            $this->assertInstanceOf(Asset\SimpleEntity::class, $en);
2040
            $this->assertInternalType('integer', $en->getId());
2041
        }
2042
2043
        $this->assertEquals(2, $entities[0]->getId());
2044
        $this->assertSame($entityInDatabaseWithIdOfTwo, $entities[0]);
2045
2046
        $this->assertEquals(3, $entities[1]->getId());
2047
        $this->assertSame($entityInDatabaseWithIdOfThree, $entities[1]);
2048
    }
2049
2050
    public function testHydrateOneToManyAssociationByReferenceWithArrayCausingDataModifications()
2051
    {
2052
        // When using hydration by value, it will use the public API of the entity to set values (setters)
2053
        $data = [
2054
            'entities' => [
2055
                ['id' => 2, 'field' => 'Modified By Hydrate'],
2056
                ['id' => 3, 'field' => 'Modified By Hydrate'],
2057
            ],
2058
        ];
2059
2060
        $entityInDatabaseWithIdOfTwo = new Asset\SimpleEntity();
2061
        $entityInDatabaseWithIdOfTwo->setId(2);
2062
        $entityInDatabaseWithIdOfTwo->setField('Unmodified Value', false);
2063
2064
        $entityInDatabaseWithIdOfThree = new Asset\SimpleEntity();
2065
        $entityInDatabaseWithIdOfThree->setId(3);
2066
        $entityInDatabaseWithIdOfThree->setField('Unmodified Value', false);
2067
2068
        $entity = new Asset\OneToManyEntityWithEntities(
2069
            new ArrayCollection([
2070
                $entityInDatabaseWithIdOfTwo,
2071
                $entityInDatabaseWithIdOfThree,
2072
            ])
2073
        );
2074
2075
        $reflSteps = [
2076
            new \ReflectionClass(Asset\OneToManyEntityWithEntities::class),
2077
            new \ReflectionClass(Asset\SimpleEntity::class),
2078
            new \ReflectionClass(Asset\SimpleEntity::class),
2079
            new \ReflectionClass(Asset\OneToManyEntityWithEntities::class),
2080
        ];
2081
        $this
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\Common\Persistence\Mapping\ClassMetadata.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
2082
            ->metadata
2083
            ->expects($this->any())
2084
            ->method('getReflectionClass')
2085
            ->will($this->returnCallback(
2086
                function () use (&$reflSteps) {
2087
                    $refl = array_shift($reflSteps);
2088
                    return $refl;
2089
                }
2090
            ));
2091
2092
        $this->configureObjectManagerForOneToManyEntity();
2093
2094
        $this
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\Common\Persistence\ObjectManager.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
2095
            ->objectManager
2096
            ->expects($this->exactly(2))
2097
            ->method('find')
2098
            ->with(
2099
                Asset\SimpleEntity::class,
2100
                $this->logicalOr($this->equalTo(['id' => 2]), $this->equalTo(['id' => 3]))
2101
            )
2102
            ->will(
2103
                $this->returnCallback(
2104
                    function ($target, $arg) use ($entityInDatabaseWithIdOfTwo, $entityInDatabaseWithIdOfThree) {
2105
                        if ($arg['id'] === 2) {
2106
                            return $entityInDatabaseWithIdOfTwo;
2107
                        } elseif ($arg['id'] === 3) {
2108
                            return $entityInDatabaseWithIdOfThree;
2109
                        }
2110
2111
                        throw new \InvalidArgumentException();
2112
                    }
2113
                )
2114
            );
2115
2116
        $entity = $this->hydratorByReference->hydrate($data, $entity);
2117
2118
        $this->assertInstanceOf(Asset\OneToManyEntityWithEntities::class, $entity);
2119
2120
        /** @var $entity Asset\OneToManyEntity */
2121
        $entities = $entity->getEntities(false);
2122
2123
        foreach ($entities as $en) {
2124
            $this->assertInstanceOf(Asset\SimpleEntity::class, $en);
2125
            $this->assertInternalType('integer', $en->getId());
2126
            $this->assertInternalType('string', $en->getField());
2127
            $this->assertContains('Modified By Hydrate', $en->getField(false));
2128
        }
2129
2130
        $this->assertEquals(2, $entities[0]->getId());
2131
        $this->assertSame($entityInDatabaseWithIdOfTwo, $entities[0]);
2132
2133
        $this->assertEquals(3, $entities[1]->getId());
2134
        $this->assertSame($entityInDatabaseWithIdOfThree, $entities[1]);
2135
    }
2136
2137
    public function testAssertCollectionsAreNotSwappedDuringHydration()
2138
    {
2139
        // When using hydration by value, it will use the public API of the entity to set values (setters)
2140
        $entity = new Asset\OneToManyEntity();
2141
        $this->configureObjectManagerForOneToManyEntity();
2142
2143
        $toMany1 = new Asset\SimpleEntity();
2144
        $toMany1->setId(2);
2145
        $toMany1->setField('foo', false);
2146
2147
        $toMany2 = new Asset\SimpleEntity();
2148
        $toMany2->setId(3);
2149
        $toMany2->setField('bar', false);
2150
2151
        $data = ['entities' => [$toMany1, $toMany2]];
2152
2153
        // Set the initial collection
2154
        $entity->addEntities(new ArrayCollection([$toMany1, $toMany2]));
2155
        $initialCollection = $entity->getEntities(false);
2156
2157
        $entity = $this->hydratorByValue->hydrate($data, $entity);
2158
2159
        $modifiedCollection = $entity->getEntities(false);
2160
        $this->assertSame($initialCollection, $modifiedCollection);
2161
    }
2162
2163
    public function testAssertCollectionsAreNotSwappedDuringHydrationUsingIdentifiersForRelations()
2164
    {
2165
        // When using hydration by value, it will use the public API of the entity to set values (setters)
2166
        $entity = new Asset\OneToManyEntity();
2167
        $this->configureObjectManagerForOneToManyEntity();
2168
2169
        $data = ['entities' => [2, 3]];
2170
2171
        $entityInDatabaseWithIdOfTwo = new Asset\SimpleEntity();
2172
        $entityInDatabaseWithIdOfTwo->setId(2);
2173
        $entityInDatabaseWithIdOfTwo->setField('foo', false);
2174
2175
        $entityInDatabaseWithIdOfThree = new Asset\SimpleEntity();
2176
        $entityInDatabaseWithIdOfThree->setId(3);
2177
        $entityInDatabaseWithIdOfThree->setField('bar', false);
2178
2179
        // Set the initial collection
2180
        $entity->addEntities(new ArrayCollection([$entityInDatabaseWithIdOfTwo, $entityInDatabaseWithIdOfThree]));
2181
        $initialCollection = $entity->getEntities(false);
2182
2183
        $this
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\Common\Persistence\ObjectManager.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
2184
            ->objectManager
2185
            ->expects($this->any())
2186
            ->method('find')
2187
            ->with(
2188
                Asset\SimpleEntity::class,
2189
                $this->logicalOr($this->equalTo(['id' => 2]), $this->equalTo(['id' => 3]))
2190
            )
2191
            ->will(
2192
                $this->returnCallback(
2193
                    function ($target, $arg) use ($entityInDatabaseWithIdOfTwo, $entityInDatabaseWithIdOfThree) {
2194
                        if ($arg['id'] === 2) {
2195
                            return $entityInDatabaseWithIdOfTwo;
2196
                        }
2197
2198
                        return $entityInDatabaseWithIdOfThree;
2199
                    }
2200
                )
2201
            );
2202
2203
        $entity = $this->hydratorByValue->hydrate($data, $entity);
2204
2205
        $modifiedCollection = $entity->getEntities(false);
2206
        $this->assertSame($initialCollection, $modifiedCollection);
2207
    }
2208
2209
    public function testCanLookupsForEmptyIdentifiers()
2210
    {
2211
        // When using hydration by reference, it won't use the public API of the entity to set values (setters)
2212
        $entity = new Asset\OneToManyEntity();
2213
        $this->configureObjectManagerForOneToManyEntity();
2214
2215
        $data = ['entities' => ['']];
2216
2217
        $entityInDatabaseWithEmptyId = new Asset\SimpleEntity();
2218
        $entityInDatabaseWithEmptyId->setId('');
2219
        $entityInDatabaseWithEmptyId->setField('baz', false);
2220
2221
        $this
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\Common\Persistence\ObjectManager.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
2222
            ->objectManager
2223
            ->expects($this->any())
2224
            ->method('find')
2225
            ->with(Asset\SimpleEntity::class, '')
2226
            ->will($this->returnValue($entityInDatabaseWithEmptyId));
2227
2228
        $entity = $this->hydratorByValue->hydrate($data, $entity);
2229
2230
        $this->assertInstanceOf(Asset\OneToManyEntity::class, $entity);
2231
2232
        $entities = $entity->getEntities(false);
2233
        $entity   = $entities[0];
2234
2235
        $this->assertEquals(1, count($entities));
2236
2237
        $this->assertInstanceOf(Asset\SimpleEntity::class, $entity);
2238
        $this->assertSame($entityInDatabaseWithEmptyId, $entity);
2239
    }
2240
2241
    public function testHandleDateTimeConversionUsingByValue()
2242
    {
2243
        // When using hydration by value, it will use the public API of the entity to set values (setters)
2244
        $entity = new Asset\SimpleEntityWithDateTime();
2245
        $this->configureObjectManagerForSimpleEntityWithDateTime();
2246
2247
        $now  = time();
2248
        $data = ['date' => $now];
2249
2250
        $entity = $this->hydratorByValue->hydrate($data, $entity);
2251
2252
        $this->assertInstanceOf('DateTime', $entity->getDate());
2253
        $this->assertEquals($now, $entity->getDate()->getTimestamp());
2254
    }
2255
2256
    public function testEmptyStringIsNotConvertedToDateTime()
2257
    {
2258
        $entity = new Asset\SimpleEntityWithDateTime();
2259
        $this->configureObjectManagerForSimpleEntityWithDateTime();
2260
2261
        $data = ['date' => ''];
2262
2263
        $entity = $this->hydratorByValue->hydrate($data, $entity);
2264
2265
        $this->assertNull($entity->getDate());
2266
    }
2267
2268
    public function testAssertNullValueHydratedForOneToOneWithOptionalMethodSignature()
2269
    {
2270
        $entity = new Asset\OneToOneEntity();
2271
2272
        $this->configureObjectManagerForOneToOneEntity();
2273
        $this->objectManager->expects($this->never())->method('find');
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\Common\Persistence\ObjectManager.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
2274
2275
        $data = ['toOne' => null];
2276
2277
        $object = $this->hydratorByValue->hydrate($data, $entity);
2278
        $this->assertNull($object->getToOne(false));
2279
    }
2280
2281
    public function testAssertNullValueNotUsedAsIdentifierForOneToOneWithNonOptionalMethodSignature()
2282
    {
2283
        $entity = new Asset\OneToOneEntityNotNullable();
2284
2285
        $entity->setToOne(new Asset\SimpleEntity());
2286
        $this->configureObjectManagerForOneToOneEntityNotNullable();
2287
        $this->objectManager->expects($this->never())->method('find');
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\Common\Persistence\ObjectManager.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
2288
2289
        $data = ['toOne' => null];
2290
2291
        $object = $this->hydratorByValue->hydrate($data, $entity);
2292
        $this->assertInstanceOf(Asset\SimpleEntity::class, $object->getToOne(false));
2293
    }
2294
2295
    public function testUsesStrategyOnSimpleFieldsWhenHydratingByValue()
2296
    {
2297
        // When using hydration by value, it will use the public API of the entity to set values (setters)
2298
        $entity = new Asset\SimpleEntity();
2299
        $this->configureObjectManagerForSimpleEntity();
2300
        $data = ['field' => 'foo'];
2301
2302
        $this->hydratorByValue->addStrategy('field', new Asset\SimpleStrategy());
2303
        $entity = $this->hydratorByValue->hydrate($data, $entity);
2304
2305
        $this->assertInstanceOf(Asset\SimpleEntity::class, $entity);
2306
        $this->assertEquals('From setter: modified while hydrating', $entity->getField(false));
2307
    }
2308
2309
    public function testUsesStrategyOnSimpleFieldsWhenHydratingByReference()
2310
    {
2311
        // When using hydration by value, it will use the public API of the entity to set values (setters)
2312
        $entity = new Asset\SimpleEntity();
2313
        $this->configureObjectManagerForSimpleEntity();
2314
        $data = ['field' => 'foo'];
2315
2316
        $this->hydratorByReference->addStrategy('field', new Asset\SimpleStrategy());
2317
        $entity = $this->hydratorByReference->hydrate($data, $entity);
2318
2319
        $this->assertInstanceOf(Asset\SimpleEntity::class, $entity);
2320
        $this->assertEquals('modified while hydrating', $entity->getField(false));
2321
    }
2322
2323
    public function testUsesStrategyOnSimpleFieldsWhenExtractingByValue()
2324
    {
2325
        $entity = new Asset\SimpleEntity();
2326
        $entity->setId(2);
2327
        $entity->setField('foo', false);
2328
2329
        $this->configureObjectManagerForSimpleEntity();
2330
2331
        $this->hydratorByValue->addStrategy('field', new Asset\SimpleStrategy());
2332
        $data = $this->hydratorByValue->extract($entity);
2333
        $this->assertInstanceOf(Asset\SimpleEntity::class, $entity);
2334
        $this->assertEquals(['id' => 2, 'field' => 'modified while extracting'], $data);
2335
    }
2336
2337
    public function testUsesStrategyOnSimpleFieldsWhenExtractingByReference()
2338
    {
2339
        $entity = new Asset\SimpleEntity();
2340
        $entity->setId(2);
2341
        $entity->setField('foo', false);
2342
2343
        $this->configureObjectManagerForSimpleEntity();
2344
2345
        $this->hydratorByReference->addStrategy('field', new Asset\SimpleStrategy());
2346
        $data = $this->hydratorByReference->extract($entity);
2347
        $this->assertInstanceOf(Asset\SimpleEntity::class, $entity);
2348
        $this->assertEquals(['id' => 2, 'field' => 'modified while extracting'], $data);
2349
    }
2350
2351
    public function testCanExtractIsserByValue()
2352
    {
2353
        $entity = new Asset\SimpleIsEntity();
2354
        $entity->setId(2);
2355
        $entity->setDone(true);
2356
2357
        $this->configureObjectManagerForSimpleIsEntity();
2358
2359
        $data = $this->hydratorByValue->extract($entity);
2360
        $this->assertInstanceOf(Asset\SimpleIsEntity::class, $entity);
2361
        $this->assertEquals(['id' => 2, 'done' => true], $data);
2362
    }
2363
2364
    public function testCanExtractIsserThatStartsWithIsByValue()
2365
    {
2366
        $entity = new Asset\SimpleEntityWithIsBoolean();
2367
        $entity->setId(2);
2368
        $entity->setIsActive(true);
2369
2370
        $this->configureObjectManagerForSimpleEntityWithIsBoolean();
2371
2372
        $data = $this->hydratorByValue->extract($entity);
2373
        $this->assertInstanceOf(Asset\SimpleEntityWithIsBoolean::class, $entity);
2374
        $this->assertEquals(['id' => 2, 'isActive' => true], $data);
2375
    }
2376
2377
    public function testExtractWithPropertyNameFilterByValue()
2378
    {
2379
        $entity = new Asset\SimpleEntity();
2380
        $entity->setId(2);
2381
        $entity->setField('foo', false);
2382
2383
        $filter = new Filter\PropertyName(['id'], false);
2384
2385
        $this->configureObjectManagerForSimpleEntity();
2386
2387
        $this->hydratorByValue->addFilter('propertyname', $filter);
0 ignored issues
show
Documentation introduced by
$filter is of type object<DoctrineModule\St...or\Filter\PropertyName>, but the function expects a callable.

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...
2388
        $data = $this->hydratorByValue->extract($entity);
2389
2390
        $this->assertEquals(2, $data['id']);
2391
        $this->assertEquals(['id'], array_keys($data), 'Only the "id" field should have been extracted.');
2392
    }
2393
2394
    public function testExtractWithPropertyNameFilterByReference()
2395
    {
2396
        $entity = new Asset\SimpleEntity();
2397
        $entity->setId(2);
2398
        $entity->setField('foo', false);
2399
2400
        $filter = new Filter\PropertyName(['id'], false);
2401
2402
        $this->configureObjectManagerForSimpleEntity();
2403
2404
        $this->hydratorByReference->addFilter('propertyname', $filter);
0 ignored issues
show
Documentation introduced by
$filter is of type object<DoctrineModule\St...or\Filter\PropertyName>, but the function expects a callable.

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...
2405
        $data = $this->hydratorByReference->extract($entity);
2406
2407
        $this->assertEquals(2, $data['id']);
2408
        $this->assertEquals(['id'], array_keys($data), 'Only the "id" field should have been extracted.');
2409
    }
2410
2411
    public function testExtractByReferenceUsesNamingStrategy()
2412
    {
2413
        $this->configureObjectManagerForNamingStrategyEntity();
2414
        $name = 'Foo';
2415
        $this->hydratorByReference->setNamingStrategy(new UnderscoreNamingStrategy());
2416
        $data = $this->hydratorByReference->extract(new Asset\NamingStrategyEntity($name));
2417
        $this->assertEquals($name, $data['camel_case']);
2418
    }
2419
2420
    public function testExtractByValueUsesNamingStrategy()
2421
    {
2422
        $this->configureObjectManagerForNamingStrategyEntity();
2423
        $name = 'Bar';
2424
        $this->hydratorByValue->setNamingStrategy(new UnderscoreNamingStrategy());
2425
        $data = $this->hydratorByValue->extract(new Asset\NamingStrategyEntity($name));
2426
        $this->assertEquals($name, $data['camel_case']);
2427
    }
2428
2429
    public function testHydrateByReferenceUsesNamingStrategy()
2430
    {
2431
        $this->configureObjectManagerForNamingStrategyEntity();
2432
        $name = 'Baz';
2433
        $this->hydratorByReference->setNamingStrategy(new UnderscoreNamingStrategy());
2434
        $entity = $this->hydratorByReference->hydrate(['camel_case' => $name], new Asset\NamingStrategyEntity());
2435
        $this->assertEquals($name, $entity->getCamelCase());
2436
    }
2437
2438
    public function testHydrateByValueUsesNamingStrategy()
2439
    {
2440
        $this->configureObjectManagerForNamingStrategyEntity();
2441
        $name = 'Qux';
2442
        $this->hydratorByValue->setNamingStrategy(new UnderscoreNamingStrategy());
2443
        $entity = $this->hydratorByValue->hydrate(['camel_case' => $name], new Asset\NamingStrategyEntity());
2444
        $this->assertEquals($name, $entity->getCamelCase());
2445
    }
2446
}
2447