/** * @param AttributeMetadataInterface $attributeMetadata * * @return mixed */ public function guess(AttributeMetadataInterface $attributeMetadata) { $value = null; $type = null; if (true === ($isDoctrine = isset($attributeMetadata->getTypes()[0]))) { $type = $attributeMetadata->getTypes()[0]; } // Guess associations if ($isDoctrine && 'object' === $type->getType() && 'DateTime' !== $type->getClass()) { $class = $type->isCollection() ? $type->getCollectionType()->getClass() : $type->getClass(); $resource = $this->resourceCollection->getResourceForEntity($class); $classMetadata = $this->classMetadataFactory->getMetadataFor($resource->getEntityClass(), $resource->getNormalizationGroups(), $resource->getDenormalizationGroups(), $resource->getValidationGroups()); $id = $this->guess($classMetadata->getIdentifier()); $value = $this->iriConverter->getIriFromResource($resource) . '/' . $id; if ($type->isCollection()) { $value = [$value]; } } // Guess by faker if (null === $value) { try { $value = call_user_func([$this->generator, $attributeMetadata->getName()]); } catch (\InvalidArgumentException $e) { } } // Guess by field name if (null === $value) { $value = $this->guessFormat(Inflector::tableize($attributeMetadata->getName())); } // Guess by Doctrine type if (null === $value && $isDoctrine) { switch ($type->getType()) { case 'string': $value = $this->generator->sentence; break; case 'int': $value = $this->generator->numberBetween; break; case 'bool': $value = $this->generator->boolean; break; case 'object': if ('DateTime' !== $type->getClass()) { throw new \InvalidArgumentException(sprintf('Unknown Doctrine object type %s in field %s', $type->getClass(), $attributeMetadata->getName())); } $value = $this->generator->dateTime; break; } } return $this->clean($value); }
/** * Denormalizes a relation. * * @param ResourceInterface $currentResource * @param AttributeMetadataInterface $attributeMetadata * @param string $class * @param mixed $value * @param array $context * * @return object|null * * @throws InvalidArgumentException */ private function denormalizeRelation(ResourceInterface $currentResource, AttributeMetadataInterface $attributeMetadata, $class, $value, array $context) { if ('DateTime' === $class) { return $this->serializer->denormalize($value, $class ?: null, self::FORMAT, $context); } $attributeName = $attributeMetadata->getName(); // Always allow IRI to be compliant with the Hydra spec if (is_string($value)) { $item = $this->iriConverter->getItemFromIri($value); if (null === $item) { throw new InvalidArgumentException(sprintf('IRI not supported (found "%s" in "%s" of "%s")', $value, $attributeName, $currentResource->getEntityClass())); } return $item; } if (!($resource = $this->resourceCollection->getResourceForEntity($class))) { throw new InvalidArgumentException(sprintf('Type not supported (found "%s" in attribute "%s" of "%s")', $class, $attributeName, $currentResource->getEntityClass())); } if (!$attributeMetadata->isDenormalizationLink()) { return $this->serializer->denormalize($value, $class, self::FORMAT, $this->createRelationContext($resource, $context)); } throw new InvalidArgumentException(sprintf('Nested objects for attribute "%s" of "%s" are not enabled. Use serialization groups to change that behavior.', $attributeName, $currentResource->getEntityClass())); }
/** * Parses an attribute. * * @param ResourceInterface $resource * @param AttributeMetadataInterface $attributeMetadata * @param string $io * @param Type|null $type * * @return array */ private function parseAttribute(ResourceInterface $resource, AttributeMetadataInterface $attributeMetadata, $io, Type $type = null) { $data = array('dataType' => null, 'required' => $attributeMetadata->isRequired(), 'description' => $attributeMetadata->getDescription(), 'readonly' => !$attributeMetadata->isWritable()); if (null == $type) { if (!isset($attributeMetadata->getTypes()[0])) { // Default to string $data['dataType'] = DataTypes::STRING; return $data; } // Use the first type found as primary $type = $attributeMetadata->getTypes()[0]; } if ($type->isCollection()) { $data['actualType'] = DataTypes::COLLECTION; if ($collectionType = $type->getCollectionType()) { $subAttribute = $this->parseAttribute($resource, $attributeMetadata, $io, $collectionType); if (self::IRI === $subAttribute['dataType']) { $data['dataType'] = 'array of IRIs'; $data['subType'] = DataTypes::STRING; return $data; } $data['subType'] = $subAttribute['subType']; $data['children'] = $subAttribute['children']; } return $data; } $phpType = $type->getType(); if ('object' === $phpType) { $class = $type->getClass(); if ('DateTime' === $class) { $data['dataType'] = DataTypes::DATETIME; $data['format'] = sprintf('{DateTime %s}', \DateTime::ATOM); return $data; } if (self::OUT_PREFIX === $io && $attributeMetadata->isNormalizationLink() || self::IN_PREFIX === $io && $attributeMetadata->isDenormalizationLink()) { $data['dataType'] = self::IRI; $data['actualType'] = DataTypes::STRING; return $data; } $data['actualType'] = DataTypes::MODEL; $data['subType'] = $class; $data['children'] = $resource->getEntityClass() === $class ? [] : $this->parseClass($resource, $class, $io); return $data; } $data['dataType'] = isset(self::$typeMap[$type->getType()]) ? self::$typeMap[$type->getType()] : DataTypes::STRING; return $data; }
/** * Gets the range of the property. * * @param AttributeMetadataInterface $attributeMetadata * * @return string|null */ private function getRange(AttributeMetadataInterface $attributeMetadata) { if (isset($attributeMetadata->getTypes()[0])) { $type = $attributeMetadata->getTypes()[0]; if ($type->isCollection() && ($collectionType = $type->getCollectionType())) { $type = $collectionType; } switch ($type->getType()) { case 'string': return 'xmls:string'; case 'int': return 'xmls:integer'; case 'float': return 'xmls:double'; case 'bool': return 'xmls:boolean'; case 'object': $class = $type->getClass(); if ($class) { if ('DateTime' === $class) { return 'xmls:dateTime'; } if ($resource = $this->resourceCollection->getResourceForEntity($type->getClass())) { return sprintf('#%s', $resource->getShortName()); } } break; } } }
/** * Populates normalization and denormalization links. * * @param ClassMetadataInterface $classMetadata * @param string $attributeName * @param AttributeMetadataInterface $attributeMetadata * @param array|null $normalizationGroups * @param array|null $denormalizationGroups * * @return ClassMetadataInterface */ private function populateNormalizationLinks(ClassMetadataInterface $classMetadata, $attributeName, AttributeMetadataInterface $attributeMetadata, array $normalizationGroups = null, array $denormalizationGroups = null) { if (!$classMetadata->hasAttributeMetadata($attributeName) || !$attributeMetadata->isLink() || $attributeMetadata->isNormalizationLink() && $attributeMetadata->isDenormalizationLink()) { return $classMetadata; } $relationSerializerMetadata = $this->serializerClassMetadataFactory->getMetadataFor($attributeMetadata->getLinkClass()); if (!$relationSerializerMetadata) { $attributeMetadata = $attributeMetadata->withNormalizationLink(true)->withDenormalizationLink(true); return $classMetadata->withAttributeMetadata($attributeName, $attributeMetadata); } foreach ($relationSerializerMetadata->getAttributesMetadata() as $serializerAttributeMetadata) { $serializerAttributeGroups = $serializerAttributeMetadata->getGroups(); if (null !== $normalizationGroups && 1 <= count(array_intersect($normalizationGroups, $serializerAttributeGroups))) { $normalizationLink = false; } if (null !== $denormalizationGroups && 1 <= count(array_intersect($denormalizationGroups, $serializerAttributeGroups))) { $denormalizationLink = false; } if (isset($normalizationLink) && isset($denormalizationLink)) { $classMetadata = $classMetadata->withAttributeMetadata($attributeName, $attributeMetadata); } } if (!isset($normalizationLink)) { $attributeMetadata = $attributeMetadata->withNormalizationLink(true); } if (!isset($denormalizationLink)) { $attributeMetadata = $attributeMetadata->withDenormalizationLink(true); } return $classMetadata->withAttributeMetadata($attributeName, $attributeMetadata); }