/** * @param Record $other * * @return string */ protected function failureDescription($other) { $otherOid = $other && $other instanceof Record ? $other->getOid() : 'NULL'; $relation = $this->record->getTableRelation($this->relationName); $otherTableName = $relation->isOwningSide($this->relationName) ? $relation->getOwningTable() : $relation->getReferencedTable(); $msg = $this->toString() . " to {$otherTableName}[{$otherOid}]"; if ($otherOid === $this->record->getOid()) { $msg .= ", both have the same oid"; } return $msg; }
/** * Gets id of old referenced record * * @param Record $owningRecord * @return bool|string */ private function getOldReferencedId(Record $owningRecord) { $oid = $owningRecord->getOid(); $oldRefId = $owningRecord->get($this->relation->getOwningField()); if (!$oldRefId && $this->hasFieldMapping($oid)) { $oldRefId = Record::NEW_RECORD_ID_MARK . $this->getFieldMapping($oid); } return $oldRefId; }
/** * @param Record $owningRecord * @param Relation $relation * @param string $refObjectId */ private function assertReferencedRelatedReferences(Record $owningRecord, Relation $relation, $refObjectId) { $oldIdentifier = Record::NEW_RECORD_ID_MARK . $owningRecord->getOid(); $newIdentifier = $owningRecord->getInternalId(); $rm = $owningRecord->getRecordManager(); /** @var ReferenceMap $referenceMap */ $referenceMap = self::readAttribute($relation, 'map'); $referenceMapping = $referenceMap->getMapping(); $refTable = $relation->getJoinTable($rm, $relation->getReferencedAlias()); $refTableRepository = $refTable->getRepository(); $referencedRecord = $refTableRepository->getByOid($refObjectId); $refId = $referencedRecord->getInternalId(); // assert that owning record id is mapped for referenced record $this->assertArrayHasKey($refId, $referenceMapping); if ($relation->isOneToMany()) { $this->assertNotContains($oldIdentifier, $referenceMapping[$refId]); $this->assertContains($newIdentifier, $referenceMapping[$refId]); } else { $this->assertEquals($newIdentifier, $referenceMapping[$refId]); } // assert record collection if ($relation->isOneToMany()) { $recordCollection = $referenceMap->getRelatedCollection($referencedRecord->getOid()); $this->assertNotNull($recordCollection); $this->assertTrue($recordCollection->has($owningRecord), "Expected '{$owningRecord}' is referenced in relation '" . $relation->getReferencedAlias() . "'"); } }
/** * @param Record $record * @param array $visited * @return array */ private function getLoadedReferences(Record $record, array $visited = array()) { $oid = $record->getOid(); if (in_array($oid, $visited)) { return false; } $visited[] = $oid; $actualReferences = array(); $table = $record->getTable(); $relations = $table->getRelations(); foreach ($relations as $relationName => $relation) { if ($relation->hasReferenceLoadedFor($record, $relationName)) { $related = $relation->getReferenceFor($record, $relationName); if ($related instanceof RecordCollection) { foreach ($related as $relatedRecord) { $loadedReferences = $this->getLoadedReferences($relatedRecord, $visited); if ($loadedReferences !== false) { $actualReferences[$relationName] = $loadedReferences; } } } else { if ($related instanceof Record) { $loadedReferences = $this->getLoadedReferences($related, $visited); if ($loadedReferences !== false) { $actualReferences[$relationName] = $loadedReferences; } } } } } return $actualReferences; }
/** * Updates identity map on record insert/update or removes identity map entry on record delete * Refreshes record identity in repository * * @param Record $record * @param string $oldInternalIdentifier */ public function refreshIdentity(Record $record, $oldInternalIdentifier = null) { $oid = $record->getOid(); if (!$this->has($oid)) { return; } $id = $record->getIdentifierAsString(); if ($record->exists()) { if ($oldInternalIdentifier) { unset($this->identityMap[$oldInternalIdentifier]); } $this->identityMap[$id] = $record->getOid(); } else { unset($this->identityMap[$id]); } }
/** * @param Record $record */ private function markRecordForRestrictOnCommitWhenNotDeleted(Record $record) { $oid = $record->getOid(); // record will have to be deleted before record with restricted relation $this->recordIdentityMap[$oid] = $record; $this->restrictNotDeletedOnCommit[$oid] = $record; }
/** * @param Record $record * @param string $relationName * @return bool|RecordCollection|Record|Record[]|null */ private function getRecordRelatedByReferences(Record $record, $relationName) { // is reference expected as collection if ($this->isOwningSide($relationName) && $this->isOneToMany()) { $reference = $this->map->getRelatedCollection($record->getOid()); if (!$reference) { $reference = $this->map->createRelatedCollection($record); } return $reference; } // is reference expected as record $refId = $this->getRecordReferencedIdentifiers($record, $relationName); // is a NULL-reference if (null === $refId) { return null; } $rm = $record->getTable()->getRecordManager(); $refTable = $this->getJoinTable($rm, $relationName); if (is_string($refId) && $refTable->isInRepository($refId)) { return $refTable->getFromRepository($refId); } return false; }
/** * @param Record $record * @param string $relationName * @param string $message */ private function assertRecordIsNotReferencedByRelation(Record $record, $relationName, $message = '') { $internalId = $record->getInternalId(); $relation = $record->getTableRelation($relationName); $isReferencedSide = $relation->isReferencedSide($relationName); /** @var ReferenceMap $referenceMap */ $referenceMap = self::readAttribute($relation, 'map'); $isOneToMany = $relation->isOneToMany(); /** @var RecordCollection[] $relatedCollections */ $relatedCollections = $isOneToMany ? self::readAttribute($referenceMap, 'relatedCollections') : null; $references = $referenceMap->getMapping(); $referencedMessage = $message . " expected not be referenced (relation '{$relationName}')"; $relatedCollectionMessage = $message . " expected not to be in a related collection (relation '{$relationName}')"; $oid = $record->getOid(); if ($isReferencedSide) { foreach ($references as $owningIds) { if ($isOneToMany) { $this->assertNotContains($internalId, $owningIds, $referencedMessage); } else { $this->assertNotEquals($internalId, $owningIds, $referencedMessage); } } if ($isOneToMany) { foreach ($relatedCollections as $relatedCollection) { $this->assertFalse($relatedCollection->has($record), $relatedCollectionMessage); } } $this->assertFalse($referenceMap->hasFieldMapping($oid)); } else { $this->assertArrayNotHasKey($internalId, $references, $referencedMessage); if ($isOneToMany) { $this->assertArrayNotHasKey($oid, $relatedCollections, $relatedCollectionMessage); } } }
/** * @param Record $record */ protected function unsetReferenceForOwningRecordOnUnloadedReference(Record $record) { $owningId = $record->getInternalId(); foreach ($this->references as $refId => $owningIds) { if ($this->removeOwningReference($refId, $owningId)) { break; } } $this->unsetFieldMapping($record->getOid()); }