Test Failed
Pull Request — develop (#6724)
by Marco
65:33
created

testFailedProxyLoadingDoesNotMarkTheProxyAsInitialized()   B

Complexity

Conditions 2
Paths 3

Size

Total Lines 28
Code Lines 18

Duplication

Lines 28
Ratio 100 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 28
loc 28
rs 8.8571
c 1
b 0
f 0
cc 2
eloc 18
nc 3
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\Tests\ORM\Proxy;
6
7
use Doctrine\ORM\EntityNotFoundException;
8
use Doctrine\ORM\Mapping\ClassMetadata;
9
use Doctrine\ORM\Mapping\ClassMetadataBuildingContext;
10
use Doctrine\ORM\Mapping\ClassMetadataFactory;
11
use Doctrine\ORM\PersistentCollection;
12
use Doctrine\ORM\Persisters\Entity\BasicEntityPersister;
13
use Doctrine\ORM\Proxy\Factory\StaticProxyFactory;
14
use Doctrine\ORM\Reflection\RuntimeReflectionService;
15
use Doctrine\Tests\Mocks\ConnectionMock;
16
use Doctrine\Tests\Mocks\DriverMock;
17
use Doctrine\Tests\Mocks\EntityManagerMock;
18
use Doctrine\Tests\Mocks\UnitOfWorkMock;
19
use Doctrine\Tests\Models\CMS\CmsUser;
20
use Doctrine\Tests\Models\Company\CompanyEmployee;
21
use Doctrine\Tests\Models\ECommerce\ECommerceFeature;
22
use Doctrine\Tests\Models\FriendObject\ComparableObject;
23
use Doctrine\Tests\Models\ProxySpecifics\FuncGetArgs;
24
use Doctrine\Tests\OrmTestCase;
25
use ProxyManager\Proxy\GhostObjectInterface;
26
27
/**
28
 * Test the proxy generator. Its work is generating on-the-fly subclasses of a given model, which implement the Proxy pattern.
29
 * @author Giorgio Sironi <[email protected]>
30
 */
31
class ProxyFactoryTest extends OrmTestCase
32
{
33
    /**
34
     * @var ConnectionMock
35
     */
36
    private $connectionMock;
37
38
    /**
39
     * @var UnitOfWorkMock
40
     */
41
    private $uowMock;
42
43
    /**
44
     * @var EntityManagerMock
45
     */
46
    private $emMock;
47
48
    /**
49
     * @var StaticProxyFactory
50
     */
51
    private $proxyFactory;
52
53
    /**
54
     * @var ClassMetadataBuildingContext
55
     */
56
    private $metadataBuildingContext;
57
58
    /**
59
     * {@inheritDoc}
60
     */
61
    protected function setUp()
62
    {
63
        parent::setUp();
64
65
        $this->metadataBuildingContext = new ClassMetadataBuildingContext(
66
            $this->createMock(ClassMetadataFactory::class),
0 ignored issues
show
Documentation introduced by
$this->createMock(\Doctr...MetadataFactory::class) is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<Doctrine\ORM\Mapp...ctClassMetadataFactory>.

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...
67
            new RuntimeReflectionService()
68
        );
69
        $this->connectionMock          = new ConnectionMock([], new DriverMock());
70
        $this->emMock                  = EntityManagerMock::create($this->connectionMock);
71
        $this->uowMock                 = new UnitOfWorkMock($this->emMock);
72
73
        $this->emMock->setUnitOfWork($this->uowMock);
74
75
        $this->proxyFactory = new StaticProxyFactory(
76
            $this->emMock,
77
            $this->emMock->getConfiguration()->buildGhostObjectFactory()
78
        );
79
    }
80
81
    public function testReferenceProxyDelegatesLoadingToThePersister()
82
    {
83
        $identifier    = ['id' => 42];
84
        $classMetaData = $this->emMock->getClassMetadata(ECommerceFeature::class);
85
86
        $persister = $this
87
            ->getMockBuilder(BasicEntityPersister::class)
88
            ->setConstructorArgs([$this->emMock, $classMetaData])
89
            ->setMethods(['loadById'])
90
            ->getMock();
91
92
        $persister
93
            ->expects($this->atLeastOnce())
94
            ->method('loadById')
95
            ->with(
96
                $identifier,
97
                self::logicalAnd(
98
                    self::isInstanceOf(GhostObjectInterface::class),
99
                    self::isInstanceOf(ECommerceFeature::class)
100
                )
101
            )
102
            ->will($this->returnValue(new \stdClass()));
103
104
        $this->uowMock->setEntityPersister(ECommerceFeature::class, $persister);
0 ignored issues
show
Documentation introduced by
$persister is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<Doctrine\ORM\Pers...y\BasicEntityPersister>.

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...
105
106
        /* @var $proxy GhostObjectInterface|ECommerceFeature */
107
        $proxy = $this->proxyFactory->getProxy($classMetaData, $identifier);
0 ignored issues
show
Documentation introduced by
$classMetaData is of type object<Doctrine\Common\P...\Mapping\ClassMetadata>, but the function expects a object<Doctrine\ORM\Mapping\ClassMetadata>.

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...
108
109
        $proxy->getDescription();
0 ignored issues
show
Bug introduced by
The method getDescription does only exist in Doctrine\Tests\Models\ECommerce\ECommerceFeature, but not in ProxyManager\Proxy\GhostObjectInterface.

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...
110
    }
111
112 View Code Duplication
    public function testSkipMappedSuperClassesOnGeneration(): void
113
    {
114
        $cm = new ClassMetadata(\stdClass::class, $this->metadataBuildingContext);
115
        $cm->isMappedSuperclass = true;
116
117
        self::assertSame(
118
            0,
119
            $this->proxyFactory->generateProxyClasses([$cm]),
120
            'No proxies generated.'
121
        );
122
    }
123
124
    /**
125
     * @group 6625
126
     * @group embedded
127
     */
128 View Code Duplication
    public function testSkipEmbeddableClassesOnGeneration(): void
129
    {
130
        $cm = new ClassMetadata(\stdClass::class, $this->metadataBuildingContext);
131
        $cm->isEmbeddedClass = true;
132
133
        self::assertSame(
134
            0,
135
            $this->proxyFactory->generateProxyClasses([$cm]),
136
            'No proxies generated.'
137
        );
138
    }
139
140
    /**
141
     * @group DDC-1771
142
     */
143
    public function testSkipAbstractClassesOnGeneration()
144
    {
145
        $cm = new ClassMetadata(AbstractClass::class, $this->metadataBuildingContext);
146
147
        self::assertNotNull($cm->getReflectionClass());
148
149
        $num = $this->proxyFactory->generateProxyClasses([$cm]);
150
151
        self::assertEquals(0, $num, "No proxies generated.");
152
    }
153
154
    /**
155
     * @group DDC-2432
156
     */
157 View Code Duplication
    public function testFailedProxyLoadingDoesNotMarkTheProxyAsInitialized()
158
    {
159
        $classMetaData = $this->emMock->getClassMetadata(ECommerceFeature::class);
160
161
        $persister = $this
162
            ->getMockBuilder(BasicEntityPersister::class)
163
            ->setConstructorArgs([$this->emMock, $classMetaData])
164
            ->setMethods(['load'])
165
            ->getMock();
166
167
        $persister
168
            ->expects($this->atLeastOnce())
169
            ->method('load')
170
            ->will($this->returnValue(null));
171
172
        $this->uowMock->setEntityPersister(ECommerceFeature::class, $persister);
0 ignored issues
show
Documentation introduced by
$persister is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<Doctrine\ORM\Pers...y\BasicEntityPersister>.

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...
173
174
        /* @var $proxy GhostObjectInterface|ECommerceFeature */
175
        $proxy = $this->proxyFactory->getProxy($classMetaData, ['id' => 42]);
0 ignored issues
show
Documentation introduced by
$classMetaData is of type object<Doctrine\Common\P...\Mapping\ClassMetadata>, but the function expects a object<Doctrine\ORM\Mapping\ClassMetadata>.

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...
176
177
        try {
178
            $proxy->getDescription();
0 ignored issues
show
Bug introduced by
The method getDescription does only exist in Doctrine\Tests\Models\ECommerce\ECommerceFeature, but not in ProxyManager\Proxy\GhostObjectInterface.

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...
179
            $this->fail('An exception was expected to be raised');
180
        } catch (EntityNotFoundException $exception) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
181
        }
182
183
        self::assertFalse($proxy->isProxyInitialized());
0 ignored issues
show
Bug introduced by
The method isProxyInitialized does only exist in ProxyManager\Proxy\GhostObjectInterface, but not in Doctrine\Tests\Models\ECommerce\ECommerceFeature.

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...
184
    }
185
186
    /**
187
     * @group DDC-2432
188
     */
189 View Code Duplication
    public function testFailedProxyCloningDoesNotMarkTheProxyAsInitialized()
190
    {
191
        $classMetaData = $this->emMock->getClassMetadata(ECommerceFeature::class);
192
193
        $persister = $this
194
            ->getMockBuilder(BasicEntityPersister::class)
195
            ->setConstructorArgs([$this->emMock, $classMetaData])
196
            ->setMethods(['load'])
197
            ->getMock();
198
199
        $persister
200
            ->expects($this->atLeastOnce())
201
            ->method('load')
202
            ->will($this->returnValue(null));
203
204
        $this->uowMock->setEntityPersister(ECommerceFeature::class, $persister);
0 ignored issues
show
Documentation introduced by
$persister is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<Doctrine\ORM\Pers...y\BasicEntityPersister>.

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...
205
206
        /* @var $proxy GhostObjectInterface|ECommerceFeature */
207
        $proxy = $this->proxyFactory->getProxy($classMetaData, ['id' => 42]);
0 ignored issues
show
Documentation introduced by
$classMetaData is of type object<Doctrine\Common\P...\Mapping\ClassMetadata>, but the function expects a object<Doctrine\ORM\Mapping\ClassMetadata>.

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...
208
209
        try {
210
            $cloned = clone $proxy;
0 ignored issues
show
Unused Code introduced by
$cloned is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
211
            $this->fail('An exception was expected to be raised');
212
        } catch (EntityNotFoundException $exception) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
213
        }
214
215
        self::assertFalse($proxy->isProxyInitialized());
0 ignored issues
show
Bug introduced by
The method isProxyInitialized does only exist in ProxyManager\Proxy\GhostObjectInterface, but not in Doctrine\Tests\Models\ECommerce\ECommerceFeature.

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...
216
    }
