DX: Create a RollingDate data transfer object and Form type

This commit is contained in:
Julien Fastré 2022-11-07 14:06:47 +01:00
parent 6fd75a175f
commit 5489178e4b
5 changed files with 268 additions and 0 deletions

View File

@ -0,0 +1,45 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\MainBundle\Form\DataMapper;
use Chill\MainBundle\Service\RollingDate\RollingDate;
use Symfony\Component\Form\DataMapperInterface;
use Symfony\Component\Form\Exception;
class RollingDateDataMapper implements DataMapperInterface
{
public function mapDataToForms($viewData, $forms)
{
if (null === $viewData) {
return;
}
if (!$viewData instanceof RollingDate) {
throw new Exception\UnexpectedTypeException($viewData, RollingDate::class);
}
$forms = iterator_to_array($forms);
$forms['roll']->setData($viewData->getRoll());
$forms['fixedDate']->setData($viewData->getFixedDate());
}
public function mapFormsToData($forms, &$viewData): void
{
$forms = iterator_to_array($forms);
$viewData = new RollingDate(
$forms['roll']->getData(),
$forms['fixedDate']->getData()
);
}
}

View File

@ -0,0 +1,50 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\MainBundle\Form\Type;
use Chill\MainBundle\Form\DataMapper\RollingDateDataMapper;
use Chill\MainBundle\Service\RollingDate\RollingDate;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class PickRollingDateType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('roll', ChoiceType::class, [
'choices' => array_combine(
array_map(static fn (string $item) => 'rolling_date.' . $item, RollingDate::ALL_T),
RollingDate::ALL_T
),
'multiple' => false,
'expanded' => false,
'label' => 'rolling_date.roll_movement',
])
->add('fixedDate', ChillDateType::class, [
'input' => 'datetime_immutable',
'label' => 'rolling_date.fixed_date_date',
]);
$builder->setDataMapper(new RollingDateDataMapper());
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'class' => RollingDate::class,
'empty_data' => new RollingDate(RollingDate::T_TODAY),
]);
}
}

View File

@ -0,0 +1,101 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\MainBundle\Service\RollingDate;
use DateTimeImmutable;
class RollingDate
{
public const ALL_T = [
self::T_YEAR_PREVIOUS_START,
self::T_QUARTER_PREVIOUS_START,
self::T_MONTH_PREVIOUS_START,
self::T_WEEK_PREVIOUS_START,
self::T_YEAR_CURRENT_START,
self::T_QUARTER_CURRENT_START,
self::T_MONTH_CURRENT_START,
self::T_WEEK_CURRENT_START,
self::T_TODAY,
self::T_WEEK_NEXT_START,
self::T_MONTH_NEXT_START,
self::T_QUARTER_NEXT_START,
self::T_YEAR_NEXT_START,
self::T_FIXED_DATE,
];
/**
* A given fixed date.
*/
public const T_FIXED_DATE = 'fixed_date';
public const T_MONTH_CURRENT_START = 'month_current_start';
public const T_MONTH_NEXT_START = 'month_next_start';
public const T_MONTH_PREVIOUS_START = 'month_previous_start';
public const T_QUARTER_CURRENT_START = 'quarter_current_start';
public const T_QUARTER_NEXT_START = 'quarter_next_start';
public const T_QUARTER_PREVIOUS_START = 'quarter_previous_start';
public const T_TODAY = 'today';
public const T_WEEK_CURRENT_START = 'week_current_start';
public const T_WEEK_NEXT_START = 'week_next_start';
public const T_WEEK_PREVIOUS_START = 'week_previous_start';
public const T_YEAR_CURRENT_START = 'year_current_start';
public const T_YEAR_NEXT_START = 'year_next_start';
public const T_YEAR_PREVIOUS_START = 'year_previous_start';
private ?DateTimeImmutable $fixedDate;
/**
* The pivot date is the date from the rolling is computed. By default, it is "now".
*/
private DateTimeImmutable $pivotDate;
private string $roll;
/**
* @param string|self::T_* $roll
* @param DateTimeImmutable|null $pivotDate Will be "now" if null is given
* @param DateTimeImmutable|null $fixedDate Only to insert if $roll equals @see{self::T_FIXED_DATE}
*/
public function __construct(string $roll, ?DateTimeImmutable $pivotDate = null, ?DateTimeImmutable $fixedDate = null)
{
$this->roll = $roll;
$this->pivotDate = $pivotDate ?? new DateTimeImmutable('now');
$this->fixedDate = $fixedDate;
}
public function getFixedDate(): DateTimeImmutable
{
return $this->fixedDate;
}
public function getPivotDate(): ?DateTimeImmutable
{
return $this->pivotDate;
}
public function getRoll(): string
{
return $this->roll;
}
}

View File

@ -0,0 +1,53 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Form\Type;
use Chill\MainBundle\Form\Type\PickRollingDateType;
use Chill\MainBundle\Service\RollingDate\RollingDate;
use Symfony\Component\Form\PreloadedExtension;
use Symfony\Component\Form\Test\TypeTestCase;
/**
* @internal
* @coversNothing
*/
final class PickRollingDateTypeTest extends TypeTestCase
{
public function testSubmitValidData()
{
$formData = [
'roll' => 'year_previous_start',
'fixedDate' => null,
];
$form = $this->factory->create(PickRollingDateType::class);
$form->submit($formData);
$this->assertTrue($form->isSynchronized());
/** @var RollingDate $rollingDate */
$rollingDate = $form->getData();
$this->assertInstanceOf(RollingDate::class, $rollingDate);
$this->assertEquals(RollingDate::T_YEAR_PREVIOUS_START, $rollingDate->getRoll());
}
protected function getExtensions(): array
{
$type = new PickRollingDateType();
return [
new PreloadedExtension([$type], []),
];
}
}

View File

@ -538,3 +538,22 @@ export:
isNoAddress: Adresse incomplète ?
_lat: Latitude
_lon: Longitude
rolling_date:
year_previous_start: Début de l'année précédente
quarter_previous_start: Début du trimestre précédent
month_previous_start: Début du mois précédent
week_previous_start: Début de la semaine précédente
year_current_start: Début de l'année courante
quarter_current_start: Début du trimestre courant
month_current_start: Début du mois courant
week_current_start: Début de la semaine courante
today: Aujourd'hui (aucune modification de la date courante)
year_next_start: Début de l'année suivante
quarter_next_start: Début du trimestre suivante
month_next_start: Début du mois suivant
week_next_start: Début de la semaine suivante
fixed_date: Date fixe
roll_movement: Modification par rapport à aujourd'hui
fixed_date_date: Date fixe