Create the denormalization method.

@param $modelFqdn
@param Context $context
@param $properties

@return Stmt\ClassMethod
962310
protected function createDenormalizeMethod($modelFqdn, Context $context, $properties)
    {
        $context->refreshScope();
        $objectVariable = new Expr\Variable('object');
        $assignStatement = new Expr\Assign($objectVariable, new Expr\New_(new Name('\\'.$modelFqdn)));
        $statements = [$assignStatement];

        if ($this->useReference) {
            $statements = [
                new Stmt\If_(
                    new Expr\Isset_([new Expr\PropertyFetch(new Expr\Variable('data'), "{'\$ref'}")]),
                    [
                        'stmts' => [
                            new Stmt\Return_(new Expr\New_(new Name('Reference'), [
                                new Expr\PropertyFetch(new Expr\Variable('data'), "{'\$ref'}"),
                                new Expr\ArrayDimFetch(new Expr\Variable('context'), new Scalar\String_('document-origin')),
                            ])),
                        ],
                    ]
                ),
                $assignStatement,
            ];
        }

        array_unshift($statements, new Stmt\If_(
            new Expr\BooleanNot(new Expr\FuncCall(new Name('is_object'), [new Arg(new Expr\Variable('data'))])),
            [
                'stmts' => [
                    new Stmt\Throw_(new Expr\New_(new Name('InvalidArgumentException')))
                ]
            ]
        ));

        foreach ($properties as $property) {
            $propertyVar = new Expr\PropertyFetch(new Expr\Variable('data'), sprintf("{'%s'}", $property->getName()));
            list($denormalizationStatements, $outputVar) = $property->getType()->createDenormalizationStatement($context, $propertyVar);

            $statements[] = new Stmt\If_(
                new Expr\FuncCall(new Name('property_exists'), [
                    new Arg(new Expr\Variable('data')),
                    new Arg(new Scalar\String_($property->getName())),
                ]), [
                    'stmts' => array_merge($denormalizationStatements, [
                        new Expr\MethodCall($objectVariable, $this->getNaming()->getPrefixedMethodName('set', $property->getName()), [
                            $outputVar,
                        ]),
                    ]),
                ]
            );
        }

        $statements[] = new Stmt\Return_($objectVariable);

        return new Stmt\ClassMethod('denormalize', [
            'type' => Stmt\Class_::MODIFIER_PUBLIC,
            'params' => [
                new Param('data'),
                new Param('class'),
                new Param('format', new Expr\ConstFetch(new Name('null'))),
                new Param('context', new Expr\Array_(), 'array'),
            ],
            'stmts' => $statements,
        ]);
    }
1105582
public function denormalize(array $data): FixtureBag
    {
        $fixtures = new FixtureBag();

        $alreadyRetried = [];
        while ($result = array_splice($data, 0, 1)) {
            $fqcnWithFlags = key($result);
            $rawFixtureSet = current($result);

            $flags = $this->flagParser->parse($fqcnWithFlags);
            $fqcn = $flags->getKey();

            if (false === is_array($rawFixtureSet)) {
                throw new InvalidArgumentException(
                    sprintf(
                        'Expected an array for the class "%s", found "%s" instead.',
                        $fqcnWithFlags,
                        gettype($rawFixtureSet)
                    )
                );
            }
            try {
                foreach ($rawFixtureSet as $reference => $specs) {
                    if (null === $specs) {
                        $specs = [];
                    }

                    $fixtures = $this->fixtureDenormalizer->denormalize(
                        $fixtures,
                        $fqcn,
                        $reference,
                        $specs ?? [],
                        $flags
                    );
                }
            } catch (UnexpectedValueException $exception) {
                if (!isset($alreadyRetried[$fqcnWithFlags])) {
                    $data[$fqcnWithFlags] = $rawFixtureSet;
                    $alreadyRetried[$fqcnWithFlags] = true;
                } else {
                    throw $exception;
                }
            }
        }

        return $fixtures;
    }