217
218
    public function testProxyClonesParentFields()
219
    {
220
        $identifier    = ['id' => 42];
221
        $classMetaData = $this->emMock->getClassMetadata(CompanyEmployee::class);
222
223
        $persister = $this
224
            ->getMockBuilder(BasicEntityPersister::class)
225
            ->setConstructorArgs([$this->emMock, $classMetaData])
226
            ->setMethods(['loadById'])
227
            ->getMock();
228
229
        $persister
230
            ->expects(self::atLeastOnce())
231
            ->method('loadById')
232
            ->with(
233
                $identifier,
234
                self::logicalAnd(
235
                    self::isInstanceOf(GhostObjectInterface::class),
236
                    self::isInstanceOf(CompanyEmployee::class)
237
                )
238
            )
239
            ->willReturnCallback(function (array $id, CompanyEmployee $companyEmployee) {
240
                $companyEmployee->setSalary(1000); // A property on the CompanyEmployee
241
                $companyEmployee->setName('Bob'); // A property on the parent class, CompanyPerson
242
243
                return $companyEmployee;
244
            });
245
246
        $this->uowMock->setEntityPersister(CompanyEmployee::class, $persister);
0 ignored issues
show
Documentation introduced by
$persister is of type object<PHPUnit\Framework\MockObject\MockObject>, but the function expects a object<Doctrine\ORM\Pers...y\BasicEntityPersister>.

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...
247
248
        /* @var $proxy GhostObjectInterface|CompanyEmployee */
249
        $proxy = $this->proxyFactory->getProxy($classMetaData, $identifier);
0 ignored issues
show
Documentation introduced by
$classMetaData is of type object<Doctrine\Common\P...\Mapping\ClassMetadata>, but the function expects a object<Doctrine\ORM\Mapping\ClassMetadata>.

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...
250
251
        $cloned = clone $proxy;
252
253
        self::assertSame(42, $cloned->getId(), 'Expected the Id to be cloned');
0 ignored issues
show
Bug introduced by
The method getId does only exist in Doctrine\Tests\Models\Company\CompanyEmployee, but not in ProxyManager\Proxy\GhostObjectInterface.

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...
254
        self::assertSame(1000, $cloned->getSalary(), 'Expect properties on the CompanyEmployee class to be cloned');
0 ignored issues
show
Bug introduced by
The method getSalary does only exist in Doctrine\Tests\Models\Company\CompanyEmployee, but not in ProxyManager\Proxy\GhostObjectInterface.

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...
255
        self::assertSame('Bob', $cloned->getName(), 'Expect properties on the CompanyPerson class to be cloned');
0 ignored issues
show
Bug introduced by
The method getName does only exist in Doctrine\Tests\Models\Company\CompanyEmployee, but not in ProxyManager\Proxy\GhostObjectInterface.

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...
256
    }
257
258
    public function testFriendObjectsDoNotLazyLoadIfNotAccessingLazyState()
259
    {
260
        /* @var $persister BasicEntityPersister|\PHPUnit_Framework_MockObject_MockObject */
261
        $persister = $this->createMock(BasicEntityPersister::class);
262
        $persister->expects(self::never())->method('loadById');
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\ORM\Persisters\...ty\BasicEntityPersister.

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...
263
264
        $this->uowMock->setEntityPersister(ComparableObject::class, $persister);
0 ignored issues
show
Bug introduced by
It seems like $persister defined by $this->createMock(\Doctr...EntityPersister::class) on line 261 can also be of type object<PHPUnit_Framework_MockObject_MockObject>; however, Doctrine\Tests\Mocks\Uni...k::setEntityPersister() does only seem to accept object<Doctrine\ORM\Pers...y\BasicEntityPersister>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
265
266
        /* @var $comparable ComparableObject|GhostObjectInterface */
267
        $comparable = $this->proxyFactory->getProxy(
268
            $this->emMock->getClassMetadata(ComparableObject::class),
0 ignored issues
show
Documentation introduced by
$this->emMock->getClassM...omparableObject::class) is of type object<Doctrine\Common\P...\Mapping\ClassMetadata>, but the function expects a object<Doctrine\ORM\Mapping\ClassMetadata>.

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...
269
            ['id' => 123]
270
        );
