Passed
Pull Request — master (#7448)
by Ilya
11:47
created

php$1 ➔ testFlushWithExceptionClearsInProgressFlag()   A

Complexity

Conditions 3

Size

Total Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
dl 0
loc 26
rs 9.504
c 0
b 0
f 0

1 Method

Rating   Name   Duplication   Size   Complexity  
A EntityManagerTest.php$1 ➔ preFlush() 0 3 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\Tests\ORM;
6
7
use Doctrine\Common\EventManager;
8
use Doctrine\DBAL\Connection;
9
use Doctrine\ORM\Configuration;
10
use Doctrine\ORM\EntityManager;
11
use Doctrine\ORM\Event\PreFlushEventArgs;
12
use Doctrine\ORM\Events;
13
use Doctrine\ORM\Exception\EntityManagerClosed;
14
use Doctrine\ORM\Exception\FlushInsideFlush;
15
use Doctrine\ORM\Mapping\ClassMetadataFactory;
16
use Doctrine\ORM\Mapping\Driver\MappingDriver;
17
use Doctrine\ORM\ORMInvalidArgumentException;
18
use Doctrine\ORM\Proxy\Factory\ProxyFactory;
19
use Doctrine\ORM\Query;
20
use Doctrine\ORM\Query\ResultSetMapping;
21
use Doctrine\ORM\QueryBuilder;
22
use Doctrine\ORM\UnitOfWork;
23
use Doctrine\Tests\Models\CMS\CmsUser;
24
use Doctrine\Tests\Models\GeoNames\Country;
25
use Doctrine\Tests\Models\IdentityIsAssociation\SimpleId;
26
use Doctrine\Tests\Models\IdentityIsAssociation\ToOneAssociationIdToSimpleId;
27
use Doctrine\Tests\Models\IdentityIsAssociation\ToOneCompositeAssociationToMultipleSimpleId;
28
use Doctrine\Tests\OrmTestCase;
29
use InvalidArgumentException;
30
use RuntimeException;
31
use stdClass;
32
use TypeError;
33
34
class EntityManagerTest extends OrmTestCase
35
{
36
    /** @var EntityManager */
37
    private $em;
38
39
    public function setUp() : void
40
    {
41
        parent::setUp();
42
43
        $this->em = $this->getTestEntityManager();
44
    }
45
46
    /**
47
     * @group DDC-899
48
     */
49
    public function testIsOpen() : void
50
    {
51
        self::assertTrue($this->em->isOpen());
52
        $this->em->close();
53
        self::assertFalse($this->em->isOpen());
54
    }
55
56
    public function testGetConnection() : void
57
    {
58
        self::assertInstanceOf(Connection::class, $this->em->getConnection());
59
    }
60
61
    public function testGetMetadataFactory() : void
62
    {
63
        self::assertInstanceOf(ClassMetadataFactory::class, $this->em->getMetadataFactory());
64
    }
65
66
    public function testGetConfiguration() : void
67
    {
68
        self::assertInstanceOf(Configuration::class, $this->em->getConfiguration());
69
    }
70
71
    public function testGetUnitOfWork() : void
72
    {
73
        self::assertInstanceOf(UnitOfWork::class, $this->em->getUnitOfWork());
74
    }
75
76
    public function testGetProxyFactory() : void
77
    {
78
        self::assertInstanceOf(ProxyFactory::class, $this->em->getProxyFactory());
79
    }
80
81
    public function testGetEventManager() : void
82
    {
83
        self::assertInstanceOf(EventManager::class, $this->em->getEventManager());
84
    }
85
86
    public function testCreateNativeQuery() : void
87
    {
88
        $rsm   = new ResultSetMapping();
89
        $query = $this->em->createNativeQuery('SELECT foo', $rsm);
90
91
        self::assertSame('SELECT foo', $query->getSql());
92
    }
93
94
    public function testCreateQueryBuilder() : void
95
    {
96
        self::assertInstanceOf(QueryBuilder::class, $this->em->createQueryBuilder());
97
    }
98
99
    public function testCreateQueryBuilderAliasValid() : void
100
    {
101
        $q  = $this->em->createQueryBuilder()
102
             ->select('u')->from(CmsUser::class, 'u');
103
        $q2 = clone $q;
104
105
        self::assertEquals('SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u', $q->getQuery()->getDql());
106
        self::assertEquals('SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u', $q2->getQuery()->getDql());
107
108
        $q3 = clone $q;
109
110
        self::assertEquals('SELECT u FROM Doctrine\Tests\Models\CMS\CmsUser u', $q3->getQuery()->getDql());
111
    }
112
113
    public function testCreateQueryDqlIsOptional() : void
114
    {
115
        self::assertInstanceOf(Query::class, $this->em->createQuery());
116
    }
117
118
    public function testGetPartialReference() : void
119
    {
120
        $user = $this->em->getPartialReference(CmsUser::class, 42);
121
        self::assertTrue($this->em->contains($user));
122
        self::assertEquals(42, $user->id);
123
        self::assertNull($user->getName());
124
    }
125
126
    public function testCreateQuery() : void
127
    {
128
        $q = $this->em->createQuery('SELECT 1');
129
        self::assertInstanceOf(Query::class, $q);
130
        self::assertEquals('SELECT 1', $q->getDql());
131
    }
132
133
    public static function dataMethodsAffectedByNoObjectArguments()
134
    {
135
        return [
136
            ['persist'],
137
            ['remove'],
138
            ['refresh'],
139
        ];
140
    }
141
142
    /**
143
     * @dataProvider dataMethodsAffectedByNoObjectArguments
144
     */
145
    public function testThrowsExceptionOnNonObjectValues($methodName) : void
146
    {
147
        $this->expectException(ORMInvalidArgumentException::class);
148
        $this->expectExceptionMessage('EntityManager#' . $methodName . '() expects parameter 1 to be an entity object, NULL given.');
149
150
        $this->em->{$methodName}(null);
151
    }
152
153
    public static function dataAffectedByErrorIfClosedException()
154
    {
155
        return [
156
            ['flush'],
157
            ['persist'],
158
            ['remove'],
159
            ['refresh'],
160
        ];
161
    }
162
163
    /**
164
     * @param string $methodName
165
     *
166
     * @dataProvider dataAffectedByErrorIfClosedException
167
     */
168
    public function testAffectedByErrorIfClosedException($methodName) : void
169
    {
170
        $this->expectException(EntityManagerClosed::class);
171
        $this->expectExceptionMessage('closed');
172
173
        $this->em->close();
174
        $this->em->{$methodName}(new stdClass());
175
    }
176
177
    public function dataToBeReturnedByTransactional()
178
    {
179
        return [
180
            [null],
181
            [false],
182
            ['foo'],
183
        ];
184
    }
185
186
    /**
187
     * @dataProvider dataToBeReturnedByTransactional
188
     */
189
    public function testTransactionalAcceptsReturn($value) : void
190
    {
191
        self::assertSame(
192
            $value,
193
            $this->em->transactional(static function ($em) use ($value) {
194
                return $value;
195
            })
196
        );
197
    }
198
199
    public function testTransactionalAcceptsVariousCallables() : void
200
    {
201
        self::assertSame('callback', $this->em->transactional([$this, 'transactionalCallback']));
202
    }
203
204
    public function transactionalCallback($em)
205
    {
206
        self::assertSame($this->em, $em);
207
        return 'callback';
208
    }
209
210
    public function testCreateInvalidConnection() : void
211
    {
212
        $this->expectException(InvalidArgumentException::class);
213
        $this->expectExceptionMessage('Invalid $connection argument of type integer given: "1".');
214
215
        $config = new Configuration();
216
        $config->setMetadataDriverImpl($this->createMock(MappingDriver::class));
217
        EntityManager::create(1, $config);
0 ignored issues
show
Bug introduced by
1 of type integer is incompatible with the type Doctrine\DBAL\Connection|array<mixed,mixed> expected by parameter $connection of Doctrine\ORM\EntityManager::create(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

217
        EntityManager::create(/** @scrutinizer ignore-type */ 1, $config);
Loading history...
218
    }
219
220
    /**
221
     * @group #5796
222
     */
223
    public function testTransactionalReThrowsThrowables() : void
224
    {
225
        try {
226
            $this->em->transactional(static function () {
227
                (static function (array $value) {
228
                    // this only serves as an IIFE that throws a `TypeError`
229
                })(null);
230
            });
231
232
            self::fail('TypeError expected to be thrown');
233
        } catch (TypeError $ignored) {
234
            self::assertFalse($this->em->isOpen());
235
        }
236
    }
237
238
    /**
239
     * @group 6017
240
     */
241
    public function testClearManager() : void
242
    {
243
        $entity = new Country(456, 'United Kingdom');
244
245
        $this->em->persist($entity);
246
247
        self::assertTrue($this->em->contains($entity));
248
249
        $this->em->clear();
250
251
        self::assertFalse($this->em->contains($entity));
252
    }
253
254
    public function testGetReferenceRetrievesReferencesWithGivenProxiesAsIdentifiers() : void
255
    {
256
        $simpleIdReference = $this->em->getReference(
257
            SimpleId::class,
258
            ['id' => 123]
259
        );
260
        /** @var GhostObjectInterface|ToOneAssociationIdToSimpleId $nestedReference */
261
        $nestedIdReference = $this->em->getReference(
262
            ToOneAssociationIdToSimpleId::class,
263
            ['simpleId' => $simpleIdReference]
264
        );
265
266
        self::assertInstanceOf(ToOneAssociationIdToSimpleId::class, $nestedIdReference);
267
        self::assertSame($simpleIdReference, $nestedIdReference->simpleId);
268
        self::assertTrue($this->em->contains($simpleIdReference));
269
        self::assertTrue($this->em->contains($nestedIdReference));
270
    }
271
272
    public function testGetReferenceRetrievesReferencesWithGivenProxiesAsIdentifiersEvenIfIdentifierOrderIsSwapped() : void
273
    {
274
        $simpleIdReferenceA = $this->em->getReference(
275
            SimpleId::class,
276
            ['id' => 123]
277
        );
278
        $simpleIdReferenceB = $this->em->getReference(
279
            SimpleId::class,
280
            ['id' => 456]
281
        );
282
        /** @var GhostObjectInterface|ToOneCompositeAssociationToMultipleSimpleId $nestedIdReference */
283
        $nestedIdReference = $this->em->getReference(
284
            ToOneCompositeAssociationToMultipleSimpleId::class,
285
            ['simpleIdB' => $simpleIdReferenceB, 'simpleIdA' => $simpleIdReferenceA]
286
        );
287
288
        self::assertInstanceOf(ToOneCompositeAssociationToMultipleSimpleId::class, $nestedIdReference);
289
        self::assertSame($simpleIdReferenceA, $nestedIdReference->simpleIdA);
290
        self::assertSame($simpleIdReferenceB, $nestedIdReference->simpleIdB);
291
        self::assertTrue($this->em->contains($simpleIdReferenceA));
292
        self::assertTrue($this->em->contains($simpleIdReferenceB));
293
        self::assertTrue($this->em->contains($nestedIdReference));
294
    }
295
296
    public function testCallingFlushInsideFlush() : void
297
    {
298
        $listener = new class()
299
        {
300
            public function preFlush(PreFlushEventArgs $eventArgs)
301
            {
302
                $eventArgs->getEntityManager()->flush();
303
            }
304
        };
305
306
        $this->expectException(FlushInsideFlush::class);
307
        $this->em->getEventManager()->addEventListener(Events::preFlush, $listener);
308
        $this->em->flush();
309
    }
310
311
    public function testFlushWithExceptionClearsInProgressFlag() : void
312
    {
313
        $listener = new class()
314
        {
315
            public function preFlush(PreFlushEventArgs $eventArgs)
0 ignored issues
show
Unused Code introduced by
The parameter $eventArgs is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

315
            public function preFlush(/** @scrutinizer ignore-unused */ PreFlushEventArgs $eventArgs)

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

Loading history...
316
            {
317
                throw new RuntimeException();
318
            }
319
        };
320
321
        $this->em->getEventManager()->addEventListener(Events::preFlush, $listener);
322
        try {
323
            $this->em->flush();
324
        } catch (RuntimeException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
Coding Style introduced by
Blank line found at start of control structure
Loading history...
325
326
        }
327
328
        $this->em->getEventManager()->removeEventListener(Events::preFlush, $listener);
329
330
        try {
331
            $this->em->flush();
332
        } catch (FlushInsideFlush $e) {
333
            $this->fail('EntityManager::$flushInProgress flag must be reset in case of exception during flush process');
334
        }
335
336
        $this->assertTrue(true);
337
    }
338
}
339