-
Notifications
You must be signed in to change notification settings - Fork 111
Expand file tree
/
Copy pathAttributeDriver.php
More file actions
109 lines (91 loc) · 3.6 KB
/
AttributeDriver.php
File metadata and controls
109 lines (91 loc) · 3.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
<?php
declare(strict_types=1);
/*
* This file is part of the BazingaGeocoderBundle package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
namespace Bazinga\GeocoderBundle\Mapping\Driver;
use Bazinga\GeocoderBundle\Mapping\Attributes;
use Bazinga\GeocoderBundle\Mapping\ClassMetadata;
use Bazinga\GeocoderBundle\Mapping\Exception\MappingException;
use Doctrine\Common\Util\ClassUtils;
use Doctrine\ORM\Proxy\DefaultProxyClassNameResolver;
/**
* @author Pierre du Plessis <pdples@gmail.com>
*/
final class AttributeDriver implements DriverInterface
{
private const PROPERTY_MATRIX = [
Attributes\Latitude::class => 'latitudeProperty',
Attributes\Longitude::class => 'longitudeProperty',
Attributes\Address::class => 'addressProperty',
Attributes\North::class => 'northProperty',
Attributes\South::class => 'southProperty',
Attributes\East::class => 'eastProperty',
Attributes\West::class => 'westProperty',
Attributes\StreetNumber::class => 'streetNumberProperty',
Attributes\StreetName::class => 'streetNameProperty',
Attributes\Locality::class => 'localityProperty',
Attributes\PostalCode::class => 'postalCodeProperty',
Attributes\SubLocality::class => 'subLocalityProperty',
Attributes\Country::class => 'countryProperty',
];
public function isGeocodeable(object $object): bool
{
$reflection = self::getReflection($object);
return [] !== $reflection->getAttributes(Attributes\Geocodeable::class);
}
/**
* @throws MappingException|\ReflectionException
*/
public function loadMetadataFromObject(object $object): ClassMetadata
{
$reflection = self::getReflection($object);
$attributes = $reflection->getAttributes(Attributes\Geocodeable::class);
if ([] === $attributes) {
throw new MappingException(sprintf('The class "%s" is not geocodeable', $object::class));
}
$args = ['provider' => $attributes[0]->newInstance()->provider];
foreach ($reflection->getProperties() as $property) {
foreach ($property->getAttributes() as $attribute) {
if (isset(self::PROPERTY_MATRIX[$attribute->getName()])) {
$args[self::PROPERTY_MATRIX[$attribute->getName()]] = $property;
}
}
}
foreach ($reflection->getMethods(\ReflectionMethod::IS_PUBLIC) as $method) {
if ([] !== $method->getAttributes(Attributes\Address::class)) {
if (0 !== $method->getNumberOfRequiredParameters()) {
throw new MappingException('You can not use a method requiring parameters with #[Address] attribute!');
}
$args['addressGetter'] = $method;
}
}
return new ClassMetadata(...$args);
}
/**
* @template T of object
*
* @param T $object
*
* @return \ReflectionClass<T>
*
* @throws \ReflectionException
*/
private static function getReflection(object $object): \ReflectionClass
{
if (class_exists(ClassUtils::class)) {
/** @var \ReflectionClass<T> */
return ClassUtils::newReflectionObject($object);
}
if (PHP_VERSION_ID < 80400) {
/** @var \ReflectionClass<T> */
return new \ReflectionClass(DefaultProxyClassNameResolver::getClass($object));
}
/** @var \ReflectionClass<T> */
return new \ReflectionClass($object);
}
}