271
272
        self::assertInstanceOf(ComparableObject::class, $comparable);
273
        self::assertInstanceOf(GhostObjectInterface::class, $comparable);
274
        self::assertFalse($comparable->isProxyInitialized());
0 ignored issues
show
Bug introduced by
The method isProxyInitialized does only exist in ProxyManager\Proxy\GhostObjectInterface, but not in Doctrine\Tests\Models\Fr...Object\ComparableObject.

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...
275
276
        // due to implementation details, identity check is not reading lazy state:
277
        self::assertTrue($comparable->equalTo($comparable));
0 ignored issues
show
Documentation introduced by
$comparable is of type object<Doctrine\Tests\Mo...y\GhostObjectInterface>, but the function expects a object<self>.

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...
Bug introduced by
The method equalTo does only exist in Doctrine\Tests\Models\Fr...Object\ComparableObject, but not in ProxyManager\Proxy\GhostObjectInterface.

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...
278
279
        self::assertFalse($comparable->isProxyInitialized());
280
    }
281
282
    public function testFriendObjectsLazyLoadWhenAccessingLazyState()
283
    {
284
        /* @var $persister BasicEntityPersister|\PHPUnit_Framework_MockObject_MockObject */
285
        $persister = $this
286
            ->getMockBuilder(BasicEntityPersister::class)
287
            ->setConstructorArgs([$this->emMock, $this->emMock->getClassMetadata(ComparableObject::class)])
288
            ->setMethods(['loadById'])
289
            ->getMock();
290
291
        $persister
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\ORM\Persisters\...ty\BasicEntityPersister.

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...
292
            ->expects(self::exactly(2))
293
            ->method('loadById')
294
            ->with(
295
                self::logicalOr(['id' => 123], ['id' => 456]),
296
                self::logicalAnd(
297
                    self::isInstanceOf(GhostObjectInterface::class),
298
                    self::isInstanceOf(ComparableObject::class)
299
                )
300
            )
301
            ->willReturnCallback(function (array $id, ComparableObject $comparableObject) {
302
                $comparableObject->setComparedFieldValue(\json_encode($id));
303
304
                return $comparableObject;
305
            });
306
307
        $this->uowMock->setEntityPersister(ComparableObject::class, $persister);
0 ignored issues
show
Bug introduced by
It seems like $persister defined by $this->getMockBuilder(\D...'loadById'))->getMock() on line 285 can also be of type object<PHPUnit_Framework_MockObject_MockObject>; however, Doctrine\Tests\Mocks\Uni...k::setEntityPersister() does only seem to accept object<Doctrine\ORM\Pers...y\BasicEntityPersister>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
308
309
        $metadata = $this->emMock->getClassMetadata(ComparableObject::class);
