-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCheckbox.php
More file actions
159 lines (141 loc) · 5.05 KB
/
Copy pathCheckbox.php
File metadata and controls
159 lines (141 loc) · 5.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
<?php
namespace Quatrevieux\Form\Component;
use Attribute;
use Closure;
use Quatrevieux\Form\RegistryInterface;
use Quatrevieux\Form\Transformer\Field\FieldTransformerInterface;
use Quatrevieux\Form\Transformer\Generator\FieldTransformerGeneratorInterface;
use Quatrevieux\Form\Transformer\Generator\FormTransformerGenerator;
use Quatrevieux\Form\Util\Code;
use Quatrevieux\Form\Validator\FieldError;
use Quatrevieux\Form\View\FieldView;
use Quatrevieux\Form\View\Generator\FieldViewProviderGeneratorInterface;
use Quatrevieux\Form\View\Provider\FieldViewProviderConfigurationInterface;
use Quatrevieux\Form\View\Provider\FieldViewProviderInterface;
use function is_scalar;
/**
* Handle HTTP checkbox input
*
* The field value is true when a value is present in the HTTP request and is equal to the given httpValue (default to "1").
* The field value is false when the value is not present in the HTTP request or is not equal to the given httpValue.
* So, the field value is always a non-nullable boolean.
*
* Note: the http value will be cast to string before comparison.
*
* Usage:
* <code>
* final class MyForm
* {
* #[Checkbox]
* public bool $isAccepted;
*
* // You can also define a custom http value
* #[Checkbox(httpValue: 'yes')]
* public bool $withCustomHttpValue;
*
* // You can use validator to ensure the field is checked (or any other validation)
* #[Checkbox, IsIdenticalTo(true, message: 'You must check this box')]
* public bool $mustBeChecked;
* }
* </code>
*
* @implements FieldViewProviderInterface<Checkbox>
* @implements FieldViewProviderGeneratorInterface<Checkbox>
* @implements FieldTransformerGeneratorInterface<Checkbox>
*/
#[Attribute(Attribute::TARGET_PROPERTY)]
final class Checkbox implements FieldTransformerInterface, FieldTransformerGeneratorInterface, FieldViewProviderConfigurationInterface, FieldViewProviderInterface, FieldViewProviderGeneratorInterface
{
public function __construct(
private readonly string $httpValue = '1',
) {}
/**
* {@inheritdoc}
*/
public function transformFromHttp(mixed $value): bool
{
return is_scalar($value) && (string) $value === $this->httpValue;
}
/**
* {@inheritdoc}
*/
public function transformToHttp(mixed $value): ?string
{
if ($value === true) {
return $this->httpValue;
}
return null;
}
/**
* {@inheritdoc}
*/
public function canThrowError(): bool
{
return false;
}
/**
* {@inheritdoc}
*/
public function getViewProvider(RegistryInterface $registry): FieldViewProviderInterface
{
return $this;
}
/**
* {@inheritdoc}
*/
public function view(FieldViewProviderConfigurationInterface $configuration, string $name, mixed $value, array|FieldError|null $error, array $attributes): FieldView
{
$attributes['type'] ??= 'checkbox';
if ($configuration->transformFromHttp($value) === true) {
$attributes['checked'] = true;
}
// Remove the required attribute : a checkbox field always have a value (true or false)
unset($attributes['required']);
return new FieldView(
$name,
$configuration->httpValue,
$error instanceof FieldError ? $error : null,
$attributes,
);
}
/**
* {@inheritdoc}
*/
public function generateTransformFromHttp(object $transformer, string $previousExpression, FormTransformerGenerator $generator): string
{
return Code::expr($previousExpression)->storeAndFormat(
'is_scalar({}) && (string) {} === {httpValue}',
httpValue: $transformer->httpValue,
);
}
/**
* {@inheritdoc}
*/
public function generateTransformToHttp(object $transformer, string $previousExpression, FormTransformerGenerator $generator): string
{
return Code::expr($previousExpression)->format(
'({}) === true ? {httpValue} : null',
httpValue: $transformer->httpValue,
);
}
/**
* {@inheritdoc}
*/
public function generateFieldViewExpression(FieldViewProviderConfigurationInterface $configuration, string $name, array $attributes): Closure
{
$attributes['type'] ??= 'checkbox';
// Remove the required attribute : a checkbox field always have a value (true or false)
unset($attributes['required']);
return static fn(string $valueAccessor, string $errorAccessor, ?string $rootFieldNameAccessor) => Code::new(FieldView::class, [
$rootFieldNameAccessor ? Code::raw('"{' . $rootFieldNameAccessor . '}[' . $name . ']"') : $name,
$configuration->httpValue,
Code::expr($errorAccessor)->isInstanceOfOr(FieldError::class, null),
$attributes + [
'checked' => Code::expr($valueAccessor)->storeAndFormat(
'is_scalar({}) && (string) {} === {httpValue}',
httpValue: $configuration->httpValue,
),
],
]);
}
}