TablePrefixEventListener   A
last analyzed

Complexity

Total Complexity 21

Size/Duplication

Total Lines 106
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
wmc 21
eloc 44
dl 0
loc 106
rs 10
c 1
b 0
f 1

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A getSubscribedEvents() 0 4 1
A addSequenceGenerator() 0 11 1
A loadClassMetadata() 0 11 2
A prefixExists() 0 3 1
A addTablePrefix() 0 16 5
A addSequencePrefix() 0 21 6
A evaluteMapping() 0 11 4
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
    public function __construct(?string $prefix)
30
    {
31
        $this->prefix = $prefix;
32
    }
33
34
    public function getSubscribedEvents(): array
35
    {
36
        return [
37
            Events::loadClassMetadata,
38
        ];
39
    }
40
41
    public function loadClassMetadata(LoadClassMetadataEventArgs $args): void
42
    {
43
        if (null === $this->prefix) {
44
            return;
45
        }
46
47
        $classMetadata = $args->getClassMetadata();
48
        $entityManager = $args->getEntityManager();
49
50
        $this->addTablePrefix($classMetadata);
51
        $this->addSequencePrefix($classMetadata, $entityManager);
52
    }
53
54
    private function addTablePrefix(ClassMetadata $classMetadata): void
55
    {
56
        if ($classMetadata->isInheritanceTypeSingleTable() && !$classMetadata->isRootEntity()) {
57
            return;
58
        }
59
60
        $tableName = $classMetadata->getTableName();
61
62
        if (!$this->prefixExists($tableName)) {
63
            $classMetadata->setPrimaryTable([
64
                'name' => $this->prefix.$tableName,
65
            ]);
66
        }
67
68
        foreach ($classMetadata->getAssociationMappings() as $fieldName => $mapping) {
69
            $this->evaluteMapping($classMetadata, $mapping, $fieldName);
70
        }
71
    }
72
73
    private function addSequencePrefix(ClassMetadata $classMetadata, EntityManager $em): void
74
    {
75
        if ($classMetadata->isInheritanceTypeSingleTable() && !$classMetadata->isRootEntity()) {
76
            return;
77
        }
78
79
        if (!$classMetadata->isIdGeneratorSequence()) {
80
            return;
81
        }
82
83
        $newDefinition  = $classMetadata->sequenceGeneratorDefinition;
84
85
        $sequenceName = $newDefinition['sequenceName'];
86
        if (!$this->prefixExists($sequenceName)) {
87
            $newDefinition['sequenceName'] = $this->prefix.$sequenceName;
88
        }
89
90
        $classMetadata->setSequenceGeneratorDefinition($newDefinition);
91
92
        if (isset($classMetadata->idGenerator)) {
93
            $this->addSequenceGenerator($classMetadata, $em, $newDefinition);
94
        }
95
    }
96
97
    private function prefixExists(string $name): bool
98
    {
99
        return 0 === strpos($name, (string) $this->prefix);
100
    }
101
102
    private function evaluteMapping(ClassMetadata $classMetadata, array $mapping, string $fieldName): void
103
    {
104
        if (ClassMetadataInfo::MANY_TO_MANY !== $mapping['type']) {
105
            return;
106
        }
107
108
        if (isset($classMetadata->associationMappings[$fieldName]['joinTable']['name'])) {
109
            $mappedTableName = $classMetadata->associationMappings[$fieldName]['joinTable']['name'];
110
111
            if (!$this->prefixExists($mappedTableName)) {
112
                $classMetadata->associationMappings[$fieldName]['joinTable']['name'] = $this->prefix.$mappedTableName;
113
            }
114
        }
115
    }
116
117
    private function addSequenceGenerator(ClassMetadata $classMetadata, EntityManager $em, array $definition): void
118
    {
119
        $sequenceGenerator = new SequenceGenerator(
120
            $em->getConfiguration()->getQuoteStrategy()->getSequenceName(
121
                $definition,
122
                $classMetadata,
123
                $em->getConnection()->getDatabasePlatform()
124
            ),
125
            $definition['allocationSize']
126
        );
127
        $classMetadata->setIdGenerator($sequenceGenerator);
128
    }
129
}
130