Skip to content

Commit

Permalink
add TransformTo extension
Browse files Browse the repository at this point in the history
  • Loading branch information
dennis84 committed Jan 27, 2015
1 parent 4b479bc commit 8951a8e
Show file tree
Hide file tree
Showing 6 changed files with 230 additions and 6 deletions.
7 changes: 3 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -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)
Expand All @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
@@ -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": [
{
Expand Down
90 changes: 90 additions & 0 deletions src/Extension/TransformTo.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
<?php

namespace Mapped\Extension;

use Mapped\ExtensionInterface;
use Mapped\Transformer\Callback;
use Mapped\Mapping;

/**
* TransformTo.
*/
class TransformTo implements ExtensionInterface
{
/**
* Transforms the data to given class via setter and getter methods.
*
* @param Mapping $mapping The mapping object
* @param string|object $object The class name or an object
*
* @return Mapping
*/
public function transformTo(Mapping $mapping, $object)
{
$mapping->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();
}
}
}
9 changes: 8 additions & 1 deletion src/Transformer/Callback.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

/**
Expand Down Expand Up @@ -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];
}
Expand Down
94 changes: 94 additions & 0 deletions tests/Extension/TransformToTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<?php

namespace Mapped\Tests\Extension;

use Mapped\Factory;
use Mapped\Tests\Fixtures\User;
use Mapped\Tests\Fixtures\Book;

class TransformToTest extends \PHPUnit_Framework_TestCase
{
public function testA()
{
$factory = new Factory([new \Mapped\Extension\TransformTo]);

$mapping = $factory->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);
}
}
34 changes: 34 additions & 0 deletions tests/Fixtures/Book.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

namespace Mapped\Tests\Fixtures;

class Book
{
private $title;
private $author;

public function __construct()
{
$this->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;
}
}

0 comments on commit 8951a8e

Please sign in to comment.