Passed
Push — master ( d70c89...2d756e )
by Christian
01:55
created

TablePrefixEventListener::addSequenceGenerator()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 7
dl 0
loc 11
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 3
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * (c) Christian Gripp <[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
namespace Core23\Doctrine\EventListener\ORM;
13
14
use Doctrine\Common\EventSubscriber;
15
use Doctrine\ORM\EntityManager;
16
use Doctrine\ORM\Event\LoadClassMetadataEventArgs;
17
use Doctrine\ORM\Events;
18
use Doctrine\ORM\Id\SequenceGenerator;
19
use Doctrine\ORM\Mapping\ClassMetadata;
20
use Doctrine\ORM\Mapping\ClassMetadataInfo;
21
22
final class TablePrefixEventListener implements EventSubscriber
23
{
24
    /**
25
     * @var string|null
26
     */
27
    private $prefix;
28
29
    /**
30
     * @param string|null $prefix
31
     */
32
    public function __construct(?string $prefix)
33
    {
34
        $this->prefix = $prefix;
35
    }
36
37
    /**
38
     * {@inheritdoc}
39
     */
40
    public function getSubscribedEvents(): array
41
    {
42
        return [
43
            Events::loadClassMetadata,
44
        ];
45
    }
46
47
    /**
48
     * @param LoadClassMetadataEventArgs $args
49
     */
50
    public function loadClassMetadata(LoadClassMetadataEventArgs $args): void
51
    {
52
        if (null === $this->prefix) {
53
            return;
54
        }
55
56
        $classMetadata = $args->getClassMetadata();
57
        $entityManager = $args->getEntityManager();
58
59
        $this->addTablePrefix($classMetadata);
60
        $this->addSequencePrefix($classMetadata, $entityManager);
61
    }
62
63
    /**
64
     * @param ClassMetadata $classMetadata
65
     */
66
    private function addTablePrefix(ClassMetadata $classMetadata): void
67
    {
68
        if ($classMetadata->isInheritanceTypeSingleTable() && !$classMetadata->isRootEntity()) {
69
            return;
70
        }
71
72
        $tableName = $classMetadata->getTableName();
73
74
        if (!$this->prefixExists($tableName)) {
75
            $classMetadata->setPrimaryTable([
76
                'name' => $this->prefix.$tableName,
77
            ]);
78
        }
79
80
        foreach ($classMetadata->getAssociationMappings() as $fieldName => $mapping) {
81
            $this->evaluteMapping($classMetadata, $mapping, $fieldName);
82
        }
83
    }
84
85
    /**
86
     * @param ClassMetadata $classMetadata
87
     * @param EntityManager $em
88
     */
89
    private function addSequencePrefix(ClassMetadata $classMetadata, EntityManager $em): void
90
    {
91
        if ($classMetadata->isInheritanceTypeSingleTable() && !$classMetadata->isRootEntity()) {
92
            return;
93
        }
94
95
        if (!$classMetadata->isIdGeneratorSequence()) {
96
            return;
97
        }
98
99
        $newDefinition  = $classMetadata->sequenceGeneratorDefinition;
100
101
        $sequenceName = $newDefinition['sequenceName'];
102
        if (!$this->prefixExists($sequenceName)) {
103
            $newDefinition['sequenceName'] = $this->prefix.$sequenceName;
104
        }
105
106
        $classMetadata->setSequenceGeneratorDefinition($newDefinition);
107
108
        if (isset($classMetadata->idGenerator)) {
109
            $this->addSequenceGenerator($classMetadata, $em, $newDefinition);
110
        }
111
    }
112
113
    /**
114
     * @param string $name
115
     *
116
     * @return bool
117
     */
118
    private function prefixExists(string $name): bool
119
    {
120
        return 0 === strpos($name, (string) $this->prefix);
121
    }
122
123
    /**
124
     * @param ClassMetadata $classMetadata
125
     * @param array         $mapping
126
     * @param string        $fieldName
127
     */
128
    private function evaluteMapping(ClassMetadata $classMetadata, array $mapping, string $fieldName): void
129
    {
130
        if (ClassMetadataInfo::MANY_TO_MANY !== $mapping['type']) {
131
            return;
132
        }
133
134
        if (isset($classMetadata->associationMappings[$fieldName]['joinTable']['name'])) {
135
            $mappedTableName = $classMetadata->associationMappings[$fieldName]['joinTable']['name'];
136
137
            if (!$this->prefixExists($mappedTableName)) {
138
                $classMetadata->associationMappings[$fieldName]['joinTable']['name'] = $this->prefix.$mappedTableName;
139
            }
140
        }
141
    }
142
143
    /**
144
     * @param ClassMetadata $classMetadata
145
     * @param EntityManager $em
146
     * @param array         $definition
147
     */
148
    private function addSequenceGenerator(ClassMetadata $classMetadata, EntityManager $em, array $definition): void
149
    {
150
        $sequenceGenerator = new SequenceGenerator(
151
            $em->getConfiguration()->getQuoteStrategy()->getSequenceName(
152
                $definition,
153
                $classMetadata,
154
                $em->getConnection()->getDatabasePlatform()
155
            ),
156
            $definition['allocationSize']
157
        );
158
        $classMetadata->setIdGenerator($sequenceGenerator);
159
    }
160
}
161