Validates & completes a one-to-one association mapping.

@param array $mapping The mapping to validate & complete.

@return array The validated & completed mapping.

@throws RuntimeException
@throws MappingException
195868
protected function _validateAndCompleteOneToOneMapping(array $mapping)
    {
        $mapping = $this->_validateAndCompleteAssociationMapping($mapping);

        if (isset($mapping['joinColumns']) && $mapping['joinColumns']) {
            $mapping['isOwningSide'] = true;
        }

        if ($mapping['isOwningSide']) {
            if ( ! isset($mapping['joinColumns']) || ! $mapping['joinColumns']) {
                // Apply default join column
                $mapping['joinColumns'] = array(array(
                    'name' => $this->namingStrategy->joinColumnName($mapping['fieldName'], $this->name),
                    'referencedColumnName' => $this->namingStrategy->referenceColumnName()
                ));
            }

            $uniqueConstraintColumns = array();
            foreach ($mapping['joinColumns'] as &$joinColumn) {
                if ($mapping['type'] === self::ONE_TO_ONE && ! $this->isInheritanceTypeSingleTable()) {
                    if (count($mapping['joinColumns']) == 1) {
                        if ( ! isset($mapping['id']) || ! $mapping['id']) {
                            $joinColumn['unique'] = true;
                        }
                    } else {
                        $uniqueConstraintColumns[] = $joinColumn['name'];
                    }
                }

                if (empty($joinColumn['name'])) {
                    $joinColumn['name'] = $this->namingStrategy->joinColumnName($mapping['fieldName'], $this->name);
                }

                if (empty($joinColumn['referencedColumnName'])) {
                    $joinColumn['referencedColumnName'] = $this->namingStrategy->referenceColumnName();
                }

                if ($joinColumn['name'][0] === '`') {
                    $joinColumn['name']   = trim($joinColumn['name'], '`');
                    $joinColumn['quoted'] = true;
                }

                if ($joinColumn['referencedColumnName'][0] === '`') {
                    $joinColumn['referencedColumnName'] = trim($joinColumn['referencedColumnName'], '`');
                    $joinColumn['quoted']               = true;
                }

                $mapping['sourceToTargetKeyColumns'][$joinColumn['name']] = $joinColumn['referencedColumnName'];
                $mapping['joinColumnFieldNames'][$joinColumn['name']] = isset($joinColumn['fieldName'])
                        ? $joinColumn['fieldName'] : $joinColumn['name'];
            }

            if ($uniqueConstraintColumns) {
                if ( ! $this->table) {
                    throw new RuntimeException("ClassMetadataInfo::setTable() has to be called before defining a one to one relationship.");
                }
                $this->table['uniqueConstraints'][$mapping['fieldName']."_uniq"] = array(
                    'columns' => $uniqueConstraintColumns
                );
            }

            $mapping['targetToSourceKeyColumns'] = array_flip($mapping['sourceToTargetKeyColumns']);
        }

        $mapping['orphanRemoval']   = isset($mapping['orphanRemoval']) ? (bool) $mapping['orphanRemoval'] : false;
        $mapping['isCascadeRemove'] = $mapping['orphanRemoval'] ? true : $mapping['isCascadeRemove'];

        if ($mapping['orphanRemoval']) {
            unset($mapping['unique']);
        }

        if (isset($mapping['id']) && $mapping['id'] === true && !$mapping['isOwningSide']) {
            throw MappingException::illegalInverseIdentifierAssociation($this->name, $mapping['fieldName']);
        }

        return $mapping;
    }
