Returns parsed info about the value reference.
public static getValueReferenceDetails ( string $reference ) : array | ||
$reference | string | |
return | array | The details has keys 'source-column', 'source-value', 'value-column' |
public function replaceForeignKeysWithReferences($entityName, $entity) { $entityInfo = $this->schemaInfo->getEntityInfo($entityName); $vpIdTable = $this->schemaInfo->getPrefixedTableName('vp_id'); foreach ($entityInfo->references as $referenceName => $targetEntity) { $targetTable = $this->schemaInfo->getEntityInfo($targetEntity)->tableName; if (isset($entity[$referenceName])) { if ($entity[$referenceName] > 0) { $referenceVpId = $this->database->get_var("SELECT HEX(vp_id) FROM {$vpIdTable} WHERE `table` = '{$targetTable}' AND id={$entity[$referenceName]}"); } else { $referenceVpId = 0; } $entity['vp_' . $referenceName] = $referenceVpId; unset($entity[$referenceName]); } } foreach ($entityInfo->valueReferences as $referenceName => $targetEntity) { list($sourceColumn, $sourceValue, $valueColumn) = array_values(ReferenceUtils::getValueReferenceDetails($referenceName)); if (isset($entity[$sourceColumn]) && $entity[$sourceColumn] == $sourceValue && isset($entity[$valueColumn])) { if ($entity[$valueColumn] == 0) { continue; } if ($targetEntity[0] === '@') { $entityNameProvider = substr($targetEntity, 1); $targetEntity = call_user_func($entityNameProvider, $entity); if (!$targetEntity) { continue; } } $targetTable = $this->schemaInfo->getEntityInfo($targetEntity)->tableName; $referenceVpId = $this->database->get_var("SELECT HEX(vp_id) FROM {$vpIdTable} WHERE `table` = '{$targetTable}' AND id=" . $entity[$valueColumn]); $entity[$valueColumn] = $referenceVpId; } } return $entity; }
/** * Fixes value references * * @param $entity */ private function fixValueReferencesOfOneEntity($entity) { $entityInfo = $this->dbSchema->getEntityInfo($this->entityName); $references = $entityInfo->valueReferences; $referencesToUpdate = array(); foreach ($references as $reference => $referencedEntity) { list($sourceColumn, $sourceValue, $valueColumn) = array_values(ReferenceUtils::getValueReferenceDetails($reference)); if (isset($entity[$sourceColumn]) && $entity[$sourceColumn] == $sourceValue && isset($entity[$valueColumn])) { $referencesToUpdate[$valueColumn] = $entity[$valueColumn]; } } if (count($referencesToUpdate) === 0) { return; } $idMap = $this->getIdsForVpIds($referencesToUpdate); $entityTable = $this->dbSchema->getPrefixedTableName($this->entityName); $vpIdTable = $this->dbSchema->getPrefixedTableName('vp_id'); $idColumnName = $entityInfo->idColumnName; $updateSql = "UPDATE {$entityTable} SET "; $newReferences = array_map(function ($vpId) use($idMap) { return $idMap[$vpId]; }, $referencesToUpdate); $updateSql .= join(", ", ArrayUtils::parametrize($newReferences)); $updateSql .= " WHERE {$idColumnName}=(SELECT id FROM {$vpIdTable} WHERE vp_id=UNHEX(\"{$entity['vp_id']}\"))"; $this->database->query($updateSql); }
/** * Returns true if there is any entity with reference to the passed one. * * @param $entityName * @param $entityId * @return bool */ private function existsSomeEntityWithReferenceTo($entityName, $entityId) { $entityNames = $this->dbSchemaInfo->getAllEntityNames(); foreach ($entityNames as $otherEntityName) { $otherEntityInfo = $this->dbSchemaInfo->getEntityInfo($otherEntityName); $otherEntityReferences = $otherEntityInfo->references; $otherEntityMnReferences = $otherEntityInfo->mnReferences; $otherEntityValueReferences = $otherEntityInfo->valueReferences; $allReferences = array_merge($otherEntityReferences, $otherEntityMnReferences, $otherEntityValueReferences); foreach ($allReferences as $reference => $referencedEntity) { // if the target is dynamic, check it anyway - just to be sure if ($referencedEntity !== $entityName && $referencedEntity[0] !== '@') { continue; } $otherEntityStorage = $this->storageFactory->getStorage($otherEntityName); $possiblyReferencingEntities = $otherEntityStorage->loadAll(); if (isset($otherEntityReferences[$reference])) { // 1:N reference $vpReference = "vp_{$reference}"; foreach ($possiblyReferencingEntities as $possiblyReferencingEntity) { if (isset($possiblyReferencingEntity[$vpReference])) { $referencedVpidsString = $possiblyReferencingEntity[$vpReference]; preg_match_all(IdUtil::getRegexMatchingId(), $referencedVpidsString, $matches); if (ArrayUtils::any($matches[0], Comparators::equals($entityId))) { return true; } } } } elseif (isset($otherEntityMnReferences[$reference])) { // M:N reference $vpReference = "vp_{$otherEntityName}"; foreach ($possiblyReferencingEntities as $possiblyReferencingEntity) { if (isset($possiblyReferencingEntity[$vpReference]) && array_search($entityId, $possiblyReferencingEntity[$vpReference]) !== false) { return true; } } } elseif (isset($otherEntityValueReferences[$reference])) { // Value reference list($sourceColumn, $sourceValue, $valueColumn, $pathInStructure) = array_values(ReferenceUtils::getValueReferenceDetails($reference)); foreach ($possiblyReferencingEntities as $possiblyReferencingEntity) { if (isset($possiblyReferencingEntity[$sourceColumn]) && ($possiblyReferencingEntity[$sourceColumn] === $sourceValue || ReferenceUtils::valueMatchesWildcard($sourceValue, $possiblyReferencingEntity[$sourceColumn])) && isset($possiblyReferencingEntity[$valueColumn])) { if (is_numeric($possiblyReferencingEntity[$valueColumn]) && intval($possiblyReferencingEntity[$valueColumn]) === 0 || $possiblyReferencingEntity[$valueColumn] === '') { continue; } if ($pathInStructure) { $possiblyReferencingEntity[$valueColumn] = unserialize($possiblyReferencingEntity[$valueColumn]); $paths = ReferenceUtils::getMatchingPaths($possiblyReferencingEntity[$valueColumn], $pathInStructure); } else { $paths = [[]]; // root = the value itself } /** @var Cursor[] $cursors */ $cursors = array_map(function ($path) use(&$possiblyReferencingEntity, $valueColumn) { return new Cursor($possiblyReferencingEntity[$valueColumn], $path); }, $paths); foreach ($cursors as $cursor) { $vpidsString = $cursor->getValue(); preg_match_all(IdUtil::getRegexMatchingId(), $vpidsString, $matches); if (ArrayUtils::any($matches[0], Comparators::equals($entityId))) { return true; } } } } } } } return false; }
public function restoreForeignKeys($entityName, $entity) { $entityInfo = $this->schemaInfo->getEntityInfo($entityName); foreach ($entityInfo->references as $referenceName => $targetEntity) { $referenceField = "vp_{$referenceName}"; if (isset($entity[$referenceField])) { if ($this->isNullReference($entity[$referenceField])) { $referencedId = 0; } else { $referencedId = $this->restoreIdsInString($entity[$referenceField]); } if (!Strings::contains($referencedId, self::UNKNOWN_VPID_MARK)) { $entity[$referenceName] = $referencedId; unset($entity[$referenceField]); } } } foreach ($entityInfo->valueReferences as $referenceName => $targetEntity) { list($sourceColumn, $sourceValue, $valueColumn, $pathInStructure) = array_values(ReferenceUtils::getValueReferenceDetails($referenceName)); if (isset($entity[$sourceColumn]) && ($entity[$sourceColumn] === $sourceValue || ReferenceUtils::valueMatchesWildcard($sourceValue, $entity[$sourceColumn])) && isset($entity[$valueColumn])) { if ($this->isNullReference($entity[$valueColumn])) { continue; } if ($pathInStructure) { $entity[$valueColumn] = unserialize($entity[$valueColumn]); $paths = ReferenceUtils::getMatchingPaths($entity[$valueColumn], $pathInStructure); } else { $paths = [[]]; // root = the value itself } /** @var Cursor[] $cursors */ $cursors = array_map(function ($path) use(&$entity, $valueColumn) { return new Cursor($entity[$valueColumn], $path); }, $paths); foreach ($cursors as $cursor) { $vpids = $cursor->getValue(); $referenceVpId = $this->restoreIdsInString($vpids); $cursor->setValue($referenceVpId); } if ($pathInStructure) { $entity[$valueColumn] = serialize($entity[$valueColumn]); } } } return $entity; }
private function maybeRestoreReference($option) { $entityInfo = $this->dbSchema->getEntityInfo('option'); foreach ($entityInfo->valueReferences as $reference => $targetEntity) { $referenceDetails = ReferenceUtils::getValueReferenceDetails($reference); if ($option[$referenceDetails['source-column']] === $referenceDetails['source-value'] && isset($option[$referenceDetails['value-column']])) { $vpid = $option[$referenceDetails['value-column']]; $vpidTable = $this->dbSchema->getPrefixedTableName('vp_id'); $targetTable = $this->dbSchema->getTableName($targetEntity); $dbId = $this->database->get_var("SELECT id FROM {$vpidTable} WHERE `table`='{$targetTable}' AND vp_id=UNHEX('{$vpid}')"); $option[$referenceDetails['value-column']] = $dbId; } } return $option; }
/** * Returns true if there is any entity with reference to the passed one. * * @param $entityName * @param $entityId * @return bool */ private function existsSomeEntityWithReferenceTo($entityName, $entityId) { $entityNames = $this->dbSchemaInfo->getAllEntityNames(); foreach ($entityNames as $otherEntityName) { $otherEntityInfo = $this->dbSchemaInfo->getEntityInfo($otherEntityName); $otherEntityReferences = $otherEntityInfo->references; $otherEntityMnReferences = $otherEntityInfo->mnReferences; $otherEntityValueReferences = $otherEntityInfo->valueReferences; $allReferences = array_merge($otherEntityReferences, $otherEntityMnReferences, $otherEntityValueReferences); $reference = array_search($entityName, $allReferences); if ($reference === false) { // Other entity is not referencing $entityName continue; } $otherEntityStorage = $this->storageFactory->getStorage($otherEntityName); $possiblyReferencingEntities = $otherEntityStorage->loadAll(); if (isset($otherEntityReferences[$reference])) { // 1:N reference $vpReference = "vp_{$reference}"; foreach ($possiblyReferencingEntities as $possiblyReferencingEntity) { if (isset($possiblyReferencingEntity[$vpReference]) && $possiblyReferencingEntity[$vpReference] === $entityId) { return true; } } } elseif (isset($otherEntityMnReferences[$reference])) { // M:N reference $vpReference = "vp_{$otherEntityName}"; foreach ($possiblyReferencingEntities as $possiblyReferencingEntity) { if (isset($possiblyReferencingEntity[$vpReference]) && array_search($entityId, $possiblyReferencingEntity[$vpReference]) !== false) { return true; } } } elseif (isset($otherEntityValueReferences[$reference])) { // Value reference list($sourceColumn, $sourceValue, $valueColumn) = array_values(ReferenceUtils::getValueReferenceDetails($reference)); foreach ($possiblyReferencingEntities as $possiblyReferencingEntity) { if (isset($possiblyReferencingEntity[$sourceColumn]) && $possiblyReferencingEntity[$sourceColumn] == $sourceValue && isset($possiblyReferencingEntity[$valueColumn]) && $possiblyReferencingEntity[$valueColumn] === $entityId) { return true; } } } } return false; }