Completed
Pull Request — master (#14)
by Pavel
03:32
created

Mapping/Driver/YmlMetadataDriver.php (2 issues)

Labels
Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace Bankiru\Api\Doctrine\Mapping\Driver;
4
5
use Bankiru\Api\Doctrine\Exception\MappingException;
6
use Bankiru\Api\Doctrine\Mapping\ApiMetadata;
7
use Bankiru\Api\Doctrine\Mapping\EntityMetadata;
8
use Bankiru\Api\Doctrine\Rpc\Method\EntityMethodProvider;
9
use Bankiru\Api\Doctrine\Rpc\Method\MethodProvider;
10
use Doctrine\Common\Persistence\Mapping\ClassMetadata;
11
use Doctrine\Common\Persistence\Mapping\Driver\FileDriver;
12
use Symfony\Component\Yaml\Exception\ParseException;
13
use Symfony\Component\Yaml\Yaml;
14
15
class YmlMetadataDriver extends FileDriver
16
{
17
    /**
18
     * Loads the metadata for the specified class into the provided container.
19
     *
20
     * @param string                       $className
21
     * @param EntityMetadata|ClassMetadata $metadata
22
     *
23
     * @return void
24
     * @throws MappingException
25
     */
26 18
    public function loadMetadataForClass($className, ClassMetadata $metadata)
27
    {
28 18
        $element = $this->getElement($className);
29
30 18
        switch ($element['type']) {
31 18
            case 'entity':
32 18
                if (array_key_exists('repositoryClass', $element)) {
33 2
                    $metadata->setCustomRepositoryClass($element['repositoryClass']);
34 2
                }
35 18
                break;
36
            case 'mappedSuperclass':
37
                $metadata->isMappedSuperclass = true;
38
                $metadata->setCustomRepositoryClass(
39
                    array_key_exists('repositoryClass', $element) ? $element['repositoryClass'] : null
40
                );
41
                break;
42 18
        }
43
44
        // Configure API
45 18
        if (array_key_exists('api', $element)) {
46 18
            if (array_key_exists('name', $element['api'])) {
47 18
                $metadata->apiName = $element['api']['name'];
0 ignored issues
show
Accessing apiName on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
48 18
            }
49 18
        }
50
51
        // Configure Client
52 18
        if (array_key_exists('client', $element)) {
53 18
            if (array_key_exists('name', $element['client'])) {
54 18
                $metadata->clientName = $element['client']['name'];
55 18
            }
56
57 18
            $methodProvider = null;
58 18
            if (array_key_exists('methods', $element['client'])) {
59
                $methodProvider = new MethodProvider($element['client']['methods']);
60
            }
61 18
            if (array_key_exists('entityPath', $element['client'])) {
62
                $pathSeparator  =
63 18
                    array_key_exists('entityPathSeparator', $element['client']) ?
64 18
                        $element['client']['entityPathSeparator'] :
65 18
                        EntityMethodProvider::DEFAULT_PATH_SEPARATOR;
66
                $methodProvider =
67 18
                    new EntityMethodProvider($element['client']['entityPath'], $pathSeparator, $methodProvider);
68 18
            }
69
70 18
            if (null === $methodProvider && null === $metadata->methodProvider) {
0 ignored issues
show
Accessing methodProvider on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
71
                throw MappingException::noMethods();
72
            }
73
74 18
            if (null !== $methodProvider) {
75 18
                $metadata->methodProvider = $methodProvider;
76 18
            }
77 18
        }
78
79
        // Configure fields
80 18
        if (array_key_exists('fields', $element)) {
81 18
            foreach ($element['fields'] as $field => $mapping) {
82 18
                $mapping = $this->fieldToArray($field, $mapping);
83 18
                $metadata->mapField($mapping);
84 18
            }
85 18
        }
86
87
        // Configure identifiers
88 18
        $associationIds = [];
89 18
        if (array_key_exists('id', $element)) {
90
            // Evaluate identifier settings
91 18
            $defaults = ['generator' => ['strategy' => 'NATURAL']];
92 18
            foreach ($element['id'] as $name => $idElement) {
93 18
                if (isset($idElement['associationKey']) && (bool)$idElement['associationKey'] === true) {
94
                    $associationIds[$name] = true;
95
                    continue;
96
                }
97
98 18
                $mapping = $this->fieldToArray($name, $idElement);
99
100 18
                $mapping['id'] = true;
101 18
                $idElement     = array_replace_recursive($defaults, $idElement);
102
103 18
                $mapping['generator']['strategy'] =
104 18
                    constant(ApiMetadata::class . '::GENERATOR_TYPE_' . $idElement['generator']['strategy']);
105
106 18
                $metadata->mapIdentifier($mapping);
107 18
            }
108 18
        }
109
110 18
        foreach (['oneToOne', 'manyToOne', 'oneToMany'] as $type) {
111 18
            if (array_key_exists($type, $element)) {
112 14
                $associations = $element[$type];
113 14
                foreach ($associations as $name => $association) {
114 14
                    $this->mapAssociation($metadata, $type, $name, $association, $associationIds);
115 14
                }
116 14
            }
117 18
        }
118 18
    }
119
120
    /**
121
     * @param EntityMetadata $metadata
122
     * @param string         $type
123
     * @param string         $name
124
     * @param array          $association
125
     * @param int[]          $associationIds
126
     */
127 14
    protected function mapAssociation(EntityMetadata $metadata, $type, $name, $association, $associationIds)
128
    {
129 14
        $mapping           = $this->fieldToArray($name, $association);
130 14
        $mapping['target'] = $association['target'];
131 14
        if (isset($association['fetch'])) {
132
            $mapping['fetch'] = constant(ApiMetadata::class . '::FETCH_' . $association['fetch']);
133
        }
134
        switch ($type) {
135 14 View Code Duplication
            case 'oneToOne':
136
                $mapping['type'] = EntityMetadata::ONE_TO_ONE;
137
                if (isset($associationIds[$mapping['field']])) {
138
                    $mapping['id'] = true;
139
                }
140
                if (array_key_exists('mappedBy', $association)) {
141
                    $mapping['mappedBy'] = $association['mappedBy'];
142
                }
143
                if (array_key_exists('inversedBy', $association)) {
144
                    $mapping['inversedBy'] = $association['inversedBy'];
145
                }
146
                $metadata->mapOneToOne($mapping);
147
                break;
148 14
            case 'manyToOne':
149 14
                $mapping['type'] = EntityMetadata::MANY_TO_ONE;
150 14
                if (array_key_exists('inversedBy', $association)) {
151 14
                    $mapping['inversedBy'] = $association['inversedBy'];
152 14
                }
153 14
                $metadata->mapManyToOne($mapping);
154 14
                break;
155 14 View Code Duplication
            case 'oneToMany':
156 14
                $mapping['type'] = EntityMetadata::ONE_TO_MANY;
157 14
                if (array_key_exists('mappedBy', $association)) {
158 14
                    $mapping['mappedBy'] = $association['mappedBy'];
159 14
                }
160 14
                if (array_key_exists('orderBy', $association)) {
161
                    $mapping['orderBy'] = $association['orderBy'];
162
                }
163 14
                if (array_key_exists('indexBy', $association)) {
164
                    $mapping['indexBy'] = $association['indexBy'];
165
                }
166 14
                $metadata->mapOneToMany($mapping);
167 14
                break;
168
        }
169 14
    }
170
171
    /**
172
     * Loads a mapping file with the given name and returns a map
173
     * from class/entity names to their corresponding file driver elements.
174
     *
175
     * @param string $file The mapping file to load.
176
     *
177
     * @return array
178
     * @throws ParseException
179
     */
180 18
    protected function loadMappingFile($file)
181
    {
182 18
        return Yaml::parse(file_get_contents($file));
183
    }
184
185 18
    private function fieldToArray($field, $source)
186
    {
187
        $mapping = [
188 18
            'field'    => $field,
189 18
            'type'     => 'string',
190 18
            'nullable' => true,
191 18
        ];
192
193 18
        if (array_key_exists('type', $source)) {
194 18
            $mapping['type'] = $source['type'];
195 18
        }
196
197 18
        if (array_key_exists('nullable', $source)) {
198 5
            $mapping['nullable'] = $source['nullable'];
199 5
        }
200
201 18
        if (array_key_exists('api_field', $source)) {
202 16
            $mapping['api_field'] = $source['api_field'];
203 16
        }
204
205 18
        return $mapping;
206
    }
207
}
208
209