313955
public function mapField(array $mapping)
    {
        if ( ! isset($mapping['fieldName']) && isset($mapping['name'])) {
            $mapping['fieldName'] = $mapping['name'];
        }
        if ( ! isset($mapping['fieldName'])) {
            throw MappingException::missingFieldName($this->name);
        }
        if ( ! isset($mapping['name'])) {
            $mapping['name'] = $mapping['fieldName'];
        }
        if (isset($this->fieldMappings[$mapping['fieldName']])) {
            //throw MappingException::duplicateFieldMapping($this->name, $mapping['fieldName']);
        }
        if ($this->discriminatorField !== null && $this->discriminatorField == $mapping['name']) {
            throw MappingException::discriminatorFieldConflict($this->name, $this->discriminatorField);
        }
        if (isset($mapping['targetDocument']) && strpos($mapping['targetDocument'], '\\') === false && strlen($this->namespace)) {
            $mapping['targetDocument'] = $this->namespace . '\\' . $mapping['targetDocument'];
        }

        if (isset($mapping['discriminatorMap'])) {
            foreach ($mapping['discriminatorMap'] as $key => $class) {
                if (strpos($class, '\\') === false && strlen($this->namespace)) {
                    $mapping['discriminatorMap'][$key] = $this->namespace . '\\' . $class;
                }
            }
        }

        if (isset($mapping['cascade']) && isset($mapping['embedded'])) {
            throw MappingException::cascadeOnEmbeddedNotAllowed($this->name, $mapping['fieldName']);
        }

        $cascades = isset($mapping['cascade']) ? array_map('strtolower', (array) $mapping['cascade']) : array();

        if (in_array('all', $cascades) || isset($mapping['embedded'])) {
            $cascades = array('remove', 'persist', 'refresh', 'merge', 'detach');
        }

        if (isset($mapping['embedded'])) {
            unset($mapping['cascade']);
        } elseif (isset($mapping['cascade'])) {
            $mapping['cascade'] = $cascades;
        }

        $mapping['isCascadeRemove'] = in_array('remove', $cascades);
        $mapping['isCascadePersist'] = in_array('persist', $cascades);
        $mapping['isCascadeRefresh'] = in_array('refresh', $cascades);
        $mapping['isCascadeMerge'] = in_array('merge', $cascades);
        $mapping['isCascadeDetach'] = in_array('detach', $cascades);

        if (isset($mapping['type']) && $mapping['type'] === 'file') {
            $mapping['file'] = true;
        }
        if (isset($mapping['file']) && $mapping['file'] === true) {
            $this->file = $mapping['fieldName'];
            $mapping['name'] = 'file';
        }
        if (isset($mapping['distance']) && $mapping['distance'] === true) {
            $this->distance = $mapping['fieldName'];
        }
        if (isset($mapping['id']) && $mapping['id'] === true) {
            $mapping['name'] = '_id';
            $mapping['type'] = isset($mapping['type']) ? $mapping['type'] : 'id';
            $this->identifier = $mapping['fieldName'];
            if (isset($mapping['strategy'])) {
                $this->generatorOptions = isset($mapping['options']) ? $mapping['options'] : array();

                $generatorType = constant('Doctrine\ODM\MongoDB\Mapping\ClassMetadata::GENERATOR_TYPE_' . strtoupper($mapping['strategy']));
                if ($generatorType !== self::GENERATOR_TYPE_AUTO) {
                    if (isset($this->generatorOptions['type'])) {
                        $mapping['type'] = $this->generatorOptions['type'];
                    } elseif ($generatorType === ClassMetadata::GENERATOR_TYPE_INCREMENT) {
                        $mapping['type'] = 'int_id';
                    } else {
                        $mapping['type'] = 'custom_id';
                    }

                    unset($this->generatorOptions['type']);
                }

                $this->generatorType = $generatorType;
            }
        }
        if ( ! isset($mapping['nullable'])) {
            $mapping['nullable'] = false;
        }

        if (isset($mapping['reference']) && ! empty($mapping['simple']) && ! isset($mapping['targetDocument'])) {
            throw MappingException::simpleReferenceRequiresTargetDocument($this->name, $mapping['fieldName']);
        }

        if (isset($mapping['reference']) && $mapping['type'] === 'one') {
            $mapping['association'] = self::REFERENCE_ONE;
        }
        if (isset($mapping['reference']) && $mapping['type'] === 'many') {
            $mapping['association'] = self::REFERENCE_MANY;
        }
        if (isset($mapping['embedded']) && $mapping['type'] === 'one') {
            $mapping['association'] = self::EMBED_ONE;
        }
        if (isset($mapping['embedded']) && $mapping['type'] === 'many') {
            $mapping['association'] = self::EMBED_MANY;
        }

        if (isset($mapping['association']) && ! isset($mapping['targetDocument']) && ! isset($mapping['discriminatorField'])) {
            $mapping['discriminatorField'] = self::DEFAULT_DISCRIMINATOR_FIELD;
        }

        /*
        if (isset($mapping['type']) && ($mapping['type'] === 'one' || $mapping['type'] === 'many')) {
            $mapping['type'] = $mapping['type'] === 'one' ? self::ONE : self::MANY;
        }
        */
        if (isset($mapping['version'])) {
            $mapping['notSaved'] = true;
            $this->setVersionMapping($mapping);
        }
        if (isset($mapping['lock'])) {
            $mapping['notSaved'] = true;
            $this->setLockMapping($mapping);
        }
        $mapping['isOwningSide'] = true;
        $mapping['isInverseSide'] = false;
        if (isset($mapping['reference'])) {
            if (isset($mapping['inversedBy']) && $mapping['inversedBy']) {
                $mapping['isOwningSide'] = true;
                $mapping['isInverseSide'] = false;
            }
            if (isset($mapping['mappedBy']) && $mapping['mappedBy']) {
                $mapping['isInverseSide'] = true;
                $mapping['isOwningSide'] = false;
            }
            if (!isset($mapping['orphanRemoval'])) {
                $mapping['orphanRemoval'] = false;
            }
        }

        $this->fieldMappings[$mapping['fieldName']] = $mapping;
        if (isset($mapping['association'])) {
            $this->associationMappings[$mapping['fieldName']] = $mapping;
        }

        return $mapping;
    }
