File: DDC2306Test.php

package info (click to toggle)
doctrine 3.3.3%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, trixie
  • size: 11,236 kB
  • sloc: php: 105,633; xml: 1,312; makefile: 35; sh: 14
file content (161 lines) | stat: -rw-r--r-- 4,374 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
<?php

declare(strict_types=1);

namespace Doctrine\Tests\ORM\Functional\Ticket;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping\Column;
use Doctrine\ORM\Mapping\Entity;
use Doctrine\ORM\Mapping\GeneratedValue;
use Doctrine\ORM\Mapping\Id;
use Doctrine\ORM\Mapping\ManyToOne;
use Doctrine\ORM\Mapping\OneToMany;
use Doctrine\Tests\OrmFunctionalTestCase;
use PHPUnit\Framework\Attributes\Group;

use function assert;

#[Group('DDC-2306')]
class DDC2306Test extends OrmFunctionalTestCase
{
    protected function setUp(): void
    {
        parent::setUp();

        $this->createSchemaForModels(
            DDC2306Zone::class,
            DDC2306User::class,
            DDC2306Address::class,
            DDC2306UserAddress::class,
        );
    }

    /**
     * Verifies that when eager loading is triggered, proxies are kept managed.
     *
     * The problem resides in the refresh hint passed to {@see \Doctrine\ORM\UnitOfWork::createEntity},
     * which, as of DDC-1734, causes the proxy to be marked as un-managed.
     * The check against the identity map only uses the identifier hash and the passed in class name, and
     * does not take into account the fact that the set refresh hint may be for an entity of a different
     * type from the one passed to {@see \Doctrine\ORM\UnitOfWork::createEntity}
     *
     * As a result, a refresh requested for an entity `Foo` with identifier `123` may cause a proxy
     * of type `Bar` with identifier `123` to be marked as un-managed.
     */
    public function testIssue(): void
    {
        $zone          = new DDC2306Zone();
        $user          = new DDC2306User();
        $address       = new DDC2306Address();
        $userAddress   = new DDC2306UserAddress($user, $address);
        $user->zone    = $zone;
        $address->zone = $zone;

        $this->_em->persist($zone);
        $this->_em->persist($user);
        $this->_em->persist($address);
        $this->_em->persist($userAddress);
        $this->_em->flush();
        $this->_em->clear();

        $address = $this->_em->find(DDC2306Address::class, $address->id);
        assert($address instanceof DDC2306Address);
        $user = $address->users->first()->user;

        $this->assertTrue($this->isUninitializedObject($user));
        self::assertInstanceOf(DDC2306User::class, $user);

        $userId = $user->id;

        self::assertNotNull($userId);

        $this->_em->getUnitOfWork()->initializeObject($user);

        self::assertEquals(
            $userId,
            $user->id,
            'As of DDC-1734, the identifier is NULL for un-managed proxies. The identifier should be an integer here',
        );
    }
}

#[Entity]
class DDC2306Zone
{
    /** @var int */
    #[Id]
    #[Column(type: 'integer')]
    #[GeneratedValue]
    public $id;
}

#[Entity]
class DDC2306User
{
    /** @var int */
    #[Id]
    #[Column(type: 'integer')]
    #[GeneratedValue]
    public $id;

    /** @var DDC2306UserAddress[]|Collection */
    #[OneToMany(targetEntity: 'DDC2306UserAddress', mappedBy: 'user')]
    public $addresses;

    /** @var DDC2306Zone */
    #[ManyToOne(targetEntity: 'DDC2306Zone', fetch: 'EAGER')]
    public $zone;

    /** Constructor */
    public function __construct()
    {
        $this->addresses = new ArrayCollection();
    }
}

#[Entity]
class DDC2306Address
{
    /** @var int */
    #[Id]
    #[Column(type: 'integer')]
    #[GeneratedValue]
    public $id;

    /** @var DDC2306UserAddress[]|Collection */
    #[OneToMany(targetEntity: 'DDC2306UserAddress', mappedBy: 'address', orphanRemoval: true)]
    public $users;

    /** @var DDC2306Zone */
    #[ManyToOne(targetEntity: 'DDC2306Zone', fetch: 'EAGER')]
    public $zone;

    /** Constructor */
    public function __construct()
    {
        $this->users = new ArrayCollection();
    }
}

#[Entity]
class DDC2306UserAddress
{
    /** @var int */
    #[Id]
    #[Column(type: 'integer')]
    #[GeneratedValue]
    public $id;

    /** Constructor */
    public function __construct(
        #[ManyToOne(targetEntity: 'DDC2306User')]
        public DDC2306User $user,
        #[ManyToOne(targetEntity: 'DDC2306Address', fetch: 'LAZY')]
        public DDC2306Address $address,
    ) {
        $user->addresses->add($this);
        $address->users->add($this);
    }
}