Completed
Push — master ( ba5b97...3964e0 )
by Paweł
63:44 queued 48:11
created

setAssociationMappings()   C

Complexity

Conditions 7
Paths 7

Size

Total Lines 26
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
c 2
b 1
f 0
dl 0
loc 26
rs 6.7272
cc 7
eloc 14
nc 7
nop 2
1
<?php
2
3
/*
4
 * This file is part of the Sylius package.
5
 *
6
 * (c) Paweł Jędrzejewski
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 Sylius\Bundle\ResourceBundle\EventListener;
13
14
use Doctrine\ORM\Event\LoadClassMetadataEventArgs;
15
use Doctrine\ORM\Events;
16
use Doctrine\ORM\Mapping\ClassMetadata;
17
use Doctrine\ORM\Mapping\ClassMetadataInfo;
18
19
/**
20
 * @author Ivan Molchanov <[email protected]>
21
 * @author Paweł Jędrzejewski <[email protected]>
22
 */
23
class ORMMappedSuperClassSubscriber extends AbstractDoctrineSubscriber
24
{
25
    /**
26
     * @return array
27
     */
28
    public function getSubscribedEvents()
29
    {
30
        return [
31
            Events::loadClassMetadata,
32
        ];
33
    }
34
35
    /**
36
     * @param LoadClassMetadataEventArgs $eventArgs
37
     */
38
    public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs)
39
    {
40
        $metadata = $eventArgs->getClassMetadata();
41
42
        $this->convertToEntityIfNeeded($metadata);
0 ignored issues
show
Compatibility introduced by
$metadata of type object<Doctrine\Common\P...\Mapping\ClassMetadata> is not a sub-type of object<Doctrine\ORM\Mapping\ClassMetadataInfo>. It seems like you assume a concrete implementation of the interface Doctrine\Common\Persistence\Mapping\ClassMetadata to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
43
44
        if (!$metadata->isMappedSuperclass) {
45
            $this->setAssociationMappings($metadata, $eventArgs->getEntityManager()->getConfiguration());
0 ignored issues
show
Compatibility introduced by
$metadata of type object<Doctrine\Common\P...\Mapping\ClassMetadata> is not a sub-type of object<Doctrine\ORM\Mapping\ClassMetadataInfo>. It seems like you assume a concrete implementation of the interface Doctrine\Common\Persistence\Mapping\ClassMetadata to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
46
        } else {
47
            $this->unsetAssociationMappings($metadata);
0 ignored issues
show
Compatibility introduced by
$metadata of type object<Doctrine\Common\P...\Mapping\ClassMetadata> is not a sub-type of object<Doctrine\ORM\Mapping\ClassMetadataInfo>. It seems like you assume a concrete implementation of the interface Doctrine\Common\Persistence\Mapping\ClassMetadata to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
48
        }
49
    }
50
51
    /**
52
     * @param ClassMetadataInfo $metadata
53
     */
54
    private function convertToEntityIfNeeded(ClassMetadataInfo $metadata)
55
    {
56
        if (false === $metadata->isMappedSuperclass) {
57
            return;
58
        }
59
60
        try {
61
            $resourceMetadata = $this->resourceRegistry->getByClass($metadata->getName());
62
        } catch (\InvalidArgumentException $exception) {
63
            return;
64
        }
65
66
        if ($metadata->getName() === $resourceMetadata->getClass('model')) {
67
            $metadata->isMappedSuperclass = false;
68
        }
69
    }
70
71
    /**
72
     * @param ClassMetadataInfo $metadata
73
     * @param $configuration
74
     */
75
    private function setAssociationMappings(ClassMetadataInfo $metadata, $configuration)
76
    {
77
        foreach (class_parents($metadata->getName()) as $parent) {
78
            $parentMetadata = new ClassMetadata(
79
                $parent,
80
                $configuration->getNamingStrategy()
81
            );
82
83
            if (false === $this->isSyliusClass($parentMetadata)) {
84
                continue;
85
            }
86
87
            if (false === in_array($parent, $configuration->getMetadataDriverImpl()->getAllClassNames())) {
88
                continue;
89
            }
90
91
            $configuration->getMetadataDriverImpl()->loadMetadataForClass($parent, $parentMetadata);
92
            if ($parentMetadata->isMappedSuperclass) {
93
                foreach ($parentMetadata->getAssociationMappings() as $key => $value) {
94
                    if ($this->hasRelation($value['type'])) {
95
                        $metadata->associationMappings[$key] = $value;
96
                    }
97
                }
98
            }
99
        }
100
    }
101
102
    /**
103
     * @param ClassMetadataInfo $metadata
104
     */
105
    private function unsetAssociationMappings(ClassMetadataInfo $metadata)
106
    {
107
        if (false === $this->isSyliusClass($metadata)) {
108
            return;
109
        }
110
111
        foreach ($metadata->getAssociationMappings() as $key => $value) {
112
            if ($this->hasRelation($value['type'])) {
113
                unset($metadata->associationMappings[$key]);
114
            }
115
        }
116
    }
117
118
    /**
119
     * @param $type
120
     *
121
     * @return bool
122
     */
123
    private function hasRelation($type)
124
    {
125
        return in_array(
126
            $type,
127
            [
128
                ClassMetadataInfo::MANY_TO_MANY,
129
                ClassMetadataInfo::ONE_TO_MANY,
130
                ClassMetadataInfo::ONE_TO_ONE,
131
            ],
132
            true
133
        );
134
    }
135
}
136