Skip to content

Commit b15c764

Browse files
authored
Fix #103: Add class for tag Form and method Html::form()
1 parent 0f1d747 commit b15c764

7 files changed

Lines changed: 473 additions & 6 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
# Yii HTML Change Log
22

3-
## 2.3.1 under development
3+
## 2.4.0 under development
44

5+
- New #103: Add class for tag `Form` and method `Html::form()` (vjik)
56
- Enh #106: Add option groups support to method `Select::optionsData()` (vjik)
67

78
## 2.3.0 March 25, 2022

README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@
1717

1818
The package provides various tools to help with dynamic server-side generation of HTML:
1919

20-
- Tag classes `A`, `Audio`, `B`, `Br`, `Button`, `Caption`, `Col`, `Colgroup`, `Div`, `Em`, `H1`, `H2`, `H3`, `H4`,
21-
`H5`, `H6` `I`, `Img`, `Input` (and specialized `Checkbox`, `Radio`), `Label`, `Li`, `Link`, `Meta`, `Noscript`, `Ol`,
22-
`Optgroup`, `Option`, `P`, `Picture`, `Script`, `Select`, `Source`, `Span`, `Strong`, `Style`, `Table`, `Tbody`, `Td`,
23-
`Textarea`, `Tfoot`, `Th`, `Thead`, `Title`, `Tr`, `Track`, `Ul`, `Video`.
20+
- Tag classes `A`, `Audio`, `B`, `Br`, `Button`, `Caption`, `Col`, `Colgroup`, `Div`, `Em`, `Form`, `H1`, `H2`, `H3`,
21+
`H4`, `H5`, `H6` `I`, `Img`, `Input` (and specialized `Checkbox`, `Radio`), `Label`, `Li`, `Link`, `Meta`, `Noscript`,
22+
`Ol`, `Optgroup`, `Option`, `P`, `Picture`, `Script`, `Select`, `Source`, `Span`, `Strong`, `Style`, `Table`, `Tbody`,
23+
`Td`, `Textarea`, `Tfoot`, `Th`, `Thead`, `Title`, `Tr`, `Track`, `Ul`, `Video`.
2424
- `CustomTag` class that helps to generate custom tag with any attributes.
2525
- HTML widgets `CheckboxList` and `RadioList`.
2626
- All tags content is automatically HTML-encoded. There is `NoEncode` class designed to wrap content that should not be encoded.
@@ -278,6 +278,7 @@ Overall the helper has the following method groups.
278278
- buttonInput
279279
- checkbox
280280
- fileInput
281+
- form
281282
- hiddenInput
282283
- input
283284
- label

src/Html.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use Yiisoft\Html\Tag\CustomTag;
1919
use Yiisoft\Html\Tag\Div;
2020
use Yiisoft\Html\Tag\Em;
21+
use Yiisoft\Html\Tag\Form;
2122
use Yiisoft\Html\Tag\H1;
2223
use Yiisoft\Html\Tag\H2;
2324
use Yiisoft\Html\Tag\H3;
@@ -558,6 +559,28 @@ public static function img(?string $url = null, ?string $alt = ''): Img
558559
return $tag;
559560
}
560561

562+
/**
563+
* Generates a {@see Form} tag.
564+
*
565+
* @param string|null $action The URL to use for form submission.
566+
* @param string|null $method The method attribute value.
567+
* @param array $attributes The tag attributes in terms of name-value pairs.
568+
*/
569+
public static function form(?string $action = null, ?string $method = null, array $attributes = []): Form
570+
{
571+
$tag = Form::tag();
572+
if ($action !== null) {
573+
$attributes['action'] = $action;
574+
}
575+
if ($method !== null) {
576+
$attributes['method'] = $method;
577+
}
578+
if (!empty($attributes)) {
579+
$tag = $tag->attributes($attributes);
580+
}
581+
return $tag;
582+
}
583+
561584
/**
562585
* Generates a {@see Label} tag.
563586
*

src/Tag/Base/NormalTag.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,12 @@ final protected function renderTag(): string
3131
*/
3232
final public function open(): string
3333
{
34-
return '<' . $this->getName() . $this->renderAttributes() . '>';
34+
return '<' . $this->getName() . $this->renderAttributes() . '>' . $this->prepend();
35+
}
36+
37+
protected function prepend(): string
38+
{
39+
return '';
3540
}
3641