72423
protected function cacheMapping($mapping)
    {
        $mapping = array_filter($mapping);
        if ($mapping && !empty($mapping)) {
            $cache = SS_Cache::factory('gridfieldimporter');
            $cache->save(serialize($mapping), $this->cacheKey());
        }
    }
1266715
protected function _validateAndCompleteFieldMapping(array &$mapping)
    {
        // Check mandatory fields
        if ( ! isset($mapping['fieldName']) || strlen($mapping['fieldName']) == 0) {
            throw MappingException::missingFieldName($this->name);
        }
        if ( ! isset($mapping['type'])) {
            // Default to string
            $mapping['type'] = 'string';
        }

        // Complete fieldName and columnName mapping
        if ( ! isset($mapping['columnName'])) {
            $mapping['columnName'] = $this->namingStrategy->propertyToColumnName($mapping['fieldName'], $this->name);
        }

        if ($mapping['columnName'][0] === '`') {
            $mapping['columnName']  = trim($mapping['columnName'], '`');
            $mapping['quoted']      = true;
        }

        $this->columnNames[$mapping['fieldName']] = $mapping['columnName'];
        if (isset($this->fieldNames[$mapping['columnName']]) || ($this->discriminatorColumn != null && $this->discriminatorColumn['name'] == $mapping['columnName'])) {
            throw MappingException::duplicateColumnName($this->name, $mapping['columnName']);
        }

        $this->fieldNames[$mapping['columnName']] = $mapping['fieldName'];

        // Complete id mapping
        if (isset($mapping['id']) && $mapping['id'] === true) {
            if ($this->versionField == $mapping['fieldName']) {
                throw MappingException::cannotVersionIdField($this->name, $mapping['fieldName']);
            }

            if ( ! in_array($mapping['fieldName'], $this->identifier)) {
                $this->identifier[] = $mapping['fieldName'];
            }
            // Check for composite key
            if ( ! $this->isIdentifierComposite && count($this->identifier) > 1) {
                $this->isIdentifierComposite = true;
            }
        }

        if (Type::hasType($mapping['type']) && Type::getType($mapping['type'])->canRequireSQLConversion()) {
            if (isset($mapping['id']) && $mapping['id'] === true) {
                 throw MappingException::sqlConversionNotAllowedForIdentifiers($this->name, $mapping['fieldName'], $mapping['type']);
            }

            $mapping['requireSQLConversion'] = true;
        }
    }
468682
private function isWithinGroup(
        ValidatorContextInterface $context,
        ValidationGroupsInterface $mapping
    ): bool {
        if ([] === $groups = $context->getGroups()) {
            return true;
        }

        foreach ($mapping->getGroups() as $group) {
            if (in_array($group, $groups, true)) {
                return true;
            }
        }

        return false;
    }
1215870
public function addMapping(PathMapping $mapping)
    {
        if (!$mapping->isLoaded()) {
            throw new NotLoadedException('The passed mapping must be loaded.');
        }

        $moduleName = $mapping->getContainingModule()->getName();
        $previousMapping = isset($this->mappings[$moduleName]) ? $this->mappings[$moduleName] : null;

        if ($previousMapping === $mapping) {
            return;
        }

        if ($previousMapping) {
            $previousMapping->removeConflict($this);
        }

        $this->mappings[$moduleName] = $mapping;
        $mapping->addConflict($this);
    }
