Skip to content

Commit e32d55c

Browse files
committed
Added more fields and widgets
1 parent d623886 commit e32d55c

File tree

7 files changed

+127
-44
lines changed

7 files changed

+127
-44
lines changed

src/Fields/ChoiceField.php

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,43 @@
44
*/
55
namespace PHPForm\Fields;
66

7+
use Fleshgrinder\Core\Formatter;
8+
9+
use PHPForm\Exceptions\ValidationError;
10+
use PHPForm\Widgets\Select;
11+
712
class ChoiceField extends Field
813
{
14+
protected $widget = Select::class;
15+
16+
protected $error_messages = array(
17+
'invalid' => 'Select a valid choice. {choice} is not one of the available choices.'
18+
);
19+
20+
public function __construct(array $args = array())
21+
{
22+
$this->choices = array_key_exists('choices', $args) ? $args['choices'] : array();
23+
24+
parent::__construct($args);
25+
26+
$this->widget->setChoices($this->choices);
27+
}
28+
29+
public function toNative($value)
30+
{
31+
return !empty($value) ? (string) $value : '';
32+
}
33+
34+
public function validate($value)
35+
{
36+
parent::validate($value);
37+
38+
if (!array_key_exists($value, $this->choices)) {
39+
$message = Formatter::format($this->error_messages['invalid'], array(
40+
'choice' => $value
41+
));
42+
43+
throw new ValidationError($message, 'invalid');
44+
}
45+
}
946
}

src/Widgets/ChoiceWidget.php

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,12 @@
1010

1111
abstract class ChoiceWidget extends Widget
1212
{
13-
const TEMPLATE_OPTION = '';
13+
const TEMPLATE_OPTION = "";
1414

1515
protected $allow_multiple_selected = false;
1616
protected $input_type = null;
1717
protected $option_inherits_attrs = true;
18+
protected $selected_attribute = "selected";
1819
protected $choices;
1920

2021
/**
@@ -24,25 +25,26 @@ public function __construct(array $choices = array(), array $css_classes = null,
2425
{
2526
parent::__construct($css_classes, $attrs);
2627

27-
$this->choices = $choices;
28+
$this->setChoices($choices);
2829
}
2930

30-
public function setChoices(array $value)
31+
public function setChoices(array $choices)
3132
{
3233
$this->choices = $choices;
3334
}
3435

3536
public function getContext(string $name, $value, array $attrs = null)
3637
{
3738
$context = parent::getContext($name, $value, $attrs);
38-
$context["options"] = $this->renderOptions($context['name'], $context['value'], $attrs);
39+
$context["options"] = $this->renderOptions($context["name"], $context["value"], $attrs);
3940

4041
return $context;
4142
}
4243

4344
public function renderOptions(string $name, $value, array $attrs = null)
4445
{
45-
$options = '';
46+
$options = "";
47+
$index = 1;
4648
$has_selected = false;
4749

4850
foreach ($this->choices as $choice_value => $choice_label) {
@@ -53,30 +55,43 @@ public function renderOptions(string $name, $value, array $attrs = null)
5355
$has_selected = true;
5456
}
5557

56-
$context = $this->getOptionContext($name, $choice_value, $choice_label, $selected, $attrs);
58+
$context = $this->getOptionContext($name, $choice_value, $choice_label, $selected, $index, $attrs);
5759

5860
$options .= Formatter::format(static::TEMPLATE_OPTION, $context);
61+
62+
$index++;
5963
}
6064

6165
return $options;
6266
}
6367

64-
public function getOptionContext(string $name, $value, string $label, bool $is_selected, array $attrs = null)
65-
{
68+
public function getOptionContext(
69+
string $name,
70+
$value,
71+
string $label,
72+
bool $is_selected,
73+
int $index,
74+
array $attrs = null
75+
) {
6676
if (!$this->option_inherits_attrs || is_null($attrs)) {
6777
$attrs = array();
6878
}
6979

80+
if ($this->option_inherits_attrs) {
81+
$attrs["id"] = $this->buildAutoId($name, $index);
82+
}
83+
7084
if ($is_selected) {
71-
$attrs["selected"] = "selected";
85+
$attrs[$this->selected_attribute] = $this->selected_attribute;
7286
}
7387

7488
return array(
89+
"for" => $this->buildAutoId($name, $index),
7590
"type" => $this->input_type,
7691
"name" => $name,
7792
"value" => htmlentities($value),
7893
"label" => htmlentities($label),
79-
"attrs" => Attributes::flatatt($attrs)
94+
"attrs" => Attributes::flatatt($attrs),
8095
);
8196
}
8297

src/Widgets/Widget.php

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
abstract class Widget
1212
{
13-
const AUTO_ID_TEMPLATE = "id_{name}";
13+
const AUTO_ID_TEMPLATE = "id_{name}[_{index}?]";
1414
const TEMPLATE = '';
1515

1616
/**
@@ -156,6 +156,16 @@ public function setRequired(bool $value)
156156
$this->required = $value;
157157
}
158158

159+
/**
160+
* Setter for $required attribute.
161+
*
162+
* @param bool $value Value to be setted.
163+
*/
164+
public function isRequired()
165+
{
166+
return $this->required;
167+
}
168+
159169
/**
160170
* Setter for $disabled attribute.
161171
*
@@ -201,10 +211,11 @@ private function buildAttrs(array $extra_attrs = null)
201211
*
202212
* @return string
203213
*/
204-
public function buildAutoId(string $name)
214+
public function buildAutoId(string $name, int $index = null)
205215
{
206216
return Formatter::format(self::AUTO_ID_TEMPLATE, array(
207-
"name" => $name
217+
"name" => $name,
218+
"index" => $index
208219
));
209220
}
210221
}

