bankiru /
doctrine-api-client
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 | 25 | public function loadMetadataForClass($className, ClassMetadata $metadata) |
|
| 27 | { |
||
| 28 | 25 | $element = $this->getElement($className); |
|
| 29 | |||
| 30 | 25 | switch ($element['type']) { |
|
| 31 | 25 | case 'entity': |
|
| 32 | 25 | if (array_key_exists('repositoryClass', $element)) { |
|
| 33 | 2 | $metadata->setCustomRepositoryClass($element['repositoryClass']); |
|
| 34 | 2 | } |
|
| 35 | 25 | break; |
|
| 36 | case 'mappedSuperclass': |
||
| 37 | $metadata->isMappedSuperclass = true; |
||
| 38 | $metadata->setCustomRepositoryClass( |
||
| 39 | array_key_exists('repositoryClass', $element) ? $element['repositoryClass'] : null |
||
| 40 | ); |
||
| 41 | break; |
||
| 42 | 25 | } |
|
| 43 | |||
| 44 | // Configure API |
||
| 45 | 25 | if (array_key_exists('api', $element)) { |
|
| 46 | 25 | if (array_key_exists('factory', $element['api'])) { |
|
| 47 | 25 | $metadata->apiFactory = $element['api']['factory']; |
|
|
0 ignored issues
–
show
|
|||
| 48 | 25 | } |
|
| 49 | 25 | } |
|
| 50 | |||
| 51 | // Evaluate discriminatorColumn |
||
| 52 | 25 | if (isset($element['discriminatorField'])) { |
|
| 53 | 4 | $discrColumn = $element['discriminatorField']; |
|
| 54 | 4 | $metadata->setDiscriminatorField( |
|
| 55 | [ |
||
| 56 | 4 | 'name' => isset($discrColumn['name']) ? (string)$discrColumn['name'] : null, |
|
| 57 | 4 | 'type' => isset($discrColumn['type']) ? (string)$discrColumn['type'] : 'string', |
|
| 58 | ] |
||
| 59 | 4 | ); |
|
| 60 | 4 | } else { |
|
|
0 ignored issues
–
show
This
else statement is empty and can be removed.
This check looks for the These if (rand(1, 6) > 3) {
print "Check failed";
} else {
//print "Check succeeded";
}
could be turned into if (rand(1, 6) > 3) {
print "Check failed";
}
This is much more concise to read. Loading history...
|
|||
| 61 | // $metadata->setDiscriminatorField(['name' => 'dtype', 'type' => 'string']); |
||
|
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
67% of this comment could be valid code. Did you maybe forget this after debugging?
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it. The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production. This check looks for comments that seem to be mostly valid code and reports them. Loading history...
|
|||
| 62 | } |
||
| 63 | // Evaluate discriminatorMap |
||
| 64 | 25 | if (isset($element['discriminatorMap'])) { |
|
| 65 | $metadata->setDiscriminatorMap($element['discriminatorMap']); |
||
| 66 | } |
||
| 67 | |||
| 68 | // Configure Client |
||
| 69 | 25 | if (array_key_exists('client', $element)) { |
|
| 70 | 25 | if (array_key_exists('name', $element['client'])) { |
|
| 71 | 25 | $metadata->clientName = $element['client']['name']; |
|
| 72 | 25 | } |
|
| 73 | |||
| 74 | 25 | $methodProvider = null; |
|
| 75 | 25 | if (array_key_exists('methods', $element['client'])) { |
|
| 76 | $methodProvider = new MethodProvider($element['client']['methods']); |
||
| 77 | 1 | } |
|
| 78 | 25 | if (array_key_exists('entityPath', $element['client'])) { |
|
| 79 | $pathSeparator = |
||
| 80 | 25 | array_key_exists('entityPathSeparator', $element['client']) ? |
|
| 81 | 25 | $element['client']['entityPathSeparator'] : |
|
| 82 | 25 | EntityMethodProvider::DEFAULT_PATH_SEPARATOR; |
|
| 83 | $methodProvider = |
||
| 84 | 25 | new EntityMethodProvider($element['client']['entityPath'], $pathSeparator, $methodProvider); |
|
| 85 | 25 | } |
|
| 86 | |||
| 87 | 25 | 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
Loading history...
|
|||
| 88 | throw MappingException::noMethods(); |
||
| 89 | } |
||
| 90 | |||
| 91 | 25 | if (null !== $methodProvider) { |
|
| 92 | 25 | $metadata->methodProvider = $methodProvider; |
|
| 93 | 25 | } |
|
| 94 | 25 | } |
|
| 95 | |||
| 96 | // Configure fields |
||
| 97 | 25 | if (array_key_exists('fields', $element)) { |
|
| 98 | 25 | foreach ($element['fields'] as $field => $mapping) { |
|
| 99 | 25 | $mapping = $this->fieldToArray($field, $mapping); |
|
| 100 | 25 | $metadata->mapField($mapping); |
|
| 101 | 25 | } |
|
| 102 | 25 | } |
|
| 103 | |||
| 104 | // Configure identifiers |
||
| 105 | 25 | $associationIds = []; |
|
| 106 | 25 | if (array_key_exists('id', $element)) { |
|
| 107 | // Evaluate identifier settings |
||
| 108 | 25 | $defaults = ['generator' => ['strategy' => 'NATURAL']]; |
|
| 109 | 25 | foreach ($element['id'] as $name => $idElement) { |
|
| 110 | 25 | if (isset($idElement['associationKey']) && (bool)$idElement['associationKey'] === true) { |
|
| 111 | $associationIds[$name] = true; |
||
| 112 | continue; |
||
| 113 | } |
||
| 114 | |||
| 115 | 25 | $mapping = $this->fieldToArray($name, $idElement); |
|
| 116 | |||
| 117 | 25 | $mapping['id'] = true; |
|
| 118 | 25 | $idElement = array_replace_recursive($defaults, $idElement); |
|
| 119 | |||
| 120 | 25 | $mapping['generator']['strategy'] = |
|
| 121 | 25 | constant(ApiMetadata::class . '::GENERATOR_TYPE_' . $idElement['generator']['strategy']); |
|
| 122 | |||
| 123 | 25 | $metadata->mapIdentifier($mapping); |
|
| 124 | 25 | } |
|
| 125 | 25 | } |
|
| 126 | |||
| 127 | 25 | foreach (['oneToOne', 'manyToOne', 'oneToMany'] as $type) { |
|
| 128 | 25 | if (array_key_exists($type, $element)) { |
|
| 129 | 17 | $associations = $element[$type]; |
|
| 130 | 17 | foreach ($associations as $name => $association) { |
|
| 131 | 17 | $this->mapAssociation($metadata, $type, $name, $association, $associationIds); |
|
| 132 | 17 | } |
|
| 133 | 17 | } |
|
| 134 | 25 | } |
|
| 135 | 25 | } |
|
| 136 | |||
| 137 | /** |
||
| 138 | * @param EntityMetadata $metadata |
||
| 139 | * @param string $type |
||
| 140 | * @param string $name |
||
| 141 | * @param array $association |
||
| 142 | * @param int[] $associationIds |
||
| 143 | */ |
||
| 144 | 17 | protected function mapAssociation(EntityMetadata $metadata, $type, $name, $association, $associationIds) |
|
| 145 | { |
||
| 146 | 17 | $mapping = $this->fieldToArray($name, $association); |
|
| 147 | 17 | $mapping['target'] = $association['target']; |
|
| 148 | 17 | if (isset($association['fetch'])) { |
|
| 149 | $mapping['fetch'] = constant(ApiMetadata::class . '::FETCH_' . $association['fetch']); |
||
| 150 | } |
||
| 151 | switch ($type) { |
||
| 152 | 17 | View Code Duplication | case 'oneToOne': |
| 153 | $mapping['type'] = EntityMetadata::ONE_TO_ONE; |
||
| 154 | if (isset($associationIds[$mapping['field']])) { |
||
| 155 | $mapping['id'] = true; |
||
| 156 | } |
||
| 157 | if (array_key_exists('mappedBy', $association)) { |
||
| 158 | $mapping['mappedBy'] = $association['mappedBy']; |
||
| 159 | } |
||
| 160 | if (array_key_exists('inversedBy', $association)) { |
||
| 161 | $mapping['inversedBy'] = $association['inversedBy']; |
||
| 162 | } |
||
| 163 | $metadata->mapOneToOne($mapping); |
||
| 164 | break; |
||
| 165 | 17 | case 'manyToOne': |
|
| 166 | 17 | $mapping['type'] = EntityMetadata::MANY_TO_ONE; |
|
| 167 | 17 | if (array_key_exists('inversedBy', $association)) { |
|
| 168 | 17 | $mapping['inversedBy'] = $association['inversedBy']; |
|
| 169 | 17 | } |
|
| 170 | 17 | $metadata->mapManyToOne($mapping); |
|
| 171 | 17 | break; |
|
| 172 | 17 | View Code Duplication | case 'oneToMany': |
| 173 | 17 | $mapping['type'] = EntityMetadata::ONE_TO_MANY; |
|
| 174 | 17 | if (array_key_exists('mappedBy', $association)) { |
|
| 175 | 17 | $mapping['mappedBy'] = $association['mappedBy']; |
|
| 176 | 17 | } |
|
| 177 | 17 | if (array_key_exists('orderBy', $association)) { |
|
| 178 | $mapping['orderBy'] = $association['orderBy']; |
||
| 179 | } |
||
| 180 | 17 | if (array_key_exists('indexBy', $association)) { |
|
| 181 | $mapping['indexBy'] = $association['indexBy']; |
||
| 182 | } |
||
| 183 | 17 | $metadata->mapOneToMany($mapping); |
|
| 184 | 17 | break; |
|
| 185 | } |
||
| 186 | 17 | } |
|
| 187 | |||
| 188 | /** |
||
| 189 | * Loads a mapping file with the given name and returns a map |
||
| 190 | * from class/entity names to their corresponding file driver elements. |
||
| 191 | * |
||
| 192 | * @param string $file The mapping file to load. |
||
| 193 | * |
||
| 194 | * @return array |
||
| 195 | * @throws ParseException |
||
| 196 | */ |
||
| 197 | 25 | protected function loadMappingFile($file) |
|
| 198 | { |
||
| 199 | 25 | return Yaml::parse(file_get_contents($file)); |
|
| 200 | } |
||
| 201 | |||
| 202 | 25 | private function fieldToArray($field, $source) |
|
| 203 | { |
||
| 204 | $mapping = [ |
||
| 205 | 25 | 'field' => $field, |
|
| 206 | 25 | 'type' => 'string', |
|
| 207 | 25 | 'nullable' => true, |
|
| 208 | 25 | ]; |
|
| 209 | |||
| 210 | 25 | if (array_key_exists('type', $source)) { |
|
| 211 | 25 | $mapping['type'] = $source['type']; |
|
| 212 | 25 | } |
|
| 213 | |||
| 214 | 25 | if (array_key_exists('nullable', $source)) { |
|
| 215 | 10 | $mapping['nullable'] = $source['nullable']; |
|
| 216 | 10 | } |
|
| 217 | |||
| 218 | 25 | if (array_key_exists('api_field', $source)) { |
|
| 219 | 23 | $mapping['api_field'] = $source['api_field']; |
|
| 220 | 23 | } |
|
| 221 | |||
| 222 | 25 | return $mapping; |
|
| 223 | } |
||
| 224 | } |
||
| 225 | |||
| 226 |
If you access a property on an interface, you most likely code against a concrete implementation of the interface.
Available Fixes
Adding an additional type check:
Changing the type hint: