diff --git a/src/Field/BooleanField.php b/src/Field/BooleanField.php index a66d352..8d35d98 100644 --- a/src/Field/BooleanField.php +++ b/src/Field/BooleanField.php @@ -4,7 +4,7 @@ class BooleanField extends Field { - public function getDynamoDbType(): string + public function dynamoDbType(): string { return 'BOOL'; } diff --git a/src/Field/DateTimeField.php b/src/Field/DateTimeField.php index 711e2c8..f430722 100644 --- a/src/Field/DateTimeField.php +++ b/src/Field/DateTimeField.php @@ -4,7 +4,7 @@ class DateTimeField extends Field { - public function getDynamoDbType(): string + public function dynamoDbType(): string { // Dates are stored as strings return 'S'; diff --git a/src/Field/Field.php b/src/Field/Field.php index e3dba9b..2e41d00 100644 --- a/src/Field/Field.php +++ b/src/Field/Field.php @@ -22,7 +22,7 @@ public function name(): string */ public function readFieldValue(array $item, string $fieldName) { - $rawDynamoDbValue = $item[$fieldName][$this->getDynamoDbType()]; + $rawDynamoDbValue = $item[$fieldName][$this->dynamoDbType()]; return $this->castValueFromDynamoDbFormat($rawDynamoDbValue); } @@ -33,11 +33,11 @@ public function readFieldValue(array $item, string $fieldName) public function dynamoDbQueryValue($fieldValue): array { return [ - $this->getDynamoDbType() => $this->castValueForDynamoDbFormat($fieldValue), + $this->dynamoDbType() => $this->castValueForDynamoDbFormat($fieldValue), ]; } - abstract protected function getDynamoDbType(): string; + abstract protected function dynamoDbType(): string; /** * @param mixed $value diff --git a/src/Field/FloatField.php b/src/Field/FloatField.php index 1387b11..daa0c63 100644 --- a/src/Field/FloatField.php +++ b/src/Field/FloatField.php @@ -4,7 +4,7 @@ class FloatField extends Field { - public function getDynamoDbType(): string + public function dynamoDbType(): string { return 'N'; } diff --git a/src/Field/IntegerField.php b/src/Field/IntegerField.php index 34df92b..c847585 100644 --- a/src/Field/IntegerField.php +++ b/src/Field/IntegerField.php @@ -4,7 +4,7 @@ class IntegerField extends Field { - public function getDynamoDbType(): string + public function dynamoDbType(): string { return 'N'; } diff --git a/src/Field/StringField.php b/src/Field/StringField.php index 398754c..6ac1b19 100644 --- a/src/Field/StringField.php +++ b/src/Field/StringField.php @@ -4,7 +4,7 @@ class StringField extends Field { - public function getDynamoDbType(): string + public function dynamoDbType(): string { return 'S'; } diff --git a/src/Mapping/ClassMapping.php b/src/Mapping/ClassMapping.php index 8dc6e43..aa38f91 100644 --- a/src/Mapping/ClassMapping.php +++ b/src/Mapping/ClassMapping.php @@ -2,8 +2,11 @@ namespace Dynamap\Mapping; +use Dynamap\Mapping\Field\DynamoDBField; use Dynamap\Mapping\Exception\CannotMapNonExistentFieldException; use Dynamap\Mapping\Exception\ClassNameInvalidException; +use Dynamap\Mapping\Exception\MappingNotFoundException; +use Dynamap\Mapping\Exception\NoFieldsMappedForClassException; class ClassMapping { @@ -33,8 +36,28 @@ public static function fromArray(string $className, array $config): ClassMapping return new static($className, $config); } + public function getClassName(): string + { + return $this->className; + } + + public function getMappedProperty(string $propertyName): DynamoDBField + { + if (true === empty($this->mapping['fields'])) { // todo: add a test for this + throw new NoFieldsMappedForClassException('You have tried to access mapping for a class which has no mapped properties'); + } + + if (false === \array_key_exists($propertyName, $this->mapping['fields'])) { + throw new MappingNotFoundException('Mapping for ' . $propertyName . ' could not be found'); + } + + return $this->mapping['fields'][$propertyName]; + } + /** + * @param string $className * @param array $fields + * @return array * @throws CannotMapNonExistentFieldException * @throws \ReflectionException */ @@ -48,16 +71,16 @@ private static function mapProperties(string $className, array $fields): array }, []); $mappedFields = []; + $factory = new FieldMappingFactory(); + foreach ($fields as $classField => $type) { - if (\in_array($classField, $classProperties) === false) { + if (false === \in_array($classField, $classProperties, false)) { throw new CannotMapNonExistentFieldException('The field ' . $classField . ' does not exist in ' . $className); } - $mappedFields[$classField] = $factory->getType($type); + $mappedFields[$classField] = $factory->getDynamoDbType($type); } - - - return $fields; + return $mappedFields; } } diff --git a/src/Mapping/Exception/MappingNotFoundException.php b/src/Mapping/Exception/MappingNotFoundException.php new file mode 100644 index 0000000..617a79e --- /dev/null +++ b/src/Mapping/Exception/MappingNotFoundException.php @@ -0,0 +1,7 @@ +mapping = $mapping; } public static function fromConfigArray(array $config) @@ -27,4 +28,21 @@ public static function fromConfigArray(array $config) return new static($mapping); } + + public function getTableFor(string $className): string + { + // todo: add a test for this + if (false === \class_exists($className)) { + throw new ClassNameInvalidException('Get table for ' . $className . ' as the class was not found'); + } + + foreach ($this->mapping as $mappedTable) { + if ($mappedTable->containsMappingForClass($className)) { + return $mappedTable->getTableName(); + } + } + + // todo: add a test for this + throw new ClassNotMappedException('The class ' . $className . ' was not found in the mapping configuration'); + } } diff --git a/src/Mapping/TableMapping.php b/src/Mapping/TableMapping.php index ee86efc..759d410 100644 --- a/src/Mapping/TableMapping.php +++ b/src/Mapping/TableMapping.php @@ -42,4 +42,16 @@ public function getTableName(): string { return $this->tableName; } + + // todo: add a test for this method + public function containsMappingForClass(string $className): bool + { + foreach ($this->classMappings as $classMapping) { + if ($className === $classMapping->getClassName()) { + return true; + } + } + + return false; + } } diff --git a/tests/Fixture/Tag.php b/tests/Fixture/Tag.php new file mode 100644 index 0000000..6c6cbae --- /dev/null +++ b/tests/Fixture/Tag.php @@ -0,0 +1,8 @@ + 'datetime', 'rating' => 'float', 'numComments' => 'integer', + 'published' => 'bool' ], ]; $classMapping = ClassMapping::fromArray(Article::class, $mapping); - $this->assertSame('S', $classMapping->getMappedProperty('id')->getDynamoDBType()); - $this->assertSame('S', $classMapping->getMappedProperty('name')->getDynamoDBType()); - $this->assertSame('S', $classMapping->getMappedProperty('createdAt')->getDynamoDBType()); - $this->assertSame('N', $classMapping->getMappedProperty('rating')->getDynamoDBType()); - $this->assertSame('N', $classMapping->getMappedProperty('numComments')->getDynamoDBType()); + $this->assertSame('S', $classMapping->getMappedProperty('id')->getDynamoDBFieldType()); + $this->assertSame('S', $classMapping->getMappedProperty('name')->getDynamoDBFieldType()); + $this->assertSame('S', $classMapping->getMappedProperty('createdAt')->getDynamoDBFieldType()); + $this->assertSame('N', $classMapping->getMappedProperty('rating')->getDynamoDBFieldType()); + $this->assertSame('N', $classMapping->getMappedProperty('numComments')->getDynamoDBFieldType()); + $this->assertSame('BOOL', $classMapping->getMappedProperty('published')->getDynamoDBFieldType()); } } diff --git a/tests/Mapping/MappingTest.php b/tests/Mapping/MappingTest.php index 600f82b..ae5c3ce 100644 --- a/tests/Mapping/MappingTest.php +++ b/tests/Mapping/MappingTest.php @@ -6,6 +6,7 @@ use Dynamap\Mapping\Mapping; use Dynamap\Test\Fixture\Article; use Dynamap\Test\Fixture\Author; +use Dynamap\Test\Fixture\Tag; use PHPUnit\Framework\TestCase; class MappingTest extends TestCase @@ -35,9 +36,19 @@ public function test a table mapping is created(): void Author::class => [], ], ], + [ + // if you're thinking about using mulitple tables, go back and read the AWS docs on why you shouldn't. + // then (and only then) come back and think about if you actually _really_ do want to do this. + 'name' => 'other_table', + 'mappings' => [ + Tag::class => [] + ] + ] ], ]); -// $this->assertSame('my_table', $mapping->getTableFor(Article::class)); + $this->assertSame('my_table', $mapping->getTableFor(Article::class)); + $this->assertSame('my_table', $mapping->getTableFor(Author::class)); + $this->assertSame('other_table', $mapping->getTableFor(Tag::class)); } }