MetadataBuilder   A
last analyzed

Complexity

Total Complexity 17

Size/Duplication

Total Lines 156
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 8

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 17
c 1
b 0
f 0
lcom 1
cbo 8
dl 0
loc 156
rs 10

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A buildMetadata() 0 15 2
A buildMetadataForDataContainer() 0 21 3
A buildReverseAssociationMetadata() 0 16 4
C validateDataItem() 0 29 7
1
<?php
2
/**
3
 * @link    https://github.com/nnx-framework/doctrine-fixture-module
4
 * @author  Malofeykin Andrey  <[email protected]>
5
 */
6
namespace Nnx\JmsSerializerModule\DoctrineObjectEngine;
7
8
use Doctrine\Common\Persistence\ObjectManager;
9
use Nnx\JmsSerializerModule\DataContainer;
10
11
/**
12
 * Class MetadataBuilder
13
 *
14
 * @package Nnx\JmsSerializerModule\DoctrineObjectEngine
15
 */
16
class MetadataBuilder implements MetadataBuilderInterface
17
{
18
    /**
19
     * Контейнер с данными для фикстуры
20
     *
21
     * @var DataContainer\DataContainerInterface
22
     */
23
    private $dataContainer;
24
25
    /**
26
     * Менеджер доктрины
27
     *
28
     * @var ObjectManager
29
     */
30
    private $objectManager;
31
32
    /**
33
     * @var MetadataInterface
34
     */
35
    private $metadata;
36
37
    /**
38
     * @var MetadataInterface
39
     */
40
    protected $metadataPrototype;
41
42
    /**
43
     * MetadataBuilder constructor.
44
     *
45
     * @param MetadataInterface $metadataPrototype
46
     */
47
    public function __construct(MetadataInterface $metadataPrototype)
48
    {
49
        $this->metadataPrototype = $metadataPrototype;
50
    }
51
52
    /**
53
     * Подготавливает метаданные
54
     *
55
     * @param DataContainer\DataContainerInterface $dataContainer
56
     * @param                        $entityClassName
57
     * @param ObjectManager          $objectManager
58
     *
59
     * @return MetadataInterface
60
     * @throws \Nnx\JmsSerializerModule\DoctrineObjectEngine\Exception\RuntimeException
61
     */
62
    public function buildMetadata(DataContainer\DataContainerInterface $dataContainer, $entityClassName, ObjectManager $objectManager)
63
    {
64
        $this->dataContainer = $dataContainer;
65
        $this->objectManager = $objectManager;
66
        $this->metadata = clone $this->metadataPrototype;
67
68
        $entities = $dataContainer->getEntities();
69
70
        foreach ($entities as $dataItem) {
71
            $this->buildMetadataForDataContainer($dataItem, $entityClassName);
72
        }
73
74
75
        return $this->metadata;
76
    }
77
78
    /**
79
     * Подготавливает метаданные для сущности
80
     *
81
     * @param DataContainer\EntityInterface $dataItem
82
     * @param        $entityClassName
83
     *
84
     * @throws \Nnx\JmsSerializerModule\DoctrineObjectEngine\Exception\RuntimeException
85
     */
86
    protected function buildMetadataForDataContainer(DataContainer\EntityInterface $dataItem, $entityClassName)
87
    {
88
        $this->metadata->linkDataContainerToEntityClassName($dataItem, $entityClassName);
89
90
        $dataItemAssociations = $dataItem->getAssociations();
91
92
        $entityMetadata = $this->objectManager->getClassMetadata($entityClassName);
93
94
        foreach ($dataItemAssociations as $dataItemAssociation) {
95
            $associationDataItems = $dataItemAssociation->getEntities();
96
            $associationName = $dataItemAssociation->getName();
97
98
            $associationTargetClass = $entityMetadata->getAssociationTargetClass($associationName);
99
100
            foreach ($associationDataItems as $associationDataItem) {
101
                $this->buildReverseAssociationMetadata($associationDataItem, $associationTargetClass, $dataItemAssociation);
102
                $this->metadata->addAssociationInfo($dataItem, $associationDataItem, $dataItemAssociation);
103
                $this->buildMetadataForDataContainer($associationDataItem, $associationTargetClass);
104
            }
105
        }
106
    }
107
108
    /**
109
     * Добавляет метаданные для двухсторонних ассоциаций
110
     *
111
     * @param DataContainer\EntityInterface      $childEntity
112
     * @param             $childEntityClassName
113
     * @param DataContainer\Association $targetAssociation
114
     */
115
    protected function buildReverseAssociationMetadata(DataContainer\EntityInterface $childEntity, $childEntityClassName, DataContainer\Association $targetAssociation)
116
    {
117
        $childEntityMetadata = $this->objectManager->getClassMetadata($childEntityClassName);
118
        $childEntityAssociationNames = $childEntityMetadata->getAssociationNames();
119
120
        $targetAssociationName = $targetAssociation->getName();
121
        foreach ($childEntityAssociationNames as $childEntityAssociationName) {
122
            if ($childEntityMetadata->isAssociationInverseSide($childEntityAssociationName)) {
123
                $associationMappedByTargetField = $childEntityMetadata->getAssociationMappedByTargetField($childEntityAssociationName);
124
125
                if ($associationMappedByTargetField === $targetAssociationName) {
126
                    $this->metadata->addReverseAssociationInfo($childEntity, $childEntity->getParentEntity(), $childEntityAssociationName);
0 ignored issues
show
Bug introduced by
It seems like $childEntity->getParentEntity() can be null; however, addReverseAssociationInfo() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
127
                }
128
            }
129
        }
130
    }
131
132
133
    /**
134
     * Проверка контейнера с данными
135
     *
136
     * @param DataContainer\EntityInterface $dataItem
137
     * @param        $entityClassName
138
     *
139
     * @return void
140
     * @throws \Nnx\JmsSerializerModule\DoctrineObjectEngine\Exception\RuntimeException
141
     */
142
    protected function validateDataItem(DataContainer\EntityInterface $dataItem, $entityClassName)
143
    {
144
        $dataItemAssociations = $dataItem->getAssociations();
145
        $properties = $dataItem->getProperties();
146
147
        $entityMetadata = $this->objectManager->getClassMetadata($entityClassName);
148
        foreach ($properties as $property) {
149
            $propertyName = $property->getName();
150
151
            if (!$entityMetadata->hasField($propertyName)) {
152
                $errMsg = sprintf('Property %s not found in %s', $propertyName, $entityClassName);
153
                throw new Exception\RuntimeException($errMsg);
154
            }
155
        }
156
157
        foreach ($dataItemAssociations as $dataItemAssociation) {
158
            $dataItemAssociationName = $dataItemAssociation->getName();
159
160
            if (!$entityMetadata->hasAssociation($dataItemAssociationName)) {
161
                $errMsg = sprintf('Association %s not found in %s', $dataItemAssociationName, $entityClassName);
162
                throw new Exception\RuntimeException($errMsg);
163
            }
164
        }
165
166
        if (0 === count($dataItemAssociations) && 0 === count($properties)) {
167
            $errMsg = sprintf('Data container id:%s is empty', $dataItem->getId());
168
            throw new Exception\RuntimeException($errMsg);
169
        }
170
    }
171
}
172