Skip to content

Commit

Permalink
Merge pull request #34 from dantleech/form
Browse files Browse the repository at this point in the history
[WIP] Added PHPCRReferenceType
  • Loading branch information
dbu committed Feb 26, 2013
2 parents 7531758 + 479a634 commit 744d489
Show file tree
Hide file tree
Showing 8 changed files with 306 additions and 0 deletions.
55 changes: 55 additions & 0 deletions Form/DataTransformer/PHPCRNodeToPathTransformer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

namespace Doctrine\Bundle\PHPCRBundle\Form\DataTransformer;

use PHPCR\SessionInterface;
use PHPCR\NodeInterface;
use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\UnexpectedTypeException;

class PHPCRNodeToPathTransformer implements DataTransformerInterface
{
protected $session;

public function __construct(SessionInterface $session)
{
$this->session = $session;
}

/**
* Transform a node into a path
*
* @param PHPCR\NodeInterface
* @throws UnexpectedTypeException if given value is not a PHPCR\NodeInterface
* @return string|null
*/
public function transform($node)
{
if (null === $node) {
return null;
}

if (!$node instanceof NodeInterface) {
throw new UnexpectedTypeException($node, 'PHPCR\NodeInterface');
}
return $node->getPath();
}

/**
* Transform a path/uuid to its corresponding PHPCR node
*
* @param string $path/uuid
* @throws PHPCR\ItemNotFoundException if node not found
* @return PHPCR\NodeInterface|null
*/
public function reverseTransform($id)
{
if (!$id) {
return null;
}

$node = $this->session->getNodeByIdentifier($id);

return $node;
}
}
30 changes: 30 additions & 0 deletions Form/DataTransformer/PHPCRNodeToUuidTransformer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace Doctrine\Bundle\PHPCRBundle\Form\DataTransformer;

use PHPCR\SessionInterface;
use PHPCR\NodeInterface;
use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\UnexpectedTypeException;

class PHPCRNodeToUuidTransformer extends PHPCRNodeToPathTransformer
{
/**
* Transform a node into a path
*
* @param PHPCR\NodeInterface
* @throws UnexpectedTypeException if given value is not a PHPCR\NodeInterface
* @return string
*/
public function transform($node)
{
if (null === $node) {
return null;
}

if (!$node instanceof NodeInterface) {
throw new UnexpectedTypeException($node, 'PHPCR\NodeInterface');
}
return $node->getIdentifier();
}
}
65 changes: 65 additions & 0 deletions Form/Type/PHPCRReferenceType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

namespace Doctrine\Bundle\PHPCRBundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Doctrine\Bundle\PHPCRBundle\Form\DataTransformer\PHPCRNodeToPathTransformer;
use Doctrine\Bundle\PHPCRBundle\Form\DataTransformer\PHPCRNodeToUuidTransformer;
use PHPCR\SessionInterface;
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;

/**
* Form type for PHPCR Node references
*
* Can use either a UUID or a PATH transformer as specified by
* the "transfomer_type" option.
*
* @author Daniel Leech <daniel@dantleech.com>
*/
class PHPCRReferenceType extends AbstractType
{
private $session;

public function __construct(SessionInterface $session)
{
$this->session = $session;
}

public function buildForm(FormBuilderInterface $builder, array $options)
{
switch (strtolower($options['transformer_type'])) {
case 'uuid':
$transformer = new PHPCRNodeToUuidTransformer($this->session);
break;
case 'path':
$transformer = new PHPCRNodeToPathTransformer($this->session);
break;
default:
throw new InvalidConfigurationException(sprintf('
The option "transformer_type" must be either "uuid" or "path", "%s" given',
$options['transformer_type']
));
}

$builder->addModelTransformer($transformer);
}

public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'transformer_type' => 'uuid',
));
}

public function getParent()
{
return 'text';
}