950769
public function property(string $propertyName): PropertyColumnDefiner
    {
        $this->verifyProperty(__METHOD__, $propertyName);

        return new PropertyColumnDefiner($this, $propertyName, function (
            Column $column,
            callable $phpToDbPropertyConverter = null,
            callable $dbToPhpPropertyConverter = null,
            bool $ignoreNullabilityMismatch = false
        ) use ($propertyName) {
            $this->propertyColumnMap[$propertyName] = $column->getName();
            $this->addColumn($column);
            $this->mappedProperties[$propertyName] = true;

            $propertyType = $this->class->getProperty($propertyName)->getType();
            $columnType   = $column->getType()->getPhpType();

            if ($ignoreNullabilityMismatch) {
                $propertyType = $propertyType->nonNullable();
                $columnType   = $columnType->nonNullable();
            }

            if ($phpToDbPropertyConverter && $dbToPhpPropertyConverter) {
                $this->phpToDbPropertyConverterMap[$propertyName] = $phpToDbPropertyConverter;
                $this->dbToPhpPropertyConverterMap[$propertyName] = $dbToPhpPropertyConverter;
            } elseif (!$propertyType->equals($columnType)) {
                throw IncompatiblePropertyMappingException::format(
                    'Invalid property to column mapping: cannot bind %s to column \'%s\' as the types are incompatible, '
                    . 'property type %s must match the column type %s',
                    $this->class->getClassName() . '::$' . $propertyName, $column->getName(),
                    $propertyType->asTypeString(), $columnType->asTypeString()
                );
            }
        });
    }
926502
public function denormalize(array $data): ParameterBag
    {
        if (false === array_key_exists('parameters', $data)
            || null === $fixturesParameters = $data['parameters']
        ) {
            return new ParameterBag();
        }

        if (false === is_array($fixturesParameters)) {
            throw TypeErrorFactory::createForInvalidFixtureBagParameters($fixturesParameters);
        }

        return new ParameterBag($fixturesParameters);
    }
871847
private function convertReflectionPropertyToFieldMetadata(
        ReflectionProperty $reflectionProperty,
        array $propertyAnnotations,
        Mapping\ClassMetadata $classMetadata
    ) {
        $className    = $classMetadata->getClassName();
        $fieldName    = $reflectionProperty->getName();
        $columnAnnot  = $propertyAnnotations[Annotation\Column::class];
        $isVersioned  = isset($propertyAnnotations[Annotation\Version::class]);
        $isPrimaryKey = isset($propertyAnnotations[Annotation\Id::class]);

        if ($columnAnnot->type === null) {
            throw Mapping\MappingException::propertyTypeIsRequired($className, $fieldName);
        }

        if ($isVersioned && $isPrimaryKey) {
            throw Mapping\MappingException::cannotVersionIdField($className, $fieldName);
        }

        $columnName = empty($columnAnnot->name)
            ? $this->namingStrategy->propertyToColumnName($fieldName, $className)
            : $columnAnnot->name;

        $fieldMetadata = $isVersioned
            ? new Mapping\VersionFieldMetadata($fieldName)
            : new Mapping\FieldMetadata($fieldName);

        $fieldMetadata->setType(Type::getType($columnAnnot->type));
        $fieldMetadata->setColumnName($columnName);
        $fieldMetadata->setScale($columnAnnot->scale);
        $fieldMetadata->setPrecision($columnAnnot->precision);
        $fieldMetadata->setNullable($columnAnnot->nullable);
        $fieldMetadata->setUnique($columnAnnot->unique);

        // Check for Id
        if ($isPrimaryKey) {
            if ($fieldMetadata->getType()->canRequireSQLConversion()) {
                throw Mapping\MappingException::sqlConversionNotAllowedForPrimaryKeyProperties($className, $fieldMetadata);
            }

            $fieldMetadata->setPrimaryKey(true);
        }

        if (! empty($columnAnnot->columnDefinition)) {
            $fieldMetadata->setColumnDefinition($columnAnnot->columnDefinition);
        }

        if (! empty($columnAnnot->length)) {
            $fieldMetadata->setLength($columnAnnot->length);
        }

        // Assign default options
        $customOptions  = $columnAnnot->options ?? [];
        $defaultOptions = [];

        if ($isVersioned) {
            switch ($fieldMetadata->getTypeName()) {
                case 'integer':
                case 'bigint':
                case 'smallint':
                    $defaultOptions['default'] = 1;
                    break;

                case 'datetime':
                    $defaultOptions['default'] = 'CURRENT_TIMESTAMP';
                    break;

                default:
                    if (! isset($customOptions['default'])) {
                        throw Mapping\MappingException::unsupportedOptimisticLockingType($fieldMetadata->getType());
                    }
            }
        }

        $fieldMetadata->setOptions(array_merge($defaultOptions, $customOptions));

        return $fieldMetadata;
    }
