From 8951a8ef7b9922e41801cc2bdb7719ebc496503b Mon Sep 17 00:00:00 2001 From: dennis84 Date: Tue, 27 Jan 2015 18:45:34 +0000 Subject: [PATCH] add `TransformTo` extension --- README.md | 7 +-- composer.json | 2 +- src/Extension/TransformTo.php | 90 +++++++++++++++++++++++++++ src/Transformer/Callback.php | 9 ++- tests/Extension/TransformToTest.php | 94 +++++++++++++++++++++++++++++ tests/Fixtures/Book.php | 34 +++++++++++ 6 files changed, 230 insertions(+), 6 deletions(-) create mode 100644 src/Extension/TransformTo.php create mode 100644 tests/Extension/TransformToTest.php create mode 100644 tests/Fixtures/Book.php diff --git a/README.md b/README.md index 9dff1ee..63c160d 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ # Mapped -Mapped is a lightweight data transformation and validation tool. You can use it -for JSON (de)serialization, form handling and many more. +A lightweight data transformation and validation tool for PHP. [![Build Status](https://travis-ci.org/dennis84/mapped.svg?branch=master)](https://travis-ci.org/dennis84/mapped) [![Coverage Status](https://coveralls.io/repos/dennis84/mapped/badge.png?branch=master)](https://coveralls.io/r/dennis84/mapped?branch=master) @@ -14,8 +13,8 @@ for JSON (de)serialization, form handling and many more. $factory = new Factory; $mapping = $factory->mapping([ - 'username' => $factory->mapping(), - 'password' => $factory->mapping(), + 'username' => $factory->string(), + 'password' => $factory->string(), ], function ($username, $password) { return new User($username, $password); }, function (User $user) { diff --git a/composer.json b/composer.json index ba4abec..b00a36f 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name": "dennis84/mapped", - "description": "Mapped is a lightweight data transformation and validation tool.", + "description": "A lightweight data transformation and validation tool.", "license": "MIT", "authors": [ { diff --git a/src/Extension/TransformTo.php b/src/Extension/TransformTo.php new file mode 100644 index 0000000..7b8f526 --- /dev/null +++ b/src/Extension/TransformTo.php @@ -0,0 +1,90 @@ +transform(new Callback(function ($data) use ($object, $mapping) { + if (is_string($object)) { + $object = new $object; + } + + foreach ($mapping->getChildren() as $name => $child) { + if (array_key_exists($name, $data) && null !== $data[$name]) { + $this->setValue($object, $name, $data[$name]); + } + } + + return $object; + }, function ($data) use ($object, $mapping) { + if (!$data instanceof $object) { + return; + } + + $result = []; + foreach ($mapping->getChildren() as $name => $child) { + $result[$name] = $this->getValue($data, $name); + } + + return $result; + }, false)); + + return $mapping; + } + + /** + * Sets the given value into the object. + * + * @param object $object The object + * @param string $name The property name + * @param mixed $value The value + */ + private function setValue($object, $name, $value) + { + if (isset($object->$name)) { + $object->$name = $value; + } + + $setter = 'set' . ucfirst($name); + if (method_exists($object, $setter)) { + return $object->$setter($value); + } + } + + /** + * Gets a value from given object. + * + * @param object $object The object + * @param string $name The property name + * + * @return mixed + */ + private function getValue($object, $name) + { + if (isset($object->$name)) { + return $object->$name; + } + + $getter = 'get' . ucfirst($name); + if (method_exists($object, $getter)) { + return $object->$getter(); + } + } +} diff --git a/src/Transformer/Callback.php b/src/Transformer/Callback.php index a89f09b..32dc6b7 100644 --- a/src/Transformer/Callback.php +++ b/src/Transformer/Callback.php @@ -11,17 +11,20 @@ class Callback extends Transformer { protected $transform; protected $reverseTransform; + protected $expand = true; /** * Constructor. * * @param callable $transform The tranform callback * @param callable $reverseTransform The reverse tranform callback + * @param bool $expand Expands the arguments if true */ - public function __construct(callable $transform = null, callable $reverseTransform = null) + public function __construct(callable $transform = null, callable $reverseTransform = null, $expand = true) { $this->transform = $transform; $this->reverseTransform = $reverseTransform; + $this->expand = $expand; } /** @@ -54,6 +57,10 @@ private function doTransform($data, callable $func = null) return $data; } + if (false === $this->expand) { + return call_user_func($func, $data); + } + if (!is_array($data)) { $data = [$data]; } diff --git a/tests/Extension/TransformToTest.php b/tests/Extension/TransformToTest.php new file mode 100644 index 0000000..a8b1a0a --- /dev/null +++ b/tests/Extension/TransformToTest.php @@ -0,0 +1,94 @@ +mapping([ + 'title' => $factory->string(), + 'author' => $factory->string(), + ])->transformTo('Mapped\Tests\Fixtures\Book'); + + $book = $mapping->apply([ + 'title' => 'LOTR', + 'author' => 'J.R.R. Tolkien', + ]); + + $this->assertInstanceOf('Mapped\Tests\Fixtures\Book', $book); + $data = $mapping->unapply($book); + + $this->assertEquals([ + 'title' => 'LOTR', + 'author' => 'J.R.R. Tolkien', + ], $data); + } + + public function testB() + { + $factory = new Factory([new \Mapped\Extension\TransformTo]); + + $mapping = $factory->mapping([ + 'title' => $factory->string(), + 'author' => $factory->string()->optional(), + ])->transformTo('Mapped\Tests\Fixtures\Book'); + + $book = $mapping->apply([ + 'title' => 'LOTR', + ]); + + $this->assertSame('N/A', $book->getAuthor()); + } + + public function testC() + { + $factory = new Factory([new \Mapped\Extension\TransformTo]); + + $book = new Book; + $mapping = $factory->mapping([ + 'title' => $factory->string(), + 'author' => $factory->string(), + ])->transformTo($book); + + $mapping->apply([ + 'title' => 'a', + 'author' => 'b', + ]); + + $this->assertSame('a', $book->getTitle()); + $this->assertSame('b', $book->getAuthor()); + } + + public function testD() + { + $factory = new Factory([new \Mapped\Extension\TransformTo]); + $user = new User('a', 'b'); + + $mapping = $factory->mapping([ + 'username' => $factory->string(), + 'password' => $factory->string(), + ])->transformTo($user); + + $user = $mapping->apply([ + 'username' => 'dennis', + 'password' => 'passwd', + ]); + + $this->assertSame('dennis', $user->username); + $this->assertSame('passwd', $user->password); + + $data = $mapping->unapply($user); + + $this->assertEquals([ + 'username' => 'dennis', + 'password' => 'passwd', + ], $data); + } +} diff --git a/tests/Fixtures/Book.php b/tests/Fixtures/Book.php new file mode 100644 index 0000000..82938c5 --- /dev/null +++ b/tests/Fixtures/Book.php @@ -0,0 +1,34 @@ +author = 'N/A'; + } + + public function setTitle($title) + { + $this->title = $title; + } + + public function getTitle() + { + return $this->title; + } + + public function setAuthor($author) + { + $this->author = $author; + } + + public function getAuthor() + { + return $this->author; + } +}