3742
/**

src/Tag/Form.php

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Yiisoft\Html\Tag;
6+
7+
use Stringable;
8+
use Yiisoft\Html\Tag\Base\NormalTag;
9+
use Yiisoft\Html\Tag\Base\TagContentTrait;
10+
11+
/**
12+
* @link https://html.spec.whatwg.org/multipage/forms.html#the-form-element
13+
*/
14+
final class Form extends NormalTag
15+
{
16+
use TagContentTrait;
17+
18+
private ?string $csrfToken = null;
19+
private ?string $csrfName = null;
20+
21+
public function get(?string $url = null): self
22+
{
23+
$new = clone $this;
24+
$new->attributes['method'] = 'GET';
25+
if ($url !== null) {
26+
$new->attributes['action'] = $url;
27+
}
28+
return $new;
29+
}
30+
31+
public function post(?string $url = null): self
32+
{
33+
$new = clone $this;
34+
$new->attributes['method'] = 'POST';
35+
if ($url !== null) {
36+
$new->attributes['action'] = $url;
37+
}
38+
return $new;
39+
}
40+
41+
/**
42+
* @param string|Stringable|null $token
43+
*/
44+
public function csrf($token, string $name = '_csrf'): self
45+
{
46+
$new = clone $this;
47+
$new->csrfToken = $token === null ? null : (string)$token;
48+
$new->csrfName = $name;
49+
return $new;
50+
}
51+
52+
/**
53+
* Character encodings to use for form submission.
54+
*
55+
* @link https://html.spec.whatwg.org/multipage/forms.html#attr-form-accept-charset
56+
*/
57+
public function acceptCharset(?string $charset): self
58+
{
59+
$new = clone $this;
60+
$new->attributes['accept-charset'] = $charset;
61+
return $new;
62+
}
63+
64+
/**
65+
* The URL to use for form submission.
66+
*
67+
* @link https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#attr-fs-action
68+
*/
69+
public function action(?string $url): self
70+
{
71+
$new = clone $this;
72+
$new->attributes['action'] = $url;
73+
return $new;
74+
}
75+
76+
/**
77+
* Default setting for autofill feature for controls in the form.
78+
*
79+
* @link https://html.spec.whatwg.org/multipage/forms.html#attr-form-autocomplete
80+
*/
81+
public function autocomplete(bool $value = true): self
82+
{
83+
$new = clone $this;
84+
$new->attributes['autocomplete'] = $value ? 'on' : 'off';
85+
return $new;
86+
}
87+
88+
/**
89+
* Entry list encoding type to use for form submission.
90+
*
91+
* @link https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#attr-fs-enctype
92+
*/
93+
public function enctype(?string $enctype): self
94+
{
95+
$new = clone $this;
96+
$new->attributes['enctype'] = $enctype;
97+
return $new;
98+
}
99+
100+
/**
101+
* The method content attribute specifies how the form-data should be submitted.
102+
*
103+
* @param string $method The method attribute value.
104+
*
105+
* @link https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#attr-fs-method
106+
*/
107+
public function method(?string $method): self
108+
{
109+
$new = clone $this;
110+
$new->attributes['method'] = $method;
111+
return $new;
112+
}
113+
114+
/**
115+
* A boolean attribute, which, if present, indicate that the form is not to be validated during submission.
116+
*
117+
* @link https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#attr-fs-novalidate
118+
*/
119+
public function noValidate(bool $noValidate = true): self
120+
{
121+
$new = clone $this;
122+
$new->attributes['novalidate'] = $noValidate;
123+
return $new;
124+
}
125+
126+
/**
127+
* Browsing context for form submission.
128+
*
129+
* @param string|null $target The target attribute value.
130+
*
131+
* @link https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#attr-fs-target
132+
* @link https://html.spec.whatwg.org/multipage/browsers.html#valid-browsing-context-name-or-keyword
133+
*/
134+
public function target(?string $target): self
135+
{
136+
$new = clone $this;
137+
$new->attributes['target'] = $target;
138+
return $new;
139+
}
140+
141+
protected function prepend(): string
142+
{
143+
return $this->csrfToken !== null
144+
? PHP_EOL . Input::hidden($this->csrfName, $this->csrfToken)
145+
: '';
146+
}
147+
148+
protected function getName(): string
149+
{
150+
return 'form';
151+
}
152+
}

tests/common/HtmlTest.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,26 @@ public function testImg(): void
221221
$this->assertSame('<img src="face.png" alt="My Face">', Html::img('face.png', 'My Face')->render());
222222
}
223223

224+
public function testForm(): void
225+
{
226+
$this->assertSame(
227+
'<form></form>',
228+
Html::form()->render()
229+
);
230+
$this->assertSame(
231+
'<form action="https://example.com/send"></form>',
232+
Html::form('https://example.com/send')->render()
233+
);
234+
$this->assertSame(
235+
'<form action="https://example.com/send" method="GET"></form>',
236+
Html::form('https://example.com/send', 'GET')->render()
237+
);
238+
$this->assertSame(
239+
'<form class="red-form" action="https://example.com/send" method="GET"></form>',
240+
Html::form('https://example.com/send', 'GET', ['class' => 'red-form'])->render()
241+
);
242+
}
243+
224244
public function testLabel(): void
225245
{
226246
$this->assertSame('<label></label>', Html::label()->render());

0 commit comments

Comments
 (0)