451205
protected function createModel($name, $properties, $methods)
    {
        return new Stmt\Class_(
            new Name($this->getNaming()->getClassName($name)),
            [
                'stmts' => array_merge($properties, $methods)
            ]
        );
    }
822936
private function createBuilderFromConnection(Connection $connection, string $modelClass): ModelQueryBuilder
    {
        return $this->getFactory()->createModelQueryBuilder($connection, $modelClass, $this->getModelSchemas());
    }
1222923
public static function create(array $properties): SkeletonEmbeddableInterface
    {
        if (array_key_exists(SkeletonEmbeddableInterface::EMBEDDED_PROP_PROPERTY_ONE, $properties)) {
            return new self(
                $properties[SkeletonEmbeddableInterface::EMBEDDED_PROP_PROPERTY_ONE],
                $properties[SkeletonEmbeddableInterface::EMBEDDED_PROP_PROPERTY_TWO]
            );
        }

        return new self(...array_values($properties));
    }
487663
public function denormalize($data, $class, $format = null, array $context = [])
    {
        // Handle -1 in expiresAt property of AppCredential.
        if ($data < 0) {
            return null;
        }
        $context[$this->normalizer::FORMAT_KEY] = 'U';
        $context[$this->normalizer::TIMEZONE_KEY] = new \DateTimeZone('UTC');

        return $this->normalizer->denormalize(intval($data / 1000), $class, $format, $context);
    }
364083
public function denormalize($data, $class, $format = null, array $context = [])
    {
        if (!\is_string($data)) {
            throw new InvalidArgumentException(sprintf('Data expected to be a string, %s given.', \gettype($data)));
        }

        if (!$this->isISO8601($data)) {
            throw new UnexpectedValueException('Expected a valid ISO 8601 interval string.');
        }

        $dateIntervalFormat = $context[self::FORMAT_KEY] ?? $this->defaultContext[self::FORMAT_KEY];

        $valuePattern = '/^'.preg_replace('/%([yYmMdDhHiIsSwW])(\w)/', '(?P<$1>\d+)$2', $dateIntervalFormat).'$/';
        if (!preg_match($valuePattern, $data)) {
            throw new UnexpectedValueException(sprintf('Value "%s" contains intervals not accepted by format "%s".', $data, $dateIntervalFormat));
        }

        try {
            return new \DateInterval($data);
        } catch (\Exception $e) {
            throw new UnexpectedValueException($e->getMessage(), $e->getCode(), $e);
        }
    }
1279797
public static function modelIdsQueryAtOnce($modelClass, $values)
    {
        $q = (new Query())
            ->select('model_id')
            ->from($modelClass::tableInheritanceTable());

        foreach ($values as $key => $vals) {
            $q->andWhere(['or', $key, $vals]);
        };

            $q->groupBy('model_id');
        return $q;
    }
67385
private function _loadOrCreateRelationModel($data, $fks, $modelClass, $relationName)
    {

        /** @var BaseActiveRecord $relationModel */
        $relationModel = null;
        if (!empty($fks)) {
            $relationModel = $modelClass::findOne($fks);
        }
        if (!($relationModel instanceof BaseActiveRecord) && !empty($data)) {
            $relationModel = new $modelClass;
        }
        // If a custom scenario is set, apply it here to correctly be able to set the model attributes
        if (array_key_exists($relationName, $this->_relationsScenario)) {
            $relationModel->setScenario($this->_relationsScenario[$relationName]);
        }
        if (($relationModel instanceof BaseActiveRecord) && is_array($data)) {
            $relationModel->setAttributes($data);
            if ($relationModel->hasMethod('loadRelations')) {
                $relationModel->loadRelations($data);
            }

        }
        return $relationModel;
    }
820324
public function denormalize($string, $class, $format = null, array $context = array())
    {
        if (!preg_match(static::FULL_REGEX, $string, $matches)) {
            throw new \InvalidArgumentException('The provided "data:" URI is not valid.');
        }

        $mime = !empty($matches[static::CONTEXT_MIME]) ? $matches[static::CONTEXT_MIME] : 'application/octet-stream';
        $charset = !empty($matches[static::CONTEXT_CHARSET]) ? $matches[static::CONTEXT_CHARSET] : null;
        $gzip = strpos($mime, 'gzip') !== false;
        $base64 = !empty($matches[static::CONTEXT_BASE64]) ? $matches[static::CONTEXT_BASE64] : null;
        $urldecode = strpos($mime, 'text/') !== false;

        $string = $matches[static::CONTEXT_DATA];

        if ($base64) {
            $string = base64_decode($string);
        }
        if ($gzip) {
            $string = gzdecode($string);
        }
        if ($urldecode or !$base64) {
            $string = urldecode($string);
        }

        return $string;
    }
