| 1 |  |  | <?php | 
            
                                                                                                            
                            
            
                                    
            
            
                | 2 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 3 |  |  | declare(strict_types=1); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 4 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 5 |  |  | namespace Cycle\ORM\Relation; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 6 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 7 |  |  | use Cycle\ORM\Heap\Node; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 8 |  |  | use Cycle\ORM\Heap\State; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 9 |  |  | use Cycle\ORM\ORMInterface; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 10 |  |  | use Cycle\ORM\Reference\ReferenceInterface; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 11 |  |  | use Cycle\ORM\Relation\Traits\ToOneTrait; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 12 |  |  | use Cycle\ORM\Service\EntityProviderInterface; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 13 |  |  | use Cycle\ORM\Transaction\Pool; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 14 |  |  | use Cycle\ORM\Transaction\Tuple; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 15 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 16 |  |  | /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 17 |  |  |  * Variation of belongs-to relation which provides the ability to be self linked. Relation can be used | 
            
                                                                                                            
                            
            
                                    
            
            
                | 18 |  |  |  * to create cyclic references. Relation does not trigger store operation of referenced object! | 
            
                                                                                                            
                            
            
                                    
            
            
                | 19 |  |  |  * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 20 |  |  |  * @internal | 
            
                                                                                                            
                            
            
                                    
            
            
                | 21 |  |  |  */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 22 |  |  | class RefersTo extends AbstractRelation implements DependencyInterface | 
            
                                                                                                            
                            
            
                                    
            
            
                | 23 |  |  | { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 24 |  |  |     use ToOneTrait; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 25 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 26 | 870 |  |     public function __construct(ORMInterface $orm, string $role, string $name, string $target, array $schema) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 27 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 28 | 870 |  |         $this->entityProvider = $orm->getService(EntityProviderInterface::class); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 29 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 30 | 870 |  |         parent::__construct($orm, $role, $name, $target, $schema); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 31 |  |  |     } | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 32 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 33 | 406 |  |     public function prepare(Pool $pool, Tuple $tuple, mixed $related, bool $load = true): void | 
            
                                                                        
                            
            
                                    
            
            
                | 34 |  |  |     { | 
            
                                                                        
                            
            
                                    
            
            
                | 35 | 406 |  |         $state = $tuple->state; | 
            
                                                                        
                            
            
                                    
            
            
                | 36 | 406 |  |         $relName = $this->getName(); | 
            
                                                                        
                            
            
                                    
            
            
                | 37 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 38 | 406 |  |         if (SpecialValue::isNotSet($related)) { | 
            
                                                                        
                            
            
                                    
            
            
                | 39 | 8 |  |             if (!$state->hasRelation($relName)) { | 
            
                                                                        
                            
            
                                    
            
            
                | 40 | 8 |  |                 $state->setRelationStatus($relName, RelationInterface::STATUS_DEFERRED); | 
            
                                                                        
                            
            
                                    
            
            
                | 41 |  |  |                 return; | 
            
                                                                        
                            
            
                                    
            
            
                | 42 | 406 |  |             } | 
            
                                                                        
                            
            
                                    
            
            
                | 43 | 142 |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 44 |  |  |             $related = $state->getRelation($relName); | 
            
                                                                        
                            
            
                                    
            
            
                | 45 | 376 |  |         } | 
            
                                                                        
                            
            
                                    
            
            
                | 46 | 376 |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 47 | 96 |  |         $node = $tuple->node; | 
            
                                                                        
                            
            
                                    
            
            
                | 48 | 96 |  |         $tuple->state->setRelation($relName, $related); | 
            
                                                                        
                            
            
                                    
            
            
                | 49 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 50 |  |  |         if ($related instanceof ReferenceInterface && $this->resolve($related, false) !== null) { | 
            
                                                                        
                            
            
                                    
            
            
                | 51 | 352 |  |             $related = $related->getValue(); | 
            
                                                                        
                            
            
                                    
            
            
                | 52 | 352 |  |             $tuple->state->setRelation($relName, $related); | 
            
                                                                        
                            
            
                                    
            
            
                | 53 | 352 |  |         } | 
            
                                                                        
                            
            
                                    
            
            
                | 54 | 320 |  |         if ($this->checkNullValue($node, $tuple->state, $related)) { | 
            
                                                                        
                            
            
                                    
            
            
                | 55 |  |  |             return; | 
            
                                                                        
                            
            
                                    
            
            
                | 56 |  |  |         } | 
            
                                                                        
                            
            
                                    
            
            
                | 57 |  |  |         $this->registerWaitingFields($tuple->state, false); | 
            
                                                                        
                            
            
                                    
            
            
                | 58 | 424 |  |         if ($related instanceof ReferenceInterface) { | 
            
                                                                        
                            
            
                                    
            
            
                | 59 |  |  |             $tuple->state->setRelationStatus($relName, RelationInterface::STATUS_DEFERRED); | 
            
                                                                        
                            
            
                                    
            
            
                | 60 | 424 |  |             return; | 
            
                                                                        
                            
            
                                    
            
            
                | 61 | 424 |  |         } | 
            
                                                                        
                            
            
                                    
            
            
                | 62 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 63 | 424 |  |         $tuple->state->setRelationStatus($relName, RelationInterface::STATUS_PROCESS); | 
            
                                                                        
                            
            
                                    
            
            
                | 64 | 8 |  |         $rTuple = $pool->offsetGet($related); | 
            
                                                                        
                            
            
                                    
            
            
                | 65 | 8 |  |         if ($rTuple === null && $this->isCascade()) { | 
            
                                                                        
                            
            
                                    
            
            
                | 66 |  |  |             $pool->attachStore($related, false, null, null, false); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 67 | 424 |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 68 | 88 |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 69 | 88 |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 70 | 88 |  |     public function queue(Pool $pool, Tuple $tuple): void | 
            
                                                                                                            
                            
            
                                    
            
            
                | 71 | 88 |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 72 |  |  |         $state = $tuple->state; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 73 | 88 |  |         $relName = $this->getName(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 74 | 88 |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 75 | 88 |  |         if (!$state->hasRelation($relName)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 76 |  |  |             $state->setRelationStatus($relName, RelationInterface::STATUS_RESOLVED); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 77 |  |  |             return; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 78 | 408 |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 79 | 56 |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 80 |  |  |         $node = $tuple->node; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 81 | 352 |  |         $related = $tuple->state->getRelation($relName); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 82 | 352 |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 83 |  |  |         if ($related instanceof ReferenceInterface && ($related->hasValue() || $this->resolve($related, false) !== null)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 84 |  |  |             $related = $related->getValue(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 85 |  |  |             $tuple->state->setRelation($relName, $related); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 86 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 87 |  |  |         if ($related instanceof ReferenceInterface) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 88 |  |  |             $scope = $related->getScope(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 89 |  |  |             if (\array_intersect($this->outerKeys, \array_keys($scope))) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 90 |  |  |                 foreach ($this->outerKeys as $i => $outerKey) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 91 |  |  |                     $tuple->state->register($this->innerKeys[$i], $scope[$outerKey]); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 92 |  |  |                 } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 93 |  |  |                 $node->setRelation($relName, $related); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 94 |  |  |                 $tuple->state->setRelationStatus($relName, RelationInterface::STATUS_RESOLVED); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 95 | 352 |  |                 return; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 96 | 208 |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 97 | 208 |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 98 | 352 |  |         if ($this->checkNullValue($tuple->node, $tuple->state, $related)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 99 |  |  |             return; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 100 | 328 |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 101 | 328 |  |         $rTuple = $pool->offsetGet($related); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 102 | 328 |  |         if ($rTuple === null) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 103 | 328 |  |             if ($this->isCascade()) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 104 |  |  |                 // todo: cascade true? | 
            
                                                                                                            
                            
            
                                    
            
            
                | 105 |  |  |                 $rTuple = $pool->attachStore($related, false, null, null, false); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 106 | 192 |  |             } elseif ( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 107 | 192 |  |                 $tuple->state->getRelationStatus($relName) !== RelationInterface::STATUS_DEFERRED | 
            
                                                                                                            
                            
            
                                    
            
            
                | 108 |  |  |                 || $tuple->status !== Tuple::STATUS_PROPOSED | 
            
                                                                                                            
                            
            
                                    
            
            
                | 109 |  |  |             ) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 110 |  |  |                 $tuple->state->setRelationStatus($relName, RelationInterface::STATUS_DEFERRED); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 111 | 328 |  |                 return; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 112 |  |  |             } else { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 113 | 328 |  |                 $tuple->state->setRelationStatus($relName, RelationInterface::STATUS_RESOLVED); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 114 | 328 |  |                 return; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 115 | 328 |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 116 | 328 |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 117 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 118 |  |  |         if ($rTuple->status === Tuple::STATUS_PROCESSED | 
            
                                                                                                            
                            
            
                                    
            
            
                | 119 |  |  |             || ($rTuple->status > Tuple::STATUS_PREPARING | 
            
                                                                                                            
                            
            
                                    
            
            
                | 120 |  |  |                 && $rTuple->state->getStatus() !== node::NEW | 
            
                                                                                                            
                            
            
                                    
            
            
                | 121 | 454 |  |                 && \array_intersect($this->outerKeys, $rTuple->state->getWaitingFields()) === []) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 122 |  |  |         ) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 123 | 454 |  |             $this->pullValues($tuple->state, $rTuple->state); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 124 | 376 |  |             $node->setRelation($relName, $related); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 125 |  |  |             $tuple->state->setRelationStatus($relName, RelationInterface::STATUS_RESOLVED); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 126 | 198 |  |             return; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 127 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 128 | 198 |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 129 |  |  |         if ($tuple->status !== Tuple::STATUS_PREPARING) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 130 | 96 |  |             $tuple->state->setRelationStatus($relName, RelationInterface::STATUS_DEFERRED); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 131 | 96 |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 132 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 133 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 134 |  |  |     private function pullValues(State $state, State $rState): void | 
            
                                                                                                            
                            
            
                                    
            
            
                | 135 | 198 |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 136 | 198 |  |         $changes = $rState->getTransactionData(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 137 | 198 |  |         foreach ($this->outerKeys as $i => $outerKey) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 138 |  |  |             if (isset($changes[$outerKey])) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 139 |  |  |                 $state->register($this->innerKeys[$i], $changes[$outerKey]); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 140 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 141 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 142 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 143 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 144 |  |  |     private function checkNullValue(Node $node, State $state, mixed $value): bool | 
            
                                                                                                            
                            
            
                                    
            
            
                | 145 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 146 |  |  |         if ($value !== null) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 147 |  |  |             return false; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 148 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 149 |  |  |         $original = $node->getRelation($this->getName()); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 150 |  |  |         // Original is not null | 
            
                                                                                                            
                            
            
                                    
            
            
                | 151 |  |  |         if ($original !== null) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 152 |  |  |             // Reset keys | 
            
                                                                                                            
                            
            
                                    
            
            
                | 153 |  |  |             foreach ($this->innerKeys as $innerKey) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 154 |  |  |                 $state->register($innerKey, null); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 155 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 156 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 157 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 158 |  |  |         $node->setRelation($this->getName(), null); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 159 |  |  |         $state->setRelationStatus($this->getName(), RelationInterface::STATUS_RESOLVED); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 160 |  |  |         return true; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 161 |  |  |     } | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 162 |  |  | } | 
            
                                                        
            
                                    
            
            
                | 163 |  |  |  |