158679
public function mapField(array $mapping)
    {
        $mapping = parent::mapField($mapping);

        if ($this->reflClass->hasProperty($mapping['fieldName'])) {
            $reflProp = $this->reflClass->getProperty($mapping['fieldName']);
            $reflProp->setAccessible(true);
            $this->reflFields[$mapping['fieldName']] = $reflProp;
        }
    }
622519
public function mapOneToOne(array $mapping)
    {
        $mapping['type'] = self::ONE_TO_ONE;
        $mapping = $this->_validateAndCompleteOneToOneMapping($mapping);
        $this->_storeAssociationMapping($mapping);
    }
322030
public function mapField(array $mapping)
    {
        $this->_validateAndCompleteFieldMapping($mapping);
        $this->assertFieldNotMapped($mapping['fieldName']);

        $this->fieldMappings[$mapping['fieldName']] = $mapping;
    }
52795
public function resolve(&$mapping, &$obj, &$context)
    {
        if (empty($mapping)) {
            return $mapping;
        } elseif (is_array($mapping)) {
            $res = [];
            foreach ($mapping as $key => $value) {
                $resolved = $this->resolve($value, $obj, $context);

                if (null !== $resolved) {
                    $res[$key] = $resolved;
                }
            }

            return $res;
        } elseif (is_string($mapping)) {
            $dictionary = array_merge($this->dictionary, ['obj' => $obj, 'context' => $context]);
            $res = null;

            try {
                $res = @$this->evaluator->evaluateWithVars($mapping, $dictionary);
            } catch (\RuntimeException $e) {
                if ($this->debug) {
                    throw $e;
                }
            }

            return $res;
        }

        throw new \RuntimeException('Mapper expected the mapping to be a string or an array');
    }
388893
private function setRootDefault($key, array $mapping)
    {
        if (!isset($mapping[$key]) || !is_array($mapping[$key])) {
            $mapping[$key] = [];
        }
        return $mapping;
    }
288882
private function validateAutoMapping(array $managerConfigs)
    {
        $autoMappedManager = null;
        foreach ($managerConfigs as $name => $manager) {
            if (!$manager['auto_mapping']) {
                continue;
            }

            if (null !== $autoMappedManager) {
                throw new \LogicException(sprintf('You cannot enable "auto_mapping" on more than one manager at the same time (found in "%s" and %s").', $autoMappedManager, $name));
            }

            $autoMappedManager = $name;
        }

        return $autoMappedManager;
    }
958288
private function getMapping(\SimpleXmlElement $mapping, $field)
    {
        $field = $mapping->$field;

        if (!$field->getName()) {
            return;
        }

        return $this->getField($field);
    }
912620
protected function buildValidPropertyAlias($mapping)
    {
        $aliases = $mapping->getAliasedProperties();
        foreach ($aliases as &$alias) {
            $alias = DataAttributesHelper::transformToValidMemberName($alias);
        }
        $mapping->setPropertyNameAliases($aliases);
    }
1060149
public function setVersionMapping(array &$mapping)
    {
        $this->isVersioned = true;
        $this->versionField = $mapping['fieldName'];

        if ( ! isset($mapping['default'])) {
            if (in_array($mapping['type'], array('integer', 'bigint', 'smallint'))) {
                $mapping['default'] = 1;
            } else if ($mapping['type'] == 'datetime') {
                $mapping['default'] = 'CURRENT_TIMESTAMP';
            } else {
                throw MappingException::unsupportedOptimisticLockingType($this->name, $mapping['fieldName'], $mapping['type']);
            }
        }
    }
859716
public function mapParameter(array $mapping)
    {
        if (isset($this->fieldMappings[$mapping['parameterName']])) {
            throw MappingException::duplicateParameterMapping($this->className, $mapping['parameterName']);
        }
        $this->parameters[$mapping['parameterName']] = $mapping;
    }
1278143
protected static function setRelationships(array &$mappedClass, Mapping $mapping, string $className)
    {
        if (!empty($mappedClass[static::RELATIONSHIPS_KEY])) {
            foreach ($mappedClass[static::RELATIONSHIPS_KEY] as $propertyName => $urls) {
                if (false === \in_array($propertyName, static::getClassProperties($className))) {
                    throw new MappingException(
                        \sprintf(
                            'Could not find property %s in class %s because it does not exist.',
                            $propertyName,
                            $className
                        )
                    );
                }

                $mapping->setRelationshipUrls($propertyName, $urls);
            }
        }
    }