/** * @param TransportableInterface $resource * @param array $data * @return TransportableInterface * * @throws HydrationException when invalid data provided. */ protected function hydrateResource(TransportableInterface $resource, array $data) { $mapping = $this->parser->parse($resource); foreach ($mapping->getFields() as $field) { $reflector = $field->getField()->getReflector(); $reflector->setAccessible(true); if (!isset($data[$field->getName()])) { throw new HydrationException(sprintf(HydrationException::MESSAGE_DATA_MISSING, get_class($resource), $reflector->getName(), $field->getName())); } $reflector->setValue($resource, $data[$field->getName()]); } foreach ($mapping->getAssociations() as $association) { $reflector = $association->getAssociation()->getReflector(); $reflector->setAccessible(true); if (!isset($data[$association->getName()])) { throw new HydrationException(sprintf(HydrationException::MESSAGE_DATA_MISSING, get_class($resource), $reflector->getName(), $association->getName())); } $resourceData = $data[$association->getName()]; if ($association->getAssociation()->collection) { $value = new ResourceCollection(); } else { $instance = $association->getAssociation()->target; $instance = new $instance(); if (isset($resourceData[self::KEY_RECURSION])) { $value = $instance; } else { $value = $this->hydrateResource($instance, $resourceData); } } $reflector->setValue($resource, $value); } return $resource; }
/** * Expect that the field mapping can get the correct name for the array. If the {@link Field} annotation * provides a alias then we should use that instead. * * @test */ public function validateFieldMappingUnderstandsName() { $annotations = new ArrayCollection(); $builder = $this->getMockBuilder(ReflectionProperty::class); $builder->disableOriginalConstructor(); $builder->setMethods(['getName']); /** @var MockObject|ReflectionProperty $property */ $property = $builder->getMock(); $property->expects($this->any())->method('getName')->willReturn('property'); $annotations->add($field = new Field()); $field->setReflector($property); $parser = new AnnotationParser(new AnnotationReader()); $mapping = $parser->processFieldAnnotations($property, $annotations); $this->assertEquals($property->getName(), $mapping->getName()); $field->name = 'property-edit'; $mapping = $parser->processFieldAnnotations($property, $annotations); $this->assertEquals($field->name, $mapping->getName()); }
/** * Expect that the given {@link ResourceMapping} should have at most one {@link Field} marked with primary. * * @test */ public function validateResourceHasAtMostOneMappedFieldFlaggedPrimary() { $resource = new ResourceMapping(); $field = new Field(); $field->primary = true; $mapping = new FieldMapping(); $mapping->setField($field); $resource->getFields()->add($mapping); $resource->getFields()->add($mapping); $this->setExpectedException(InvalidMappingException::class, 'resource-field-primary-many'); $this->parser->validateResourceMapping($resource); }
/** * Expect that the {@link ArtistResourceMock} is parsed correctly. * * @test */ public function validateMockResourceParsing() { $resource = new ArtistResourceMock(); $mapping = $this->parser->parse($resource); $message = 'The primary @Field annotation was marked against the $id property.'; $this->assertEquals('id', $mapping->getPrimary()->getField()->getReflector()->getName(), $message); $fields = $mapping->getFields(); $this->assertCount(2, $fields, 'There should be 2 properties mapped with @Field annotations'); $field = $fields[0]; $this->assertEquals('id', $field->getField()->getReflector()->getName()); $this->assertTrue($field->getField()->primary); $field = $fields[1]; $this->assertEquals('name', $field->getField()->getReflector()->getName()); $this->assertFalse($field->getField()->primary); $associations = $mapping->getAssociations(); $this->assertCount(1, $associations, 'There should be 1 property mapped with @Association annotations'); $field = $associations[0]; $this->assertEquals('albums', $field->getField()->getReflector()->getName()); $this->assertFalse($field->getField()->primary); $this->assertEquals(AlbumResourceMock::class, $field->getAssociation()->target); $this->assertTrue($field->getAssociation()->collection); }