tests/unit/Fields/BooleanFieldTest.php

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,25 @@
55

66
use PHPForm\Exceptions\ValidationError;
77
use PHPForm\Fields\BooleanField;
8-
use PHPForm\Widgets\BooleanInput;
8+
use PHPForm\Widgets\CheckboxInput;
99

1010
class BooleanFieldTest extends TestCase
1111
{
12-
// public function testConstruct()
13-
// {
14-
// $field = new BooleanField();
15-
// $this->assertInstanceOf(BooleanInput::class, $field->getWidget());
16-
// }
12+
public function testConstruct()
13+
{
14+
$field = new BooleanField();
15+
$this->assertInstanceOf(CheckboxInput::class, $field->getWidget());
16+
}
1717

1818
public function testToNative()
1919
{
2020
$field = new BooleanField();
21-
$this->assertEquals($field->clean(false), false);
22-
$this->assertEquals($field->clean(true), true);
23-
$this->assertEquals($field->clean("false"), false);
24-
$this->assertEquals($field->clean("0"), false);
25-
$this->assertEquals($field->clean("1"), true);
26-
$this->assertEquals($field->clean("aa"), true);
21+
$this->assertEquals($field->toNative(false), false);
22+
$this->assertEquals($field->toNative(true), true);
23+
$this->assertEquals($field->toNative("false"), false);
24+
$this->assertEquals($field->toNative("0"), false);
25+
$this->assertEquals($field->toNative("1"), true);
26+
$this->assertEquals($field->toNative("aa"), true);
2727
}
2828

2929
/**
@@ -35,4 +35,10 @@ public function testValidate()
3535
$field = new BooleanField(array('required' => true));
3636
$field->clean(false);
3737
}
38+
39+
public function testValidateValidValue()
40+
{
41+
$field = new BooleanField(array('required' => true));
42+
$this->assertTrue($field->clean(true));
43+
}
3844
}

tests/unit/Widgets/RadioSelect.php

Lines changed: 0 additions & 13 deletions
This file was deleted.

tests/unit/Widgets/SelectMultipleTest.php

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,31 @@ public function setUp()
1414

1515
public function testRender()
1616
{
17-
$render = $this->widget->render("name", null);
18-
1917
$expected = '<select id="id_name" multiple="multiple" name="name">' .
2018
'<option value="option1">option1</option>' .
2119
'<option value="option2">option2</option>' .
2220
'</select>';
2321

24-
$this->assertXmlStringEqualsXmlString($expected, $render);
22+
$this->assertXmlStringEqualsXmlString($expected, $this->widget->render("name", null));
23+
}
24+
25+
public function testRenderSelected()
26+
{
27+
$expected = '<select id="id_name" multiple="multiple" name="name">' .
28+
'<option value="option1" selected="selected">option1</option>' .
29+
'<option value="option2">option2</option>' .
30+
'</select>';
31+
32+
$this->assertXmlStringEqualsXmlString($expected, $this->widget->render("name", "option1"));
33+
}
34+
35+
public function testRenderMultipleSelected()
36+
{
37+
$expected = '<select id="id_name" multiple="multiple" name="name">' .
38+
'<option value="option1" selected="selected">option1</option>' .
39+
'<option value="option2" selected="selected">option2</option>' .
40+
'</select>';
41+
42+
$this->assertXmlStringEqualsXmlString($expected, $this->widget->render("name", ["option1", "option2"]));
2543
}
2644
}

tests/unit/Widgets/SelectTest.php

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,22 @@ public function setUp()
1414

1515
public function testRender()
1616
{
17-
$render = $this->widget->render("name", null);
18-
1917
$expected = '<select id="id_name" name="name">' .
2018
'<option value="option1">option1</option>' .
2119
'<option value="option2">option2</option>' .
2220
'</select>';
2321

24-
$this->assertXmlStringEqualsXmlString($expected, $render);
22+
$this->assertXmlStringEqualsXmlString($expected, $this->widget->render("name", null));
23+
}
24+
25+
public function testRenderSelected()
26+
{
27+
$expected = '<select id="id_name" name="name">' .
28+
'<option value="option1" selected="selected">option1</option>' .
29+
'<option value="option2">option2</option>' .
30+
'</select>';
31+
32+
$this->assertXmlStringEqualsXmlString($expected, $this->widget->render("name", "option1"));
33+
$this->assertXmlStringEqualsXmlString($expected, $this->widget->render("name", ["option1", "option2"]));
2534
}
2635
}

0 commit comments

Comments
 (0)