310
311
        /* @var $comparable1 ComparableObject|GhostObjectInterface */
312
        $comparable1 = $this->proxyFactory->getProxy($metadata, ['id' => 123]);
0 ignored issues
show
Documentation introduced by
$metadata is of type object<Doctrine\Common\P...\Mapping\ClassMetadata>, but the function expects a object<Doctrine\ORM\Mapping\ClassMetadata>.

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...
313
        /* @var $comparable2 ComparableObject|GhostObjectInterface */
314
        $comparable2 = $this->proxyFactory->getProxy($metadata, ['id' => 456]);
0 ignored issues
show
Documentation introduced by
$metadata is of type object<Doctrine\Common\P...\Mapping\ClassMetadata>, but the function expects a object<Doctrine\ORM\Mapping\ClassMetadata>.

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...
315
316
        self::assertInstanceOf(ComparableObject::class, $comparable1);
317
        self::assertInstanceOf(ComparableObject::class, $comparable2);
318
        self::assertInstanceOf(GhostObjectInterface::class, $comparable1);
319
        self::assertInstanceOf(GhostObjectInterface::class, $comparable2);
320
        self::assertNotSame($comparable1, $comparable2);
321
        self::assertFalse($comparable1->isProxyInitialized());
0 ignored issues
show
Bug introduced by
The method isProxyInitialized does only exist in ProxyManager\Proxy\GhostObjectInterface, but not in Doctrine\Tests\Models\Fr...Object\ComparableObject.

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...
322
        self::assertFalse($comparable2->isProxyInitialized());
323
324
        self::assertFalse(
325
            $comparable1->equalTo($comparable2),
0 ignored issues
show
Documentation introduced by
$comparable2 is of type object<Doctrine\Tests\Mo...y\GhostObjectInterface>, but the function expects a object<self>.

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...
Bug introduced by
The method equalTo does only exist in Doctrine\Tests\Models\Fr...Object\ComparableObject, but not in ProxyManager\Proxy\GhostObjectInterface.

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...
326
            'Due to implementation details, identity check is not reading lazy state'
327
        );
328
329
        self::assertTrue($comparable1->isProxyInitialized());
330
        self::assertTrue($comparable2->isProxyInitialized());
331
    }
332
333
    public function testProxyMethodsSupportFuncGetArgsLogic()
334
    {
335
        /* @var $persister BasicEntityPersister|\PHPUnit_Framework_MockObject_MockObject */
336
        $persister = $this->createMock(BasicEntityPersister::class);
337
        $persister->expects(self::never())->method('loadById');
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\ORM\Persisters\...ty\BasicEntityPersister.

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...
338
339
        $this->uowMock->setEntityPersister(FuncGetArgs::class, $persister);
0 ignored issues
show
Bug introduced by
It seems like $persister defined by $this->createMock(\Doctr...EntityPersister::class) on line 336 can also be of type object<PHPUnit_Framework_MockObject_MockObject>; however, Doctrine\Tests\Mocks\Uni...k::setEntityPersister() does only seem to accept object<Doctrine\ORM\Pers...y\BasicEntityPersister>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
340
341
        /* @var $funcGetArgs FuncGetArgs|GhostObjectInterface */
342
        $funcGetArgs = $this->proxyFactory->getProxy(
343
            $this->emMock->getClassMetadata(FuncGetArgs::class),
0 ignored issues
show
Documentation introduced by
$this->emMock->getClassM...ics\FuncGetArgs::class) is of type object<Doctrine\Common\P...\Mapping\ClassMetadata>, but the function expects a object<Doctrine\ORM\Mapping\ClassMetadata>.

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...
344
            ['id' => 123]
345
        );
