Stratadox /
HydrationMapper
| 1 | <?php |
||
| 2 | declare(strict_types=1); |
||
| 3 | |||
| 4 | namespace Stratadox\Hydration\Mapper\Instruction\Relation; |
||
| 5 | |||
| 6 | use Stratadox\Hydration\Mapper\Mapper; |
||
| 7 | use Stratadox\Hydration\Mapping\Property\Check; |
||
| 8 | use Stratadox\HydrationMapper\DefinesRelationships; |
||
| 9 | use Stratadox\HydrationMapper\FindsKeys; |
||
| 10 | use Stratadox\HydrationMapper\InstructsHowToMap; |
||
| 11 | use Stratadox\HydrationMapper\InvalidMapperConfiguration; |
||
| 12 | use Stratadox\HydrationMapper\RepresentsChoice; |
||
| 13 | use Stratadox\HydrationMapping\MapsProperty; |
||
| 14 | use Stratadox\Hydrator\Hydrates; |
||
| 15 | use Stratadox\Hydrator\OneOfTheseHydrators; |
||
| 16 | use Stratadox\Proxy\ProducesProxyLoaders; |
||
| 17 | use function assert; |
||
| 18 | use Stratadox\Specification\Contract\Satisfiable; |
||
| 19 | |||
| 20 | /** |
||
| 21 | * Defines a relationship with another class. |
||
| 22 | * |
||
| 23 | * @package Stratadox\Hydrate |
||
| 24 | * @author Stratadox |
||
| 25 | */ |
||
| 26 | abstract class Relationship implements DefinesRelationships |
||
| 27 | { |
||
| 28 | /** @var string */ |
||
| 29 | protected $class; |
||
| 30 | |||
| 31 | /** @var FindsKeys|null */ |
||
| 32 | protected $key; |
||
| 33 | |||
| 34 | /** @var string|null */ |
||
| 35 | protected $container; |
||
| 36 | |||
| 37 | /** @var ProducesProxyLoaders|null */ |
||
| 38 | protected $loader; |
||
| 39 | |||
| 40 | /** @var bool */ |
||
| 41 | protected $shouldNest = false; |
||
| 42 | |||
| 43 | /** @var (InstructsHowToMap|null)[] */ |
||
| 44 | protected $properties = []; |
||
| 45 | |||
| 46 | /** @var string|null */ |
||
| 47 | protected $decisionKey; |
||
| 48 | |||
| 49 | /** @var RepresentsChoice[] */ |
||
| 50 | protected $choices = []; |
||
| 51 | |||
| 52 | /** @var Satisfiable|null */ |
||
| 53 | protected $constraint; |
||
| 54 | |||
| 55 | private function __construct(string $class, FindsKeys $key = null) |
||
| 56 | { |
||
| 57 | $this->class = $class; |
||
| 58 | $this->key = $key; |
||
| 59 | } |
||
| 60 | |||
| 61 | /** |
||
| 62 | * Defines a new relationship with another class. |
||
| 63 | * |
||
| 64 | * @param string $class The fully qualified class name. |
||
| 65 | * @param FindsKeys|null $key The input array offset (optional) |
||
| 66 | * @return DefinesRelationships The relationship definition. |
||
| 67 | */ |
||
| 68 | public static function ofThe( |
||
| 69 | string $class, |
||
| 70 | FindsKeys $key = null |
||
| 71 | ): DefinesRelationships { |
||
| 72 | return new static($class, $key); |
||
| 73 | } |
||
| 74 | |||
| 75 | /** @inheritdoc */ |
||
| 76 | public function containedInA(string $container): DefinesRelationships |
||
| 77 | { |
||
| 78 | $inst = clone $this; |
||
| 79 | $inst->container = $container; |
||
| 80 | return $inst; |
||
| 81 | } |
||
| 82 | |||
| 83 | /** @inheritdoc */ |
||
| 84 | public function loadedBy(ProducesProxyLoaders $loader): DefinesRelationships |
||
| 85 | { |
||
| 86 | $inst = clone $this; |
||
| 87 | $inst->loader = $loader; |
||
| 88 | return $inst; |
||
| 89 | } |
||
| 90 | |||
| 91 | /** @inheritdoc */ |
||
| 92 | public function nested(): DefinesRelationships |
||
| 93 | { |
||
| 94 | $inst = clone $this; |
||
| 95 | $inst->shouldNest = true; |
||
| 96 | return $inst; |
||
| 97 | } |
||
| 98 | |||
| 99 | /** @inheritdoc */ |
||
| 100 | public function with( |
||
| 101 | string $property, |
||
| 102 | InstructsHowToMap $instruction = null |
||
| 103 | ): DefinesRelationships { |
||
| 104 | $inst = clone $this; |
||
| 105 | $inst->properties += [$property => $instruction]; |
||
| 106 | return $inst; |
||
| 107 | } |
||
| 108 | |||
| 109 | /** @inheritdoc */ |
||
| 110 | public function selectBy( |
||
| 111 | string $decisionKey, |
||
| 112 | array $choices |
||
| 113 | ): DefinesRelationships { |
||
| 114 | $inst = clone $this; |
||
| 115 | $inst->decisionKey = $decisionKey; |
||
| 116 | $inst->choices = $choices; |
||
| 117 | return $inst; |
||
| 118 | } |
||
| 119 | |||
| 120 | public function that(Satisfiable $constraint): InstructsHowToMap |
||
| 121 | { |
||
| 122 | $inst = clone $this; |
||
| 123 | $inst->constraint = $constraint; |
||
| 124 | return $inst; |
||
| 125 | } |
||
| 126 | |||
| 127 | /** |
||
| 128 | * Returns the key if one was provided, defaulting to the property name. |
||
| 129 | * |
||
| 130 | * @param string $property The property name to use as fallback. |
||
| 131 | * @return string The key to use as offset for the input data. |
||
| 132 | */ |
||
| 133 | protected function keyOr(string $property): string |
||
| 134 | { |
||
| 135 | return $this->key ? $this->key->find() : $property; |
||
| 136 | } |
||
| 137 | |||
| 138 | /** |
||
| 139 | * Produces a mapped hydrator according to the relationship configuration. |
||
| 140 | * |
||
| 141 | * @return Hydrates The hydrator for the relationship mapping. |
||
| 142 | * @throws InvalidMapperConfiguration |
||
| 143 | */ |
||
| 144 | protected function hydrator(): Hydrates |
||
| 145 | { |
||
| 146 | if (isset($this->decisionKey)) { |
||
| 147 | return $this->choiceHydrator(); |
||
| 148 | } |
||
| 149 | $mapped = Mapper::forThe($this->class); |
||
| 150 | foreach ($this->properties as $property => $instruction) { |
||
| 151 | $mapped = $mapped->property($property, $instruction); |
||
| 152 | } |
||
| 153 | return $mapped->finish(); |
||
| 154 | } |
||
| 155 | |||
| 156 | protected function addConstraintTo(MapsProperty $mapping): MapsProperty |
||
| 157 | { |
||
| 158 | if (isset($this->constraint)) { |
||
| 159 | $mapping = Check::that($this->constraint, $mapping); |
||
| 160 | } |
||
| 161 | return $mapping; |
||
| 162 | } |
||
| 163 | |||
| 164 | /** |
||
| 165 | * Produces a multiple-choice hydrator. |
||
| 166 | * |
||
| 167 | * @return Hydrates The adapter that selects the hydrator. |
||
| 168 | * @throws InvalidMapperConfiguration |
||
| 169 | */ |
||
| 170 | private function choiceHydrator(): Hydrates |
||
| 171 | { |
||
| 172 | assert(isset($this->decisionKey)); |
||
| 173 | return OneOfTheseHydrators::decideBasedOnThe( |
||
| 174 | $this->decisionKey, |
||
|
0 ignored issues
–
show
Bug
introduced
by
Loading history...
|
|||
| 175 | array_map(function (RepresentsChoice $choice): Hydrates { |
||
| 176 | return $choice->finish(); |
||
| 177 | }, $this->choices) |
||
| 178 | ); |
||
| 179 | } |
||
| 180 | } |
||
| 181 |