Passed
Pull Request — master (#2428)
by Vincent
03:30
created

DataPersister::persist()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 7
nc 3
nop 2
dl 0
loc 14
rs 10
c 0
b 0
f 0
1
<?php
2
3
/*
4
 * This file is part of the API Platform project.
5
 *
6
 * (c) Kévin Dunglas <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace ApiPlatform\Core\Bridge\Doctrine\Common;
15
16
use ApiPlatform\Core\DataPersister\ContextAwareDataPersisterInterface;
17
use ApiPlatform\Core\Util\ClassInfoTrait;
18
use Doctrine\Common\Persistence\ManagerRegistry;
19
use Doctrine\Common\Persistence\ObjectManager as DoctrineObjectManager;
20
use Doctrine\ORM\Mapping\ClassMetadataInfo;
21
use Symfony\Component\PropertyAccess\PropertyAccess;
22
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
23
24
/**
25
 * Data persister for Doctrine.
26
 *
27
 * @author Baptiste Meyer <[email protected]>
28
 */
29
final class DataPersister implements ContextAwareDataPersisterInterface
30
{
31
    use ClassInfoTrait;
32
33
    private $managerRegistry;
34
    private $propertyAccessor;
35
36
    public function __construct(ManagerRegistry $managerRegistry, PropertyAccessorInterface $propertyAccessor = null)
37
    {
38
        $this->managerRegistry = $managerRegistry;
39
        $this->propertyAccessor = $propertyAccessor ?? PropertyAccess::createPropertyAccessor();
40
    }
41
42
    /**
43
     * {@inheritdoc}
44
     */
45
    public function supports($data, array $context = []): bool
46
    {
47
        return null !== $this->getManager($data);
48
    }
49
50
    /**
51
     * {@inheritdoc}
52
     */
53
    public function persist($data, array $context = [])
54
    {
55
        if (!$manager = $this->getManager($data)) {
56
            return $data;
57
        }
58
59
        if (!$manager->contains($data) || $this->isDeferredExplicit($manager, $data)) {
60
            $manager->persist($data);
61
        }
62
63
        $manager->flush();
64
        $manager->refresh($data);
65
66
        return $data;
67
    }
68
69
    /**
70
     * {@inheritdoc}
71
     */
72
    public function remove($data, array $context = [])
73
    {
74
        if (!$manager = $this->getManager($data)) {
75
            return;
76
        }
77
78
        $manager->remove($data);
79
        $manager->flush();
80
    }
81
82
    /**
83
     * {@inheritdoc}
84
     */
85
    public function removeElementFromCollection($data, array $context = [])
86
    {
87
        if (!$manager = $this->getManager($data)) {
0 ignored issues
show
Unused Code introduced by
The assignment to $manager is dead and can be removed.
Loading history...
88
            return;
89
        }
90
91
        $context['parentData']->removeRelatedDummy($data);
92
        $this->persist($context['parentData'], $context);
93
    }
94
95
    /**
96
     * Gets the Doctrine object manager associated with given data.
97
     */
98
    private function getManager($data): ?DoctrineObjectManager
99
    {
100
        return \is_object($data) ? $this->managerRegistry->getManagerForClass($this->getObjectClass($data)) : null;
101
    }
102
103
    /**
104
     * Checks if doctrine does not manage data automatically.
105
     */
106
    private function isDeferredExplicit(DoctrineObjectManager $manager, $data): bool
107
    {
108
        $classMetadata = $manager->getClassMetadata($this->getObjectClass($data));
109
        if ($classMetadata instanceof ClassMetadataInfo && method_exists($classMetadata, 'isChangeTrackingDeferredExplicit')) {
110
            return $classMetadata->isChangeTrackingDeferredExplicit();
111
        }
112
113
        return false;
114
    }
115
}
116