/** * {@inheritdoc} */ public function create(string $resourceClass, string $name, array $options = []) : PropertyMetadata { if (null === $this->decorated) { $propertyMetadata = new PropertyMetadata(); } else { try { $propertyMetadata = $this->decorated->create($resourceClass, $name, $options); } catch (PropertyNotFoundException $propertyNotFoundException) { $propertyMetadata = new PropertyMetadata(); } } if (null === $propertyMetadata->getType()) { $types = $this->propertyInfo->getTypes($resourceClass, $name, $options); if (isset($types[0])) { $propertyMetadata = $propertyMetadata->withType($types[0]); } } if (null === $propertyMetadata->getDescription() && null !== ($description = $this->propertyInfo->getShortDescription($resourceClass, $name, $options))) { $propertyMetadata = $propertyMetadata->withDescription($description); } if (null === $propertyMetadata->isReadable() && null !== ($readable = $this->propertyInfo->isReadable($resourceClass, $name, $options))) { $propertyMetadata = $propertyMetadata->withReadable($readable); } if (null === $propertyMetadata->isWritable() && null !== ($writable = $this->propertyInfo->isWritable($resourceClass, $name, $options))) { $propertyMetadata = $propertyMetadata->withWritable($writable); } return $propertyMetadata; }
/** * Sets readable/writable based on matching normalization/denormalization groups. * * A false value is never reset as it could be unreadable/unwritable for other reasons. * If normalization/denormalization groups are not specified, the property is implicitly readable/writable. * * @param PropertyMetadata $propertyMetadata * @param string $resourceClass * @param string $propertyName * @param string[]|null $normalizationGroups * @param string[]|null $denormalizationGroups * * @return PropertyMetadata */ private function transformReadWrite(PropertyMetadata $propertyMetadata, string $resourceClass, string $propertyName, array $normalizationGroups = null, array $denormalizationGroups = null) : PropertyMetadata { $groups = $this->getPropertySerializerGroups($resourceClass, $propertyName); if (false !== $propertyMetadata->isReadable()) { $propertyMetadata = $propertyMetadata->withReadable(null === $normalizationGroups || !empty(array_intersect($normalizationGroups, $groups))); } if (false !== $propertyMetadata->isWritable()) { $propertyMetadata = $propertyMetadata->withWritable(null === $denormalizationGroups || !empty(array_intersect($denormalizationGroups, $groups))); } return $propertyMetadata; }
/** * Gets a property definition. * * @param PropertyMetadata $propertyMetadata * @param string $propertyName * @param string $prefixedShortName * @param string $shortName * * @return array */ private function getProperty(PropertyMetadata $propertyMetadata, string $propertyName, string $prefixedShortName, string $shortName) : array { $type = $propertyMetadata->isReadableLink() ? 'rdf:Property' : 'hydra:Link'; $property = ['@type' => 'hydra:SupportedProperty', 'hydra:property' => ['@id' => ($iri = $propertyMetadata->getIri()) ? $iri : sprintf('#%s/%s', $shortName, $propertyName), '@type' => $type, 'rdfs:label' => $propertyName, 'domain' => $prefixedShortName], 'hydra:title' => $propertyName, 'hydra:required' => $propertyMetadata->isRequired(), 'hydra:readable' => $propertyMetadata->isReadable(), 'hydra:writable' => $propertyMetadata->isWritable()]; if (null !== ($range = $this->getRange($propertyMetadata))) { $property['hydra:property']['range'] = $range; } if (null !== ($description = $propertyMetadata->getDescription())) { $property['hydra:description'] = $description; } return $property; }
public function testCreateWithPropertyWithNonStringValidationGroupsAndRequiredConstraints() { $propertyMetadata = new PropertyMetadata(null, 'A dummy group', true, true, null, null, null, false); $expectedPropertyMetadata = $propertyMetadata->withRequired(false); $decoratedPropertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class); $decoratedPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummyGroup', ['validation_groups' => [1312]])->willReturn($propertyMetadata)->shouldBeCalled(); $validatorMetadataFactory = $this->prophesize(MetadataFactoryInterface::class); $validatorMetadataFactory->getMetadataFor(DummyValidatedEntity::class)->willReturn($this->validatorClassMetadata)->shouldBeCalled(); $validatorPropertyMetadataFactory = new ValidatorPropertyMetadataFactory($validatorMetadataFactory->reveal(), $decoratedPropertyMetadataFactory->reveal()); $resultedPropertyMetadata = $validatorPropertyMetadataFactory->create(DummyValidatedEntity::class, 'dummyGroup', ['validation_groups' => [1312]]); $this->assertInstanceOf(PropertyMetadata::class, $resultedPropertyMetadata); $this->assertEquals($expectedPropertyMetadata, $resultedPropertyMetadata); }
/** * Parses a property. * * @param ResourceMetadata $resourceMetadata * @param PropertyMetadata $propertyMetadata * @param string $io * @param Type|null $type * @param string[] $visited * * @return array */ private function parseProperty(ResourceMetadata $resourceMetadata, PropertyMetadata $propertyMetadata, $io, Type $type = null, array $visited = []) { $data = ['dataType' => null, 'required' => $propertyMetadata->isRequired(), 'description' => $propertyMetadata->getDescription(), 'readonly' => !$propertyMetadata->isWritable()]; if (null === $type && null === ($type = $propertyMetadata->getType())) { // Default to string $data['dataType'] = DataTypes::STRING; return $data; } if ($type->isCollection()) { $data['actualType'] = DataTypes::COLLECTION; if ($collectionType = $type->getCollectionValueType()) { $subProperty = $this->parseProperty($resourceMetadata, $propertyMetadata, $io, $collectionType, $visited); if (self::TYPE_IRI === $subProperty['dataType']) { $data['dataType'] = 'array of IRIs'; $data['subType'] = DataTypes::STRING; return $data; } $data['subType'] = $subProperty['subType']; if (isset($subProperty['children'])) { $data['children'] = $subProperty['children']; } } return $data; } $builtinType = $type->getBuiltinType(); if ('object' === $builtinType) { $className = $type->getClassName(); if (is_subclass_of($className, \DateTimeInterface::class)) { $data['dataType'] = DataTypes::DATETIME; $data['format'] = sprintf('{DateTime %s}', \DateTime::RFC3339); return $data; } try { $this->resourceMetadataFactory->create($className); } catch (ResourceClassNotFoundException $e) { $data['actualType'] = DataTypes::MODEL; $data['subType'] = $className; return $data; } if (self::OUT_PREFIX === $io && true !== $propertyMetadata->isReadableLink() || self::IN_PREFIX === $io && true !== $propertyMetadata->isWritableLink()) { $data['dataType'] = self::TYPE_IRI; $data['actualType'] = DataTypes::STRING; return $data; } $data['actualType'] = DataTypes::MODEL; $data['subType'] = $className; $data['children'] = in_array($className, $visited) ? [] : $this->parseResource($resourceMetadata, $className, $io); return $data; } $data['dataType'] = self::TYPE_MAP[$builtinType] ?? DataTypes::STRING; return $data; }
public function testValueObject() { $type = new Type(Type::BUILTIN_TYPE_STRING); $metadata = new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'desc', true, true, false, false, true, false, 'http://example.com/foo', null, ['foo' => 'bar']); $this->assertEquals($type, $metadata->getType()); $this->assertEquals('desc', $metadata->getDescription()); $this->assertTrue($metadata->isReadable()); $this->assertTrue($metadata->isWritable()); $this->assertFalse($metadata->isReadableLink()); $this->assertFalse($metadata->isWritableLink()); $this->assertTrue($metadata->isRequired()); $this->assertFalse($metadata->isIdentifier()); $this->assertEquals('http://example.com/foo', $metadata->getIri()); $this->assertEquals(['foo' => 'bar'], $metadata->getAttributes()); $newType = new Type(Type::BUILTIN_TYPE_BOOL); $newMetadata = $metadata->withType($newType); $this->assertNotSame($metadata, $newMetadata); $this->assertEquals($newType, $newMetadata->getType()); $newMetadata = $metadata->withDescription('description'); $this->assertNotSame($metadata, $newMetadata); $this->assertEquals('description', $newMetadata->getDescription()); $newMetadata = $metadata->withReadable(false); $this->assertNotSame($metadata, $newMetadata); $this->assertFalse($newMetadata->isReadable()); $newMetadata = $metadata->withWritable(false); $this->assertNotSame($metadata, $newMetadata); $this->assertFalse($newMetadata->isWritable()); $newMetadata = $metadata->withReadableLink(true); $this->assertNotSame($metadata, $newMetadata); $this->assertTrue($newMetadata->isReadableLink()); $newMetadata = $metadata->withWritableLink(true); $this->assertNotSame($metadata, $newMetadata); $this->assertTrue($newMetadata->isWritableLink()); $newMetadata = $metadata->withRequired(false); $this->assertNotSame($metadata, $newMetadata); $this->assertFalse($newMetadata->isRequired()); $newMetadata = $metadata->withIdentifier(true); $this->assertNotSame($metadata, $newMetadata); $this->assertTrue($newMetadata->isIdentifier()); $newMetadata = $metadata->withIri('foo:bar'); $this->assertNotSame($metadata, $newMetadata); $this->assertEquals('foo:bar', $newMetadata->getIri()); $newMetadata = $metadata->withAttributes(['a' => 'b']); $this->assertNotSame($metadata, $newMetadata); $this->assertEquals(['a' => 'b'], $newMetadata->getAttributes()); }
/** * Gets a property Schema Object. * * @see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#schemaObject * * @param PropertyMetadata $propertyMetadata * * @return \ArrayObject */ private function getPropertySchema(PropertyMetadata $propertyMetadata) : \ArrayObject { $propertySchema = new \ArrayObject(); if (false === $propertyMetadata->isWritable()) { $propertySchema['readOnly'] = true; } if (null !== ($description = $propertyMetadata->getDescription())) { $propertySchema['description'] = $description; } if (null === ($type = $propertyMetadata->getType())) { return $propertySchema; } $isCollection = $type->isCollection(); if (null === ($valueType = $isCollection ? $type->getCollectionValueType() : $type)) { $builtinType = 'string'; $className = null; } else { $builtinType = $valueType->getBuiltinType(); $className = $valueType->getClassName(); } $valueSchema = $this->getType($builtinType, $isCollection, $className, $propertyMetadata->isReadableLink()); return new \ArrayObject((array) $propertySchema + $valueSchema); }
/** * Normalizes a relation as an URI if is a Link or as a JSON-LD object. * * @param PropertyMetadata $propertyMetadata * @param mixed $relatedObject * @param string $resourceClass * @param string|null $format * @param array $context * * @return string|array */ private function normalizeRelation(PropertyMetadata $propertyMetadata, $relatedObject, string $resourceClass, string $format = null, array $context) { if ($propertyMetadata->isReadableLink()) { return $this->serializer->normalize($relatedObject, $format, $this->createRelationSerializationContext($resourceClass, $context)); } return $this->iriConverter->getIriFromItem($relatedObject); }