346
347
        self::assertInstanceOf(GhostObjectInterface::class, $funcGetArgs);
348
        self::assertFalse($funcGetArgs->isProxyInitialized());
0 ignored issues
show
Bug introduced by
The method isProxyInitialized does only exist in ProxyManager\Proxy\GhostObjectInterface, but not in Doctrine\Tests\Models\ProxySpecifics\FuncGetArgs.

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...
349
350
        self::assertSame(
351
            [1, 2, 3, 4],
352
            $funcGetArgs->funcGetArgsCallingMethod(1, 2, 3, 4),
0 ignored issues
show
Bug introduced by
The method funcGetArgsCallingMethod does only exist in Doctrine\Tests\Models\ProxySpecifics\FuncGetArgs, but not in ProxyManager\Proxy\GhostObjectInterface.

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...
353
            '`func_get_args()` calls are now supported in proxy implementations'
354
        );
355
356
        self::assertFalse($funcGetArgs->isProxyInitialized(), 'No lazy state was accessed anyway');
357
    }
358
359
    /**
360
     * @group #6722
361
     */
362
    public function testAccessingProxyToManyFieldsCausesNoAdditionalQueries() : void
363
    {
364
        /* @var $persister BasicEntityPersister|\PHPUnit_Framework_MockObject_MockObject */
365
        $persister = $this->createMock(BasicEntityPersister::class);
366
        $persister->expects(self::never())->method('loadById');
0 ignored issues
show
Bug introduced by
The method expects does only exist in PHPUnit_Framework_MockObject_MockObject, but not in Doctrine\ORM\Persisters\...ty\BasicEntityPersister.

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...
367
368
        $this->uowMock->setEntityPersister(CmsUser::class, $persister);
0 ignored issues
show
Bug introduced by
It seems like $persister defined by $this->createMock(\Doctr...EntityPersister::class) on line 365 can also be of type object<PHPUnit_Framework_MockObject_MockObject>; however, Doctrine\Tests\Mocks\Uni...k::setEntityPersister() does only seem to accept object<Doctrine\ORM\Pers...y\BasicEntityPersister>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
369
370
        /* @var $user CmsUser|GhostObjectInterface */
371
        $user = $this->proxyFactory->getProxy(CmsUser::class, ['id' => 123]);
372
373
        self::assertInstanceOf(GhostObjectInterface::class, $user);
374
        self::assertFalse($user->isProxyInitialized());
0 ignored issues
show
Bug introduced by
The method isProxyInitialized does only exist in ProxyManager\Proxy\GhostObjectInterface, but not in Doctrine\Tests\Models\CMS\CmsUser.

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...
375
376
        /* @var $phoneNumbers PersistentCollection */
377
        $phoneNumbers = $user->phonenumbers;
378
379
        self::assertInstanceOf(PersistentCollection::class, $phoneNumbers);
380
        self::assertFalse($phoneNumbers->isDirty());
381
        self::assertFalse($phoneNumbers->isInitialized());
382
        self::assertSame($user, $phoneNumbers->getOwner());
383
384
        /* @var $groups PersistentCollection */
385
        $groups = $user->groups;
386
387
        self::assertInstanceOf(PersistentCollection::class, $groups);
388
        self::assertFalse($groups->isDirty());
389
        self::assertFalse($groups->isInitialized());
390
        self::assertSame($user, $groups->getOwner());
391
392
        self::assertFalse($user->isProxyInitialized(), 'No lazy state was accessed anyway');
393
    }
394
}
395
396
abstract class AbstractClass
397
{
398
399
}
400