cerbero90 /
dto
| 1 | <?php |
||||||
| 2 | |||||||
| 3 | namespace Cerbero\Dto\Traits; |
||||||
| 4 | |||||||
| 5 | use Cerbero\Dto\DtoPropertiesMapper; |
||||||
| 6 | use Cerbero\Dto\DtoProperty; |
||||||
| 7 | use Cerbero\Dto\Exceptions\UnknownDtoPropertyException; |
||||||
| 8 | |||||||
| 9 | /** |
||||||
| 10 | * Trait to interact with properties. |
||||||
| 11 | * |
||||||
| 12 | */ |
||||||
| 13 | trait HasProperties |
||||||
| 14 | { |
||||||
| 15 | /** |
||||||
| 16 | * The properties map. |
||||||
| 17 | * |
||||||
| 18 | * @var array |
||||||
| 19 | */ |
||||||
| 20 | protected $propertiesMap; |
||||||
| 21 | |||||||
| 22 | /** |
||||||
| 23 | * Retrieve the DTO properties map |
||||||
| 24 | * |
||||||
| 25 | * @return array |
||||||
| 26 | */ |
||||||
| 27 | 32 | public function getPropertiesMap(): array |
|||||
| 28 | { |
||||||
| 29 | 32 | return $this->propertiesMap; |
|||||
| 30 | } |
||||||
| 31 | |||||||
| 32 | /** |
||||||
| 33 | * Retrieve the DTO property names |
||||||
| 34 | * |
||||||
| 35 | * @return array |
||||||
| 36 | */ |
||||||
| 37 | 6 | public function getPropertyNames(): array |
|||||
| 38 | { |
||||||
| 39 | 6 | return array_keys($this->getPropertiesMap()); |
|||||
| 40 | } |
||||||
| 41 | |||||||
| 42 | /** |
||||||
| 43 | * Retrieve the DTO properties |
||||||
| 44 | * |
||||||
| 45 | * @return DtoProperty[] |
||||||
| 46 | */ |
||||||
| 47 | 2 | public function getProperties(): array |
|||||
| 48 | { |
||||||
| 49 | 2 | return array_values($this->getPropertiesMap()); |
|||||
| 50 | } |
||||||
| 51 | |||||||
| 52 | /** |
||||||
| 53 | * Determine whether the given property is set (even if its value is NULL) |
||||||
| 54 | * |
||||||
| 55 | * @param string $property |
||||||
| 56 | * @return bool |
||||||
| 57 | */ |
||||||
| 58 | 23 | public function hasProperty(string $property): bool |
|||||
| 59 | { |
||||||
| 60 | try { |
||||||
| 61 | 23 | return !!$this->getProperty($property); |
|||||
| 62 | 15 | } catch (UnknownDtoPropertyException $e) { |
|||||
| 63 | 15 | return false; |
|||||
| 64 | } |
||||||
| 65 | } |
||||||
| 66 | |||||||
| 67 | /** |
||||||
| 68 | * Retrieve the given DTO property (support dot notation) |
||||||
| 69 | * |
||||||
| 70 | * @param string $property |
||||||
| 71 | * @return DtoProperty |
||||||
| 72 | * @throws UnknownDtoPropertyException |
||||||
| 73 | */ |
||||||
| 74 | 43 | public function getProperty(string $property): DtoProperty |
|||||
| 75 | { |
||||||
| 76 | 43 | if (isset($this->propertiesMap[$property])) { |
|||||
| 77 | 28 | return $this->propertiesMap[$property]; |
|||||
| 78 | } |
||||||
| 79 | |||||||
| 80 | 26 | if (strpos($property, '.') === false) { |
|||||
| 81 | 24 | throw new UnknownDtoPropertyException(static::class, $property); |
|||||
| 82 | } |
||||||
| 83 | |||||||
| 84 | 8 | [$property, $nestedProperty] = explode('.', $property, 2); |
|||||
| 85 | 8 | $presumedDto = $this->get($property); |
|||||
|
0 ignored issues
–
show
Bug
introduced
by
Loading history...
|
|||||||
| 86 | |||||||
| 87 | 7 | if ($presumedDto instanceof self) { |
|||||
| 88 | 6 | return $presumedDto->getProperty($nestedProperty); |
|||||
| 89 | } |
||||||
| 90 | |||||||
| 91 | 1 | throw new UnknownDtoPropertyException(static::class, $nestedProperty); |
|||||
| 92 | } |
||||||
| 93 | |||||||
| 94 | /** |
||||||
| 95 | * Retrieve the given DTO property or map it if not mapped yet |
||||||
| 96 | * |
||||||
| 97 | * @param string $property |
||||||
| 98 | * @param mixed $value |
||||||
| 99 | * @return void |
||||||
| 100 | */ |
||||||
| 101 | 14 | protected function setPropertyValueOrMap(string $property, $value): void |
|||||
| 102 | { |
||||||
| 103 | 14 | if ($this->hasProperty($property)) { |
|||||
| 104 | 7 | $this->getProperty($property)->setValue($value, $this->getFlags()); |
|||||
|
0 ignored issues
–
show
It seems like
getFlags() must be provided by classes using this trait. How about adding it as abstract method to this trait?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||||
| 105 | 7 | return; |
|||||
| 106 | } |
||||||
| 107 | |||||||
| 108 | 7 | $data = $this->toArray(); |
|||||
|
0 ignored issues
–
show
It seems like
toArray() must be provided by classes using this trait. How about adding it as abstract method to this trait?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||||
| 109 | |||||||
| 110 | 7 | if (strpos($property, '.') === false) { |
|||||
| 111 | 5 | $data[$property] = $value; |
|||||
| 112 | } else { |
||||||
| 113 | 2 | [$property, $nestedProperty] = explode('.', $property, 2); |
|||||
| 114 | 2 | $data[$property] = $this->resolveNestedValue($nestedProperty, $value); |
|||||
| 115 | } |
||||||
| 116 | |||||||
| 117 | 7 | $this->propertiesMap = $this->mapData($data); |
|||||
| 118 | 6 | } |
|||||
| 119 | |||||||
| 120 | /** |
||||||
| 121 | * Retrieve the DTO mapped properties for the given data |
||||||
| 122 | * |
||||||
| 123 | * @param array $data |
||||||
| 124 | * @return array |
||||||
| 125 | * @throws \Cerbero\Dto\Exceptions\DtoNotFoundException |
||||||
| 126 | * @throws \Cerbero\Dto\Exceptions\MissingValueException |
||||||
| 127 | * @throws \Cerbero\Dto\Exceptions\UnexpectedValueException |
||||||
| 128 | * @throws UnknownDtoPropertyException |
||||||
| 129 | */ |
||||||
| 130 | 81 | protected function mapData(array $data): array |
|||||
| 131 | { |
||||||
| 132 | 81 | $mergedData = array_merge(static::getDefaultValues(), $data); |
|||||
| 133 | |||||||
| 134 | 81 | return DtoPropertiesMapper::for(static::class)->map($mergedData, $this->getFlags()); |
|||||
| 135 | } |
||||||
| 136 | |||||||
| 137 | /** |
||||||
| 138 | * Retrieve a nested value following the dot notation |
||||||
| 139 | * |
||||||
| 140 | * @param string $property |
||||||
| 141 | * @param mixed $value |
||||||
| 142 | * @return array |
||||||
| 143 | */ |
||||||
| 144 | 2 | protected function resolveNestedValue(string $property, $value): array |
|||||
| 145 | { |
||||||
| 146 | 2 | if (strpos($property, '.') === false) { |
|||||
| 147 | 2 | return [$property => $value]; |
|||||
| 148 | } |
||||||
| 149 | |||||||
| 150 | 1 | [$property, $nestedProperty] = explode('.', $property, 2); |
|||||
| 151 | |||||||
| 152 | 1 | return [$property => $this->resolveNestedValue($nestedProperty, $value)]; |
|||||
| 153 | } |
||||||
| 154 | } |
||||||
| 155 |