From c07d025f0df662789a78b1b3bcfda5a41638f0e0 Mon Sep 17 00:00:00 2001 From: Iain Mckay Date: Thu, 21 Apr 2016 11:34:11 +0200 Subject: [PATCH] Addition of a mapper which can cast properties to primitive types --- src/Annotation/Cast.php | 12 ++++ src/Mapper/CastingObjectMapper.php | 102 +++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 src/Annotation/Cast.php create mode 100644 src/Mapper/CastingObjectMapper.php diff --git a/src/Annotation/Cast.php b/src/Annotation/Cast.php new file mode 100644 index 0000000..3853f01 --- /dev/null +++ b/src/Annotation/Cast.php @@ -0,0 +1,12 @@ +propertyMapper = $propertyMapper; + $this->annotationReader = $annotationReader; + } + + public function map($from, $to) + { + $this->propertyMapper->map($from, $to); + + if (is_object($to)) { + $reflector = new \ReflectionClass($to); + + foreach ($reflector->getProperties() as $property) { + $annotation = $this->annotationReader->getPropertyAnnotation($property, Cast::class); + + if ($annotation !== null) { + $this->cast($to, $property->getName(), $annotation->to); + } + } + } + + return $to; + } + + protected function cast($obj, $propertyName, $type) + { + $value = $obj->{$propertyName}; + + if ($type === 'int') { + $type = 'integer'; + } else if ($type === 'bool') { + $type = 'boolean'; + } + + // don't try converting if the value is already of the target type + if (gettype($value) === $type) { + return; + } + + switch ($type) { + case 'integer': + $value = is_numeric($value) ? (int) $value : null; + break; + + case 'float': + $tmp = floatval($value); + $tmp2 = (float) $value; + $value = $tmp == $tmp2 ? $tmp2 : null; + break; + + case 'double': + $tmp = doubleval($value); + $tmp2 = (double) $value; + $value = $tmp == $tmp2 ? $tmp2 : null; + break; + + case 'boolean': + $tmp = boolval($value); + $tmp2 = (bool) $value; + $value = $tmp == $tmp2 ? $tmp2 : null; + break; + + case 'string': + $value = (string) $value; + break; + } + + $obj->{$propertyName} = $value; + } +}