Skip to content
This repository was archived by the owner on Apr 30, 2019. It is now read-only.

Commit cb8249d

Browse files
committed
Init project
1 parent bf49fb4 commit cb8249d

12 files changed

Lines changed: 868 additions & 0 deletions
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the "elao/form-simple-object-mapper" package.
5+
*
6+
* Copyright (C) 2016 Elao
7+
*
8+
* @author Elao <contact@elao.com>
9+
*/
10+
11+
namespace Elao\FormSimpleObjectMapper\DataMapper;
12+
13+
/**
14+
* @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
15+
*/
16+
class CallbackFormDataToObjectConverter implements FormDataToObjectConverterInterface
17+
{
18+
/**
19+
* The callable used to map form data to an object.
20+
*
21+
* @var callable
22+
*/
23+
private $converter;
24+
25+
/**
26+
* @param callable $converter
27+
*/
28+
public function __construct(callable $converter)
29+
{
30+
$this->converter = $converter;
31+
}
32+
33+
/**
34+
* {@inheritdoc}
35+
*/
36+
public function convertFormDataToObject(array $data, $originalData)
37+
{
38+
return call_user_func($this->converter, $data, $originalData);
39+
}
40+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the "elao/form-simple-object-mapper" package.
5+
*
6+
* Copyright (C) 2016 Elao
7+
*
8+
* @author Elao <contact@elao.com>
9+
*/
10+
11+
namespace Elao\FormSimpleObjectMapper\DataMapper;
12+
13+
/**
14+
* @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
15+
*/
16+
interface FormDataToObjectConverterInterface
17+
{
18+
/**
19+
* Convert the form data into an object.
20+
*
21+
* @param array $data Array of form data indexed by fields names
22+
* @param object|null $originalData Original data set in the form (after FormEvents::PRE_SET_DATA)
23+
*
24+
* @return object|null
25+
*/
26+
public function convertFormDataToObject(array $data, $originalData);
27+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the "elao/form-simple-object-mapper" package.
5+
*
6+
* Copyright (C) 2016 Elao
7+
*
8+
* @author Elao <contact@elao.com>
9+
*/
10+
11+
namespace Elao\FormSimpleObjectMapper\DataMapper;
12+
13+
/**
14+
* @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
15+
*/
16+
interface ObjectToFormDataConverterInterface
17+
{
18+
/**
19+
* Convert given object to form data.
20+
*
21+
* @param object|null $object The object to map to the form
22+
*
23+
* @return array The array of form data indexed by fields names
24+
*/
25+
public function convertObjectToFormData($object);
26+
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the "elao/form-simple-object-mapper" package.
5+
*
6+
* Copyright (C) 2016 Elao
7+
*
8+
* @author Elao <contact@elao.com>
9+
*/
10+
11+
namespace Elao\FormSimpleObjectMapper\DataMapper;
12+
13+
use Symfony\Component\Form\DataMapperInterface;
14+
use Symfony\Component\Form\Exception\UnexpectedTypeException;
15+
use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper;
16+
17+
/**
18+
* @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
19+
*/
20+
class SimpleObjectMapper implements DataMapperInterface
21+
{
22+
/** @var FormDataToObjectConverterInterface */
23+
private $converter;
24+
25+
/** @var DataMapperInterface|null */
26+
private $originalMapper;
27+
28+
public function __construct(
29+
FormDataToObjectConverterInterface $converter,
30+
DataMapperInterface $originalMapper = null
31+
) {
32+
$this->converter = $converter;
33+
$this->originalMapper = $originalMapper;
34+
}
35+
36+
/**
37+
* {@inheritdoc}
38+
*/
39+
public function mapDataToForms($data, $forms)
40+
{
41+
// Fallback to original mapper instance or default to "PropertyPathMapper"
42+
// mapper implementation if not an "ObjectToFormDataConverterInterface" instance:
43+
if (!$this->converter instanceof ObjectToFormDataConverterInterface) {
44+
$propertyPathMapper = $this->originalMapper ?: new PropertyPathMapper();
45+
$propertyPathMapper->mapDataToForms($data, $forms);
46+
47+
return;
48+
}
49+
50+
$data = $this->convertObjectToFormData($this->converter, $data);
51+
52+
foreach ($forms as $form) {
53+
$config = $form->getConfig();
54+
55+
if ($config->getMapped() && isset($data[$form->getName()])) {
56+
$form->setData($data[$form->getName()]);
57+
58+
continue;
59+
}
60+
61+
$form->setData($config->getData());
62+
}
63+
}
64+
65+
/**
66+
* {@inheritdoc}
67+
*/
68+
public function mapFormsToData($forms, &$data)
69+
{
70+
$fieldsData = [];
71+
foreach ($forms as $form) {
72+
$fieldsData[$form->getName()] = $form->getData();
73+
}
74+
75+
$data = $this->converter->convertFormDataToObject($fieldsData, $data);
76+
}
77+
78+
private function convertObjectToFormData(ObjectToFormDataConverterInterface $converter, $data)
79+
{
80+
if (!is_object($data) && null !== $data) {
81+
throw new UnexpectedTypeException($data, 'object or null');
82+
}
83+
84+
$data = $converter->convertObjectToFormData($data);
85+
86+
if (!is_array($data)) {
87+
throw new UnexpectedTypeException($data, 'array');
88+
}
89+
90+
return $data;
91+
}
92+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the "elao/form-simple-object-mapper" package.
5+
*
6+
* Copyright (C) 2016 Elao
7+
*
8+
* @author Elao <contact@elao.com>
9+
*/
10+
11+
namespace Elao\FormSimpleObjectMapper\Type\Extension;
12+
13+
use Elao\FormSimpleObjectMapper\DataMapper\CallbackFormDataToObjectConverter;
14+
use Elao\FormSimpleObjectMapper\DataMapper\FormDataToObjectConverterInterface;
15+
use Elao\FormSimpleObjectMapper\DataMapper\SimpleObjectMapper;
16+
use Symfony\Component\Form\AbstractTypeExtension;
17+
use Symfony\Component\Form\Extension\Core\Type\FormType;
18+
use Symfony\Component\Form\FormBuilderInterface;
19+
use Symfony\Component\OptionsResolver\Options;
20+
use Symfony\Component\OptionsResolver\OptionsResolver;
21+
22+
/**
23+
* Type extension easing the value objects manipulation with form types.
24+
* It internally sets a dedicated data mapper using the normalizer provided in a "value_object_normalizer" form option.
25+
*
26+
* @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
27+
*/
28+
class SimpleObjectMapperTypeExtension extends AbstractTypeExtension
29+
{
30+
const MAPPER_OPTION = 'simple_object_mapper';
31+
32+
/**
33+
* {@inheritdoc}
34+
*/
35+
public function buildForm(FormBuilderInterface $builder, array $options)
36+
{
37+
if (false === $options['compound']) {
38+
return;
39+
}
40+
41+
if (!isset($options[static::MAPPER_OPTION])) {
42+
return;
43+
}
44+
45+
$converter = $options[static::MAPPER_OPTION];
46+
47+
$valueObjectDataMapper = new SimpleObjectMapper($converter, $builder->getDataMapper());
48+
49+
$builder->setDataMapper($valueObjectDataMapper);
50+
}
51+
52+
public function configureOptions(OptionsResolver $resolver)
53+
{
54+
$simpleObjectMapperNormalizer = function (Options $options, $value) {
55+
if (null === $value) {
56+
return null;
57+
}
58+
59+
if (!$value instanceof FormDataToObjectConverterInterface && is_callable($value)) {
60+
return new CallbackFormDataToObjectConverter($value);
61+
}
62+
63+
return $value;
64+
};
65+
66+
$emptyData = function (Options $options, $value) {
67+
if (isset($options[static::MAPPER_OPTION])) {
68+
return null; // `empty_data` should be set to `null` when using the `simple_object_mapper` option.
69+
}
70+
71+
return $value;
72+
};
73+
74+
$resolver
75+
->setDefined(static::MAPPER_OPTION)
76+
->setDefault('empty_data', $emptyData)
77+
->setAllowedTypes(static::MAPPER_OPTION, [FormDataToObjectConverterInterface::class, 'null', 'callable'])
78+
->setNormalizer(static::MAPPER_OPTION, $simpleObjectMapperNormalizer)
79+
;
80+
}
81+
82+
/**
83+
* {@inheritdoc}
84+
*/
85+
public function getExtendedType()
86+
{
87+
return FormType::class;
88+
}
89+
}

tests/Fixtures/Money.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the "elao/form-simple-object-mapper" package.
5+
*
6+
* Copyright (C) 2016 Elao
7+
*
8+
* @author Elao <contact@elao.com>
9+
*/
10+
11+
namespace Elao\FormSimpleObjectMapper\Tests\Fixtures;
12+
13+
class Money
14+
{
15+
/** @var float */
16+
private $amount;
17+
18+
/** @var string */
19+
private $currency;
20+
21+
public function __construct($amount, $currency)
22+
{
23+
$this->amount = $amount;
24+
$this->currency = $currency;
25+
}
26+
27+
public function getAmount()
28+
{
29+
return $this->amount;
30+
}
31+
32+
public function getCurrency()
33+
{
34+
return $this->currency;
35+
}
36+
}

tests/Fixtures/MoneyType.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the "elao/form-simple-object-mapper" package.
5+
*
6+
* Copyright (C) 2016 Elao
7+
*
8+
* @author Elao <contact@elao.com>
9+
*/
10+
11+
namespace Elao\FormSimpleObjectMapper\Tests\Fixtures;
12+
13+
use Symfony\Component\Form\AbstractType;
14+
use Symfony\Component\Form\Extension\Core\Type\NumberType;
15+
use Symfony\Component\Form\FormBuilderInterface;
16+
use Symfony\Component\OptionsResolver\OptionsResolver;
17+
18+
class MoneyType extends AbstractType
19+
{
20+
public function buildForm(FormBuilderInterface $builder, array $options)
21+
{
22+
$builder
23+
->add('amount', NumberType::class)
24+
->add('currency')
25+
;
26+
}
27+
28+
public function configureOptions(OptionsResolver $resolver)
29+
{
30+
$resolver->setDefaults([
31+
'data_class' => Money::class,
32+
'simple_object_mapper' => new MoneyTypeConverter(),
33+
]);
34+
}
35+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the "elao/form-simple-object-mapper" package.
5+
*
6+
* Copyright (C) 2016 Elao
7+
*
8+
* @author Elao <contact@elao.com>
9+
*/
10+
11+
namespace Elao\FormSimpleObjectMapper\Tests\Fixtures;
12+
13+
use Elao\FormSimpleObjectMapper\DataMapper\FormDataToObjectConverterInterface;
14+
15+
class MoneyTypeConverter implements FormDataToObjectConverterInterface
16+
{
17+
/**
18+
* {@inheritdoc}
19+
*
20+
* @param Money|null $originalData
21+
*/
22+
public function convertFormDataToObject(array $data, $originalData)
23+
{
24+
// Logic to determine if the result should be considered null according to form fields data.
25+
if (null === $data['amount'] && null === $data['currency']) {
26+
return;
27+
}
28+
29+
return new Money($data['amount'], $data['currency']);
30+
}
31+
}

0 commit comments

Comments
 (0)