public function getName()
{
return 'phpcr_reference';
}
}
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,16 @@ More information on the doctrine event system integration is in this [symfony co

The bundle provides a ``ValidPhpcrOdm`` constraint validator you can use to check if your document ``Id`` or ``Nodename`` and ``Parent`` fields are correct.

# Form types

The bundle will provide various form types for PHPCR and PHPCR-ODM specific cases.

## PHPCRReferenceType

Represent a PHPCR reference within a form. The input will be rendered as a text field
containing either the PATH or the UUID as per the configuration. The form will resolve
to a PHPCR node.

# Additional requirements for the doctrine:phpcr:fixtures:load command

To use the doctrine:phpcr:fixtures:load command, you additionally need the Doctrine
Expand Down
6 changes: 6 additions & 0 deletions Resources/config/phpcr.xml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@
</call>
</service>

<service id="form.type.phpcr.reference" class="Doctrine\Bundle\PHPCRBundle\Form\Type\PHPCRReferenceType">
<tag name="form.type" alias="phpcr_reference"/>
<argument type="service" id="doctrine_phpcr.session"/>
</service>


</services>

</container>
61 changes: 61 additions & 0 deletions Tests/Form/DataTransformer/PHPCRNodeToPathTransformerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php

namespace Doctrine\Bundle\PHPCRBundle\Tests\Form\DataTransformer;

use Doctrine\Bundle\PHPCRBundle\Form\DataTransformer\PHPCRNodeToPathTransformer;
use Jackalope\Node;

class PHPCRNodeToPathTransformerTest extends \PHPUnit_Framework_Testcase
{
public function setUp()
{
$this->session = $this->getMock('PHPCR\SessionInterface');
$this->transformer = new PHPCRNodeToPathTransformer($this->session);
$this->node = $this->getMockBuilder('Jackalope\Node')
->disableOriginalConstructor()
->getMock();
}

public function testTransform()
{
$this->node->expects($this->once())
->method('getPath')
->will($this->returnValue('/asd'));
$res = $this->transformer->transform($this->node);
$this->assertEquals('/asd', $res);
}

/**
* @expectedException Symfony\Component\Form\Exception\UnexpectedTypeException
*/
public function testTransformWrongType()
{
$res = $this->transformer->transform(new \stdClass);
}

public function testReverseTransform()
{
$this->session->expects($this->once())
->method('getNodeByIdentifier')
->with('/asd')
->will($this->returnValue($this->node));

$res = $this->transformer->reverseTransform('/asd');
$this->assertSame($this->node, $res);
}

public function testReverseTransformEmpty()
{
$this->session->expects($this->never())
->method('getNodeByIdentifier');
$res = $this->transformer->reverseTransform('');
$this->assertNull($res);

}

public function testReverseTransformNotFound()
{
// nothing to test, the PHPCR session will throw an
// ItemNotFoundException
}
}
24 changes: 24 additions & 0 deletions Tests/Form/DataTransformer/PHPCRNodeToUuidTransformerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace Doctrine\Bundle\PHPCRBundle\Tests\Form\DataTransformer;

use Doctrine\Bundle\PHPCRBundle\Form\DataTransformer\PHPCRNodeToUuidTransformer;
use Jackalope\Node;

class PHPCRNodeToUuidTransformerTest extends PHPCRNodeToPathTransformerTest
{
public function setUp()
{
parent::setUp();
$this->transformer = new PHPCRNodeToUuidTransformer($this->session);
}

public function testTransform()
{
$this->node->expects($this->once())
->method('getIdentifier')
->will($this->returnValue('/asd'));
$res = $this->transformer->transform($this->node);
$this->assertEquals('/asd', $res);
}
}
55 changes: 55 additions & 0 deletions Tests/Form/Type/PHPCRReferenceTypeTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

namespace Doctrine\Bundle\PHPCRBundle\Tests\Form\DataTransformer;

use Doctrine\Bundle\PHPCRBundle\Form\DataTransformer\PHPCRNodeToPathTransformer;
use Jackalope\Node;
use Doctrine\Bundle\PHPCRBundle\Form\Type\PHPCRReferenceType;

class PHPCRReferenceTypeTest extends \PHPUnit_Framework_Testcase
{
public function setUp()
{
$this->session = $this->getMock('PHPCR\SessionInterface');

// hmm, phpunit won't mock a traversable interface so mocking the concrete class
$this->builder = $this->getMockBuilder('Symfony\Component\Form\FormBuilder')
->disableOriginalConstructor()
->getMock();
$this->type = new PHPCRReferenceType($this->session);
}

public function provideTypes()
{
return array(
array('uuid', 'Doctrine\Bundle\PHPCRBundle\Form\DataTransformer\PHPCRNodeToUuidTransformer'),
array('path', 'Doctrine\Bundle\PHPCRBundle\Form\DataTransformer\PHPCRNodeToPathTransformer'),
);
}

/**
* @dataProvider provideTypes
*/
public function testBuildForm($transformerType, $transformerFqn)
{
$type = null;
$this->builder->expects($this->once())
->method('addModelTransformer')
->will($this->returnCallback(function ($transformer) use (&$type) {
$type = get_class($transformer);
return null;
}));
$this->type->buildForm($this->builder, array('transformer_type' => $transformerType));

$this->assertEquals($transformerFqn, $type);
}

/**
* @expectedException Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
*/
public function testInvalidType()
{
$this->type->buildForm($this->builder, array('transformer_type' => 'asdasd'));
}
}

0 comments on commit 744d489

Please sign in to comment.