1271918
public function denormalize($data, $class, $format = null, array $context = [])
    {
        // Avoid issues with proxies if we populated the object
        if (!isset($context[self::OBJECT_TO_POPULATE]) && isset($data['data']['id'])) {
            if (true !== ($context['api_allow_update'] ?? true)) {
                throw new NotNormalizableValueException('Update is not allowed for this operation.');
            }

            $context[self::OBJECT_TO_POPULATE] = $this->iriConverter->getItemFromIri(
                $data['data']['id'],
                $context + ['fetch_data' => false]
            );
        }

        // Merge attributes and relationships, into format expected by the parent normalizer
        $dataToDenormalize = array_merge(
            $data['data']['attributes'] ?? [],
            $data['data']['relationships'] ?? []
        );

        return parent::denormalize(
            $dataToDenormalize,
            $class,
            $format,
            $context
        );
    }
1157193
protected function createModel(string $name, $properties, $methods, bool $hasExtensions = false): Stmt\Class_
    {
        return new Stmt\Class_(
            new Name($this->getNaming()->getClassName($name)),
            [
                'stmts' => array_merge($properties, $methods),
                'extends' => $hasExtensions ? new Name('\ArrayObject') : null,
            ]
        );
    }
594924
protected function deepDelete(EnvironmentInterface $environment, ModelIdInterface $modelId)
    {
        /** @var DefaultModelRelationshipDefinition $relationships */
        $relationships = $environment->getDataDefinition()->getDefinition('model-relationships');

        $childConditions = $relationships->getChildConditions($modelId->getDataProviderName());

        // delete child element before delete parent element
        /** @var ParentChildConditionInterface $childCondition */
        foreach ($childConditions as $childCondition) {
            $destinationChildConditions = $relationships->getChildConditions($childCondition->getDestinationName());
            if (empty($destinationChildConditions)) {
                continue;
            }

            $dataProvider                 = $environment->getDataProvider($modelId->getDataProviderName());
            $model                        = $dataProvider->fetch(
                $dataProvider->getEmptyConfig()->setId($modelId->getId())
            );
            $destinationChildDataProvider = $environment->getDataProvider($childCondition->getDestinationName());

            /** @var DefaultCollection $destinationChildModels */
            $destinationChildModels = $destinationChildDataProvider->fetchAll(
                $dataProvider->getEmptyConfig()->setFilter($childCondition->getFilter($model))
            );
            if ($destinationChildModels->count() < 1) {
                continue;
            }

            foreach ($destinationChildModels as $destinationChildModel) {
                $this->deepDelete($environment, ModelId::fromModel($destinationChildModel));
            }
        }

        foreach ($childConditions as $childCondition) {
            $dataProvider      = $environment->getDataProvider($modelId->getDataProviderName());
            $model             = $dataProvider->fetch($dataProvider->getEmptyConfig()->setId($modelId->getId()));
            $childDataProvider = $environment->getDataProvider($childCondition->getDestinationName());

            $filters = $childCondition->getFilter($model);
            /** @var DefaultCollection $childModels */
            $childModels = $childDataProvider->fetchAll($dataProvider->getEmptyConfig()->setFilter($filters));
            if ($childModels->count() < 1) {
                continue;
            }

            foreach ($childModels as $childModel) {
                // Trigger event before the model will be deleted.
                $preDeleteEvent = new PreDeleteModelEvent($environment, $childModel);
                $environment->getEventDispatcher()->dispatch($preDeleteEvent::NAME, $preDeleteEvent);

                $childDataProvider->delete($childModel);

                // Trigger event after the model is deleted.
                $postDeleteEvent = new PostDeleteModelEvent($environment, $childModel);
                $environment->getEventDispatcher()->dispatch($postDeleteEvent::NAME, $postDeleteEvent);
            }
        }
    }
1136524
public static function createConvertType(
        string $name,
        string $type,
        bool $emptyToNull = false
    ): DenormalizationFieldMappingBuilderInterface {
        $self = new self($name);
        $self->fieldDenormalizer = new ConvertTypeFieldDenormalizer(new PropertyAccessor($name), $type, $emptyToNull);

        return $self;
    }