Skip to content

Commit

Permalink
add Forms extension
Browse files Browse the repository at this point in the history
  • Loading branch information
dennis84 committed Feb 18, 2015
1 parent eed675f commit cf3632c
Show file tree
Hide file tree
Showing 4 changed files with 314 additions and 0 deletions.
158 changes: 158 additions & 0 deletions src/Extension/Form.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
<?php

namespace Mapped\Extension;

use Mapped\Mapping;
use Mapped\ValidationException;

/**
* Form.
*/
class Form implements \ArrayAccess
{
private $mapping;
private $children = [];
private $value;
private $data;
private $errors = [];

/**
* Constructor.
*
* @param Mapping $mapping The mapping object
* @param Form[] $children An array of form objects
*/
public function __construct(Mapping $mapping, array $children = [])
{
$this->mapping = $mapping;
$this->children = $children;
}

/**
* Binds the given data to the form.
*
* @param mixed $data The submitted data
*/
public function bind($data)
{
try {
$this->data = $this->mapping->apply($data);
} catch (ValidationException $e) {
$this->errors = $e->getErrors();
}
}

/**
* Fills the form.
*
* @param mixed $data The data
*/
public function fill($data)
{
$this->value = $this->mapping->unapply($data);
}

/**
* Returns true if this form is valid, otherwise false.
*
* @return bool
*/
public function isValid()
{
return 0 === count($this->errors);
}

/**
* Sets data.
*
* @param mixed $data Some data
*/
public function setData($data)
{
$this->data = $data;
}

/**
* Gets the data (the applied result).
*
* return mixed
*/
public function getData()
{
return $this->data;
}

/**
* Sets value.
*
* @param mixed $value Some value
*/
public function setValue($value)
{
$this->value = $value;
}

/**
* Gets the value (The unapplied result).
*
* @return mixed
*/
public function getValue()
{
return $this->value;
}

/**
* Sets errors.
*
* @param Error[] $errors An array of error objects
*/
public function setErrors(array $errors)
{
$this->errors = $errors;
}

/**
* Gets the errors.
*
* @return Error[]
*/
public function getErrors()
{
return $this->errors;
}

/**
* {@inheritdoc}
*/
public function offsetGet($offset)
{
if ($this->offsetExists($offset)) {
return $this->children[$offset];
}
}

/**
* {@inheritdoc}
*/
public function offsetExists($offset)
{
return isset($this->children[$offset]);
}

/**
* {@inheritdoc}
*/
public function offsetSet($offset, $value)
{
throw new \RuntimeException('Not implemented');
}

/**
* {@inheritdoc}
*/
public function offsetUnset($offset)
{
throw new \RuntimeException('Not implemented');
}
}
42 changes: 42 additions & 0 deletions src/Extension/Forms.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

namespace Mapped\Extension;

use Mapped\ExtensionInterface;
use Mapped\Mapping;
use Mapped\Events;

/**
* Forms.
*/
class Forms implements ExtensionInterface
{
/**
* Returns a form.
*
* @param Mapping $mapping The mapping object
*
* @return Form
*/
public function form(Mapping $mapping)
{
$children = array_map(function (Mapping $child) {
return $child->form();
}, $mapping->getChildren());

$form = new Form($mapping, $children);
$emitter = $mapping->getEmitter();

$emitter->on(Events::APPLIED, function ($data) use ($form) {
$form->setData($data->getResult());
$form->setValue($data->getInput());
$form->setErrors($data->getErrors());
});

$emitter->on(Events::UNAPPLIED, function ($data) use ($form) {
$form->setValue($data->getResult());
});

return $form;
}
}
47 changes: 47 additions & 0 deletions tests/Extension/FormTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

namespace Mapped\Tests\Extension;

use Mapped\Extension\Form;

class FormTest extends \PHPUnit_Framework_TestCase
{
public function testOffsetGetAndExists()
{
$mapping = $this->getMockBuilder('Mapped\Mapping')
->disableOriginalConstructor()
->getMock();

$form = new Form($mapping, [
'foo' => new Form($mapping),
'bar' => new Form($mapping),
]);

$this->assertNotNull($form['foo']);
$this->assertNull($form['baz']);
$this->assertTrue(isset($form['foo']));
$this->assertFalse(isset($form['baz']));
}

public function testOffsetSet()
{
$this->setExpectedException('RuntimeException');
$mapping = $this->getMockBuilder('Mapped\Mapping')
->disableOriginalConstructor()
->getMock();

$form = new Form($mapping);
$form['foo'] = $form;
}

public function testOffsetUnset()
{
$this->setExpectedException('RuntimeException');
$mapping = $this->getMockBuilder('Mapped\Mapping')
->disableOriginalConstructor()
->getMock();

$form = new Form($mapping);
unset($form['foo']);
}
}
67 changes: 67 additions & 0 deletions tests/Extension/FormsTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php

namespace Mapped\Tests\Extension;

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

class FormsTest extends \PHPUnit_Framework_TestCase
{
public function testA()
{
$factory = new Factory([new \Mapped\Extension\Forms]);
$mapping = $factory->mapping([
'username' => $factory->mapping(),
'password' => $factory->mapping(),
], function ($username, $password) {
return new User($username, $password);
}, function (User $user) {
return [
'username' => $user->username,
'password' => $user->password,
];
});

$form = $mapping->form();
$form->bind([
'username' => 'dennis',
'password' => 'passwd',
]);

$this->assertTrue($form->isValid());
$this->assertInstanceOf('Mapped\Tests\Fixtures\User', $form->getData());
$this->assertSame('dennis', $form['username']->getData());
$this->assertSame('passwd', $form['password']->getData());

$form->fill($form->getData());

$this->assertSame([
'username' => 'dennis',
'password' => 'passwd',
], $form->getValue());

$this->assertSame('dennis', $form['username']->getValue());
$this->assertSame('passwd', $form['password']->getValue());
}

public function testB()
{
$factory = new Factory([new \Mapped\Extension\Forms]);
$mapping = $factory->mapping([
'username' => $factory->mapping()->notEmpty(),
'password' => $factory->mapping(),
], function ($username, $password) {
return new User($username, $password);
});

$form = $mapping->form();
$form->bind(['username' => '']);

$this->assertFalse($form->isValid());
$this->assertCount(2, $form->getErrors());
$this->assertCount(1, $form['username']->getErrors());
$this->assertCount(1, $form['password']->getErrors());
$this->assertSame('error.not_empty', $form['username']->getErrors()[0]->getMessage());
$this->assertSame('error.required', $form['password']->getErrors()[0]->getMessage());
}
}

0 comments on commit cf3632c

Please sign in to comment.