mailpoet
/
vendor-prefixed
/
doctrine
/
orm
/
src
/
Mapping
/
Reflection
/
ReflectionPropertiesGetter.php
ReflectionPropertiesGetter.php
71 lines
| 1 | <?php |
| 2 | declare (strict_types=1); |
| 3 | namespace MailPoetVendor\Doctrine\ORM\Mapping\Reflection; |
| 4 | if (!defined('ABSPATH')) exit; |
| 5 | use MailPoetVendor\Doctrine\Persistence\Mapping\ReflectionService; |
| 6 | use ReflectionClass; |
| 7 | use ReflectionProperty; |
| 8 | use function array_combine; |
| 9 | use function array_filter; |
| 10 | use function array_map; |
| 11 | use function array_merge; |
| 12 | final class ReflectionPropertiesGetter |
| 13 | { |
| 14 | private $properties = []; |
| 15 | private $reflectionService; |
| 16 | public function __construct(ReflectionService $reflectionService) |
| 17 | { |
| 18 | $this->reflectionService = $reflectionService; |
| 19 | } |
| 20 | public function getProperties($className) : array |
| 21 | { |
| 22 | if (isset($this->properties[$className])) { |
| 23 | return $this->properties[$className]; |
| 24 | } |
| 25 | return $this->properties[$className] = array_merge( |
| 26 | // first merge because `array_merge` expects >= 1 params |
| 27 | ...array_merge([[]], array_map([$this, 'getClassProperties'], $this->getHierarchyClasses($className))) |
| 28 | ); |
| 29 | } |
| 30 | private function getHierarchyClasses(string $className) : array |
| 31 | { |
| 32 | $classes = []; |
| 33 | $parentClassName = $className; |
| 34 | while ($parentClassName && ($currentClass = $this->reflectionService->getClass($parentClassName))) { |
| 35 | $classes[] = $currentClass; |
| 36 | $parentClassName = null; |
| 37 | $parentClass = $currentClass->getParentClass(); |
| 38 | if ($parentClass) { |
| 39 | $parentClassName = $parentClass->name; |
| 40 | } |
| 41 | } |
| 42 | return $classes; |
| 43 | } |
| 44 | // phpcs:disable SlevomatCodingStandard.Classes.UnusedPrivateElements.UnusedMethod |
| 45 | private function getClassProperties(ReflectionClass $reflectionClass) : array |
| 46 | { |
| 47 | // phpcs:enable SlevomatCodingStandard.Classes.UnusedPrivateElements.UnusedMethod |
| 48 | $properties = $reflectionClass->getProperties(); |
| 49 | return array_filter(array_filter(array_map([$this, 'getAccessibleProperty'], array_combine(array_map([$this, 'getLogicalName'], $properties), $properties))), [$this, 'isInstanceProperty']); |
| 50 | } |
| 51 | private function isInstanceProperty(ReflectionProperty $reflectionProperty) : bool |
| 52 | { |
| 53 | return !$reflectionProperty->isStatic(); |
| 54 | } |
| 55 | private function getAccessibleProperty(ReflectionProperty $property) : ?ReflectionProperty |
| 56 | { |
| 57 | return $this->reflectionService->getAccessibleProperty($property->class, $property->name); |
| 58 | } |
| 59 | private function getLogicalName(ReflectionProperty $property) : string |
| 60 | { |
| 61 | $propertyName = $property->name; |
| 62 | if ($property->isPublic()) { |
| 63 | return $propertyName; |
| 64 | } |
| 65 | if ($property->isProtected()) { |
| 66 | return "\x00*\x00" . $propertyName; |
| 67 | } |
| 68 | return "\x00" . $property->class . "\x00" . $propertyName; |
| 69 | } |
| 70 | } |
| 71 |