PluginProbe
Flexible Subscriptions / trunk
Flexible Subscriptions vtrunk
1.8.5 1.8.4 1.8.3 1.8.2 1.8.1 1.8.0 1.7.19 1.7.18 1.7.17 1.7.16 1.7.15 1.7.14 1.7.13 1.7.12 1.7.11 trunk 1.0.0 1.0.1 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.2.1 1.2.2 All 62 releases
flexible-subscriptions / src / Form / ExtendedForm.php

ExtendedForm.php in Flexible Subscriptions trunk, at src/Form/ExtendedForm.php

232 lines 5.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 declare(strict_types=1);
3
4 namespace WPDesk\FlexibleSubscriptions\Form;
5
6 use WPDesk\FlexibleSubscriptions\Vendor\Psr\Container\ContainerInterface;
7 use WPDesk\FlexibleSubscriptions\Vendor\WPDesk\Forms\Field;
8 use WPDesk\FlexibleSubscriptions\Vendor\WPDesk\Forms\Form;
9 use WPDesk\FlexibleSubscriptions\Vendor\WPDesk\Persistence\ElementNotExistsException;
10 use WPDesk\FlexibleSubscriptions\Vendor\WPDesk\View\Renderer\Renderer;
11
12 /**
13 * This is inspired by wp-forms, but changes the internals for handling iterable field groups.
14 */
15 class ExtendedForm implements Form {
16 use Field\Traits\HtmlAttributes;
17
18 private string $form_id = 'form';
19
20 protected ?array $updated_data = null;
21
22 /** @var Field[] */
23 private array $fields;
24
25 /**
26 * @param Field[] $fields
27 */
28 public function __construct( array $fields, string $form_id = 'form' ) {
29 $this->fields = $fields;
30 $this->form_id = $form_id;
31 $this->set_action( '' );
32 $this->set_method( 'POST' );
33 }
34
35 public function is_valid(): bool {
36 foreach ( $this->fields as $field ) {
37 if ( ! $this->is_field_valid( $field ) ) {
38 return false;
39 }
40 }
41
42 return true;
43 }
44
45 private function is_field_valid( Field $field ): bool {
46 if ( is_iterable( $field ) ) {
47 foreach ( $field as $child ) {
48 if ( ! $this->is_field_valid( $child ) ) {
49 return false;
50 }
51 }
52
53 return true;
54 }
55
56 $validator = $field->get_validator();
57 return $validator->is_valid( $this->updated_data[ $field->get_name() ] ?? $field->get_default_value() );
58 }
59
60 public function handle_request( array $request = [] ) {
61 if ( $this->updated_data === null ) {
62 $this->updated_data = [];
63 }
64
65 foreach ( $this->fields as $field ) {
66 $this->handle_field_from_request( $field, $request );
67 }
68 }
69
70 public function handle_field_from_request( Field $field, $request ) {
71 if ( is_iterable( $field ) ) {
72 foreach ( $field as $child ) {
73 $this->handle_field_from_request( $child, $request );
74 }
75 return;
76 }
77
78 $data_key = $field->get_name();
79 if ( isset( $request[ $data_key ] ) ) {
80 $this->updated_data[ $data_key ] = $field->get_sanitizer()->sanitize( $request[ $data_key ] );
81 }
82 }
83
84 public function set_data( ContainerInterface $data ) {
85 foreach ( $this->fields as $field ) {
86 $this->set_data_from_field( $field, $data );
87 }
88 }
89
90 private function set_data_from_field( Field $field, ContainerInterface $data ) {
91 if ( is_iterable( $field ) ) {
92 foreach ( $field as $child ) {
93 $this->set_data_from_field( $child, $data );
94 }
95 return;
96 }
97
98 $data_key = $field->get_name();
99 if ( $data->has( $data_key ) ) {
100 try {
101 $this->updated_data[ $data_key ] = $data->get( $data_key );
102 } catch ( ElementNotExistsException $e ) {
103 $this->updated_data[ $data_key ] = false;
104 }
105 }
106 }
107
108 public function get_data(): array {
109 if ( empty( $this->fields ) ) {
110 return [];
111 }
112
113 $data = $this->updated_data;
114
115 foreach ( $this->fields as $field ) {
116 $data = $this->get_data_by_field( $field, $data );
117 }
118
119 return $data;
120 }
121
122 protected function get_data_by_field( Field $field, $data ): array {
123 if ( is_iterable( $field ) ) {
124 foreach ( $field as $child ) {
125 $data = array_merge( $data, $this->get_data_by_field( $child, $data ) );
126 }
127 return $data;
128 }
129
130 $data_key = $field->get_name();
131 if ( ! isset( $data[ $data_key ] ) ) {
132 $data[ $data_key ] = $field->get_default_value();
133 }
134
135 return $data;
136 }
137
138 public function render_fields( Renderer $renderer ): string {
139 $content = '';
140 $fields_data = $this->get_data();
141 foreach ( $this->get_fields() as $field ) {
142 $content .= $renderer->render(
143 $field->should_override_form_template() ? $field->get_template_name() : 'form-field',
144 [
145 'field' => $field,
146 'renderer' => $renderer,
147 'name_prefix' => $this->get_form_id(),
148 'value' => $this->get_field_value( $field, $fields_data ),
149 'template_name' => $field->get_template_name(),
150 ]
151 );
152 }
153
154 return $content;
155 }
156
157 protected function get_field_value( Field $field, array $fields_data ) {
158 if ( is_iterable( $field ) ) {
159 $values = [];
160 foreach ( $field as $child ) {
161 $values[ $child->get_name() ] = $this->get_field_value( $child, $fields_data );
162 }
163 return $values;
164 }
165
166 return $fields_data[ $field->get_name() ] ?? $field->get_default_value();
167 }
168
169 /** Set Form action attribute. */
170 public function set_action( string $action ): self {
171 $this->attributes['action'] = $action;
172
173 return $this;
174 }
175
176 public function get_action(): string {
177 return $this->attributes['action'];
178 }
179
180 /** Set Form method attribute ie. GET/POST. */
181 public function set_method( string $method ): self {
182 $this->attributes['method'] = $method;
183
184 return $this;
185 }
186
187 public function get_method(): string {
188 return $this->attributes['method'];
189 }
190
191
192 public function is_submitted(): bool {
193 return null !== $this->updated_data;
194 }
195
196 public function is_active(): bool {
197 return true;
198 }
199
200 public function render_form( Renderer $renderer ): string {
201 $content = $renderer->render(
202 'form-start',
203 [ 'form' => $this ]
204 );
205 $content .= $this->render_fields( $renderer );
206 $content .= $renderer->render( 'form-end' );
207
208 return $content;
209 }
210
211 public function get_fields(): array {
212 $fields = $this->fields;
213
214 usort(
215 $fields,
216 static function ( Field $a, Field $b ) {
217 return $a->get_priority() <=> $b->get_priority();
218 }
219 );
220
221 return $fields;
222 }
223
224 public function get_form_id(): string {
225 return $this->form_id;
226 }
227
228 public function get_normalized_data(): array {
229 return $this->get_data();
230 }
231 }
232