/** * Returns the description of the failure * * The beginning of failure messages is "Failed asserting that" in most * cases. This method should return the second part of that sentence. * * @param Relation $relation Evaluated value or object. * @return string */ protected function failureDescription($relation) { $owningAlias = $relation->getOwningAlias(); $owningTable = $relation->getOwningTable(); $referencedAlias = $relation->getReferencedAlias(); $referencedTable = $relation->getReferencedTable(); return $this->toString() . "{$owningTable}->{$referencedAlias}: {$referencedTable} | {$referencedTable}->{$owningAlias}: {$owningTable}"; }
/** * unlink the record * * @param Record $record * @return bool */ public function unlinkRecord(Record $record) { $key = $this->search($record); if ($key === false) { return false; } $this->offsetUnset($key); if ($this->refRecord && $this->relation) { $this->relation->updateRecordReference($record, null); } return true; }
/** * Updates references between owner and referenced record collection * * @param RecordCollection|Record[] $ownerCollection * @param RecordCollection|Record[] $referencedCollection */ public function updateOwnerCollectionWithReferencedCollection(RecordCollection $ownerCollection, RecordCollection $referencedCollection) { $owningField = $this->relation->getOwningField(); $isOneToMany = $this->relation->isOneToMany(); foreach ($ownerCollection as $refRecord) { $refId = $refRecord->get($owningField); $owningId = $refRecord->getInternalId(); $this->assignReference($refId, $owningId); } foreach ($referencedCollection as $refRecord) { $id = $refRecord->getInternalId(); if (!$this->isReferenced($id) && !$this->hasNullReference($id)) { $reference = $isOneToMany ? array() : null; $this->setReference($id, $reference); } } }
/** * gets relation instance * * @param string $name * @param array $relationData * @return \Dive\Relation\Relation */ private function getRelationInstance($name, array $relationData) { if (!isset($this->relations[$name])) { $owningTable = $relationData['owningTable']; $owningAlias = $relationData['owningAlias']; $owningField = $relationData['owningField']; $referencedTable = $relationData['refTable']; $referencedAlias = $relationData['refAlias']; $referencedField = $relationData['refField']; $type = $relationData['type']; $onDelete = !empty($relationData['onDelete']) ? $relationData['onDelete'] : PlatformInterface::RESTRICT; $onUpdate = !empty($relationData['onUpdate']) ? $relationData['onUpdate'] : PlatformInterface::RESTRICT; $relation = new Relation($owningAlias, $owningTable, $owningField, $referencedAlias, $referencedTable, $referencedField, $type, $onDelete, $onUpdate); if (isset($relationData['orderBy'])) { $relation->setOrderBy($relationData['orderBy']); } $this->relations[$name] = $relation; } return $this->relations[$name]; }
/** * adds foreign key by relation instance * * @param \Dive\Relation\Relation $relation * @return Migration * @throws MigrationException */ public function addForeignKeyByRelation(Relation $relation) { if ($relation->getOwningTable() !== $this->tableName) { throw new MigrationException("\n Relation does not belong to table {$this->tableName}, it belongs to " . $relation->getOwningTable() . '!'); } $owningField = $relation->getOwningField(); $referencedTable = $relation->getReferencedTable(); $referencedField = $relation->getReferencedField(); $onDelete = $relation->getOnDelete(); $onUpdate = $relation->getOnUpdate(); return $this->addForeignKey($owningField, $referencedTable, $referencedField, $onDelete, $onUpdate); }
/** * @param RecordManager $rm * @param Relation $relation * @return string */ protected function insertRequiredLocalRelationGraph(RecordManager $rm, Relation $relation) { $randomGenerator = new FieldValuesGenerator(); $conn = $rm->getConnection(); $refTableName = $relation->getReferencedTable(); $refTable = $rm->getTable($refTableName); $refFields = $refTable->getFields(); $data = array(); // recursion: walk through all local relations that are required and handle this by calling this method with // next relation $owningRelations = $refTable->getReferencedRelationsIndexedByOwningField(); foreach ($owningRelations as $owningField => $owningRelation) { // check if field is required (default of matchType) and insert required related data if ($randomGenerator->matchType($refFields[$owningField])) { $data[$owningField] = $this->insertRequiredLocalRelationGraph($rm, $owningRelation); } } // insert a record and return its id $data = $randomGenerator->getRandomRecordData($refFields, $data); $conn->insert($refTable, $data); return $conn->getLastInsertId($refTableName); }
/** * @param Relation $relation * @param string $relationName * @param bool $withMappedFields * @param array $visited * @return array|bool */ private function getReferenceAsArray(Relation $relation, $relationName, $withMappedFields, array &$visited) { if (!$relation->hasReferenceLoadedFor($this, $relationName)) { return false; } /** @var Record|Record[]|RecordCollection $related */ $related = $this->get($relationName); if ($relation->isOneToMany() && $relation->isOwningSide($relationName)) { $reference = array(); foreach ($related as $relatedRecord) { $reference[] = $relatedRecord->toArray(true, $withMappedFields, $visited); } return $reference; } return $related->toArray(true, $withMappedFields, $visited); }
/** * @param Relation $owningRelation * @param Record $owningRecord * @throws UnitOfWorkException */ private function applyDeleteConstraint(Relation $owningRelation, Record $owningRecord) { $owningFieldName = $owningRelation->getOwningField(); if ($owningRecord->isFieldModified($owningFieldName)) { return; } $constraintName = $owningRelation->getOnDelete(); switch ($constraintName) { case PlatformInterface::CASCADE: $this->scheduleDelete($owningRecord); break; case PlatformInterface::SET_NULL: if (!$this->isRecordScheduledForDelete($owningRecord)) { $owningRecord->set($owningFieldName, null); $this->scheduleSave($owningRecord); } break; case PlatformInterface::RESTRICT: case PlatformInterface::NO_ACTION: // if not deleted yet, it has to be deleted before commit for comply with the constraint if (!$this->isRecordScheduledForDelete($owningRecord)) { $this->markRecordForRestrictOnCommitWhenNotDeleted($owningRecord); } break; } }
public function testGetDefinition() { $expected = array('owningAlias' => 'Author', 'owningTable' => 'user_id', 'owningField' => 'author', 'refAlias' => 'User', 'refTable' => 'id', 'refField' => 'user', 'type' => '1-1', 'onDelete' => 'CASCADE', 'onUpdate' => 'CASCADE', 'orderBy' => ''); $rm = new Relation($expected['owningAlias'], $expected['owningTable'], $expected['owningField'], $expected['refAlias'], $expected['refTable'], $expected['refField'], $expected['type'], $expected['onDelete'], $expected['onUpdate']); $this->assertEquals($expected, $rm->getDefinition()); }
/** * @param Relation $relation * @param string $relationName * @return Record */ private function getReferencedRecord(Relation $relation, $relationName) { return $relation->isReferencedSide($relationName) ? $this->relatedRecord : $this->storedRecord; }
/** * Saves record on owning relation * * @param array $row * @param \Dive\Relation\Relation $relation * @param string $value * @return array */ private function saveRecordOnReferencedRelation(array $row, Relation $relation, $value) { $refTable = $relation->getReferencedTable(); $relatedId = $this->getRecordIdFromMap($refTable, $value); if ($relatedId === false) { $relatedId = $this->saveRelatedRecord($refTable, $value); } $row[$relation->getOwningField()] = $relatedId; return $row; }