Skip to content

Commit

Permalink
Add new Form WeekType
Browse files Browse the repository at this point in the history
  • Loading branch information
dFayet authored and xabbuh committed Oct 19, 2019
1 parent 594e7ae commit fea3d59
Show file tree
Hide file tree
Showing 10 changed files with 911 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,17 @@
{{ block('form_widget_simple') }}
{%- endblock color_widget -%}

{%- block week_widget -%}
{%- if widget == 'single_text' -%}
{{ block('form_widget_simple') }}
{%- else -%}
{%- set vars = widget == 'text' ? { 'attr': { 'size': 1 }} : {} -%}
<div {{ block('widget_container_attributes') }}>
{{ form_widget(form.year, vars) }}-{{ form_widget(form.week, vars) }}
</div>
{%- endif -%}
{%- endblock week_widget -%}

{# Labels #}

{%- block form_label -%}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

abstract class AbstractBootstrap3LayoutTest extends AbstractLayoutTest
{
protected static $supportedFeatureSetVersion = 403;
protected static $supportedFeatureSetVersion = 404;

public function testLabelOnForm()
{
Expand Down Expand Up @@ -2722,6 +2722,104 @@ public function testColor()
[@name="name"]
[@class="my&class form-control"]
[@value="#0000ff"]
'
);
}

public function testWeekSingleText()
{
$this->requiresFeatureSet(404);

$form = $this->factory->createNamed('holidays', 'Symfony\Component\Form\Extension\Core\Type\WeekType', '1970-W01', [
'input' => 'string',
'widget' => 'single_text',
]);

$this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']],
'/input
[@type="week"]
[@name="holidays"]
[@class="my&class form-control"]
[@value="1970-W01"]
[not(@maxlength)]
'
);
}

public function testWeekSingleTextNoHtml5()
{
$this->requiresFeatureSet(404);

$form = $this->factory->createNamed('holidays', 'Symfony\Component\Form\Extension\Core\Type\WeekType', '1970-W01', [
'input' => 'string',
'widget' => 'single_text',
'html5' => false,
]);

$this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']],
'/input
[@type="text"]
[@name="holidays"]
[@class="my&class form-control"]
[@value="1970-W01"]
[not(@maxlength)]
'
);
}

public function testWeekChoices()
{
$this->requiresFeatureSet(404);

$data = ['year' => date('Y'), 'week' => 1];

$form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\WeekType', $data, [
'input' => 'array',
'required' => false,
]);

$this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']],
'/div
[@class="my&class"]
[
./select
[@id="name_year"]
[@class="form-control"]
[./option[@value="'.$data['year'].'"][@selected="selected"]]
/following-sibling::select
[@id="name_week"]
[@class="form-control"]
[./option[@value="'.$data['week'].'"][@selected="selected"]]
]
[count(.//select)=2]'
);
}

public function testWeekText()
{
$this->requiresFeatureSet(404);

$form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\WeekType', '2000-W01', [
'input' => 'string',
'widget' => 'text',
]);

$this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']],
'/div
[@class="my&class"]
[
./input
[@id="name_year"]
[@type="number"]
[@class="form-control"]
[@value="2000"]
/following-sibling::input
[@id="name_week"]
[@type="number"]
[@class="form-control"]
[@value="1"]
]
[count(./input)=2]
'
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php if ($widget == 'single_text'): ?>
<?php echo $view['form']->block($form, 'form_widget_simple'); ?>
<?php else: ?>
<?php $vars = $widget == 'text' ? ['attr' => ['size' => 1]] : [] ?>
<div <?php echo $view['form']->block($form, 'widget_container_attributes') ?>>
<?php
// There should be no spaces between the colons and the widgets, that's why
// this block is written in a single PHP tag
echo $view['form']->widget($form['year'], $vars);
echo '-';
echo $view['form']->widget($form['week'], $vars);
?>
</div>
<?php endif ?>
1 change: 1 addition & 0 deletions src/Symfony/Component/Form/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ CHANGELOG
4.4.0
-----

* add new `WeekType`
* using different values for the "model_timezone" and "view_timezone" options of the `TimeType` without configuring a
reference date is deprecated
* preferred choices are repeated in the list of all choices
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ protected function loadTypes()
new Type\CurrencyType(),
new Type\TelType(),
new Type\ColorType(),
new Type\WeekType(),
];
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Form\Extension\Core\DataTransformer;

use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;

/**
* Transforms between an ISO 8601 week date string and an array.
*
* @author Damien Fayet <damienf1521@gmail.com>
*/
class WeekToArrayTransformer implements DataTransformerInterface
{
/**
* Transforms a string containing an ISO 8601 week date into an array.
*
* @param string|null $value A week date string
*
* @return array A value containing year and week
*
* @throws TransformationFailedException If the given value is not a string,
* or if the given value does not follow the right format
*/
public function transform($value)
{
if (null === $value) {
return ['year' => null, 'week' => null];
}

if (!\is_string($value)) {
throw new TransformationFailedException(sprintf('Value is expected to be a string but was "%s".', \is_object($value) ? \get_class($value) : \gettype($value)));
}

if (0 === preg_match('/^(?P<year>\d{4})-W(?P<week>\d{2})$/', $value, $matches)) {
throw new TransformationFailedException('Given data does not follow the date format "Y-\WW".');
}

return [
'year' => (int) $matches['year'],
'week' => (int) $matches['week'],
];
}

/**
* Transforms an array into a week date string.
*
* @param array $value An array containing a year and a week number
*
* @return string|null A week date string following the format Y-\WW
*
* @throws TransformationFailedException If the given value can not be merged in a valid week date string,
* or if the obtained week date does not exists
*/
public function reverseTransform($value)
{
if (null === $value || [] === $value) {
return;
}

if (!\is_array($value)) {
throw new TransformationFailedException(sprintf('Value is expected to be an array, but was "%s".', \is_object($value) ? \get_class($value) : \gettype($value)));
}

if (!\array_key_exists('year', $value)) {
throw new TransformationFailedException('Key "year" is missing.');
}

if (!\array_key_exists('week', $value)) {
throw new TransformationFailedException('Key "week" is missing.');
}

if (null === $value['year'] && null === $value['week']) {
return null;
}

if (!\is_int($value['year'])) {
throw new TransformationFailedException(sprintf('Year is expected to be an integer, but was "%s".', \is_object($value['year']) ? \get_class($value['year']) : \gettype($value['year'])));
}

if (!\is_int($value['week'])) {
throw new TransformationFailedException(sprintf('Week is expected to be an integer, but was "%s".', \is_object($value['week']) ? \get_class($value['week']) : \gettype($value['week'])));
}

// The 28th December is always in the last week of the year
if (date('W', strtotime('28th December '.$value['year'])) < $value['week']) {
throw new TransformationFailedException(sprintf('Week "%d" does not exist for year "%d".', $value['week'], $value['year']));
}

return sprintf('%d-W%02d', $value['year'], $value['week']);
}
}
Loading

0 comments on commit fea3d59

Please sign in to comment.