PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / trunk
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More vtrunk
6.35 6.34 6.33.1 6.33 6.32.1 6.32 6.31 6.25 6.25.1 6.26 6.26.1 6.27 6.28 6.29 6.3 6.3.1 6.3.2 6.30 6.4 6.4.1 6.4.2 6.5 6.5.1 6.5.2 6.5.3 All 141 releases
formidable / classes / helpers / FrmFieldGridHelper.php

FrmFieldGridHelper.php in Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More trunk, at classes/helpers/FrmFieldGridHelper.php

335 lines 6.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if ( ! defined( 'ABSPATH' ) ) {
3 die( 'You are not allowed to call this page directly.' );
4 }
5
6 class FrmFieldGridHelper {
7
8 /**
9 * @var bool
10 */
11 private $parent_li;
12
13 /**
14 * @var int
15 */
16 private $current_list_size;
17
18 /**
19 * @var int
20 */
21 private $current_field_count;
22
23 /**
24 * @var string
25 */
26 private $field_layout_class;
27
28 /**
29 * @var int
30 */
31 private $active_field_size;
32
33 /**
34 * @var bool flagged while calling get_field_layout_class, true if classes contain frm_first class.
35 */
36 private $is_frm_first;
37
38 /**
39 * @var stdClass|null
40 */
41 private $field;
42
43 /**
44 * @var FrmFieldGridHelper|null
45 */
46 private $section_helper;
47
48 /**
49 * @var bool
50 */
51 private $nested;
52
53 /**
54 * @var int
55 */
56 private $section_size;
57
58 /**
59 * @var bool
60 */
61 private $section_is_open = false;
62
63 /**
64 * @param bool $nested
65 */
66 public function __construct( $nested = false ) {
67 $this->parent_li = false;
68 $this->current_list_size = 0;
69 $this->current_field_count = 0;
70 $this->nested = $nested;
71 }
72
73 /**
74 * @param stdClass $field
75 *
76 * @return void
77 */
78 public function set_field( $field ) {
79 $this->field = $field;
80
81 if ( $this->section_helper && 'end_divider' !== $field->type ) {
82 $this->section_helper->set_field( $field );
83 return;
84 }
85
86 if ( 'end_divider' === $field->type ) {
87 $this->field_layout_class = '';
88 $this->active_field_size = $this->section_size;
89 $this->section_is_open = false;
90 $this->maybe_close_section_helper();
91 } else {
92 $this->field_layout_class = $this->get_field_layout_class();
93 $this->active_field_size = self::get_size_of_class( $this->field_layout_class );
94 }
95
96 if ( 'divider' !== $field->type || $this->nested ) {
97 return;
98 }
99
100 $this->section_size = $this->active_field_size;
101 $this->active_field_size = 0;
102 $this->section_helper = new self( true );
103 }
104
105 /**
106 * @return void
107 */
108 private function maybe_close_section_helper() {
109 if ( ! $this->section_helper ) {
110 return;
111 }
112 $this->section_helper->force_close_field_wrapper();
113 $this->section_helper = null;
114 }
115
116 /**
117 * @return string
118 */
119 public function get_field_layout_class() {
120 $field = FrmFieldsHelper::setup_edit_vars( $this->field );
121
122 if ( empty( $field['classes'] ) ) {
123 return '';
124 }
125
126 $split = explode( ' ', $field['classes'] );
127 $this->is_frm_first = in_array( 'frm_first', $split, true );
128
129 foreach ( self::get_grid_classes() as $class ) {
130 if ( in_array( $class, $split, true ) ) {
131 return $class;
132 }
133 }
134
135 return '';
136 }
137
138 /**
139 * @return void
140 */
141 public function maybe_begin_field_wrapper() {
142 if ( $this->should_first_close_the_active_field_wrapper() ) {
143 $this->close_field_wrapper();
144 }
145
146 if ( false === $this->parent_li && 'end_divider' !== $this->field->type ) {
147 $this->begin_field_wrapper();
148 }
149
150 if ( $this->section_helper && $this->section_is_open ) {
151 $this->section_helper->maybe_begin_field_wrapper();
152 }
153 }
154
155 /**
156 * @return bool
157 */
158 private function should_first_close_the_active_field_wrapper() {
159 if ( false === $this->parent_li ) {
160 return false;
161 }
162
163 /**
164 * Fields that sit inside an open section are wrapped by that section's own helper, so the
165 * row here is not theirs to close. set_field() opens the section helper for the section
166 * field itself, one step ahead of this check, and section_is_open is not set until
167 * sync_list_size() runs afterwards. Testing both is what keeps the section field subject to
168 * the width check below rather than being treated as though it were already inside itself.
169 *
170 * @see https://github.com/Strategy11/formidable-pro/issues/3820
171 */
172 if ( $this->section_helper && $this->section_is_open ) {
173 return false;
174 }
175
176 if ( 'end_divider' === $this->field->type ) {
177 return false;
178 }
179
180 return ! $this->can_support_current_layout() || $this->is_frm_first;
181 }
182
183 /**
184 * @return void
185 */
186 private function begin_field_wrapper() {
187 echo '<li class="frm_field_box"><ul class="frm_grid_container frm_sorting">';
188 $this->parent_li = true;
189 $this->current_list_size = 0;
190 $this->current_field_count = 0;
191 }
192
193 /**
194 * @param string $class
195 *
196 * @return int
197 */
198 private static function get_size_of_class( $class ) {
199 switch ( $class ) {
200 case 'frm_half':
201 return 6;
202 case 'frm_third':
203 return 4;
204 case 'frm_two_thirds':
205 return 8;
206 case 'frm_fourth':
207 return 3;
208 case 'frm_three_fourths':
209 return 9;
210 case 'frm_sixth':
211 return 2;
212 }
213
214 if ( str_starts_with( $class, 'frm' ) ) {
215 $substr = substr( $class, 3 );
216
217 if ( is_numeric( $substr ) ) {
218 return (int) $substr;
219 }
220 }
221
222 // Anything missing a layout class should be a full width row.
223 return 12;
224 }
225
226 /**
227 * @return void
228 */
229 public function sync_list_size() {
230 if ( ! $this->field ) {
231 return;
232 }
233
234 if ( 'divider' === $this->field->type ) {
235 $this->section_is_open = true;
236 }
237
238 if ( $this->section_helper ) {
239 $this->section_helper->sync_list_size();
240
241 if ( 'end_divider' === $this->field->type ) {
242 $this->maybe_close_section_helper();
243 }
244
245 return;
246 }
247
248 if ( false === $this->parent_li ) {
249 return;
250 }
251
252 ++$this->current_field_count;
253 $this->current_list_size += $this->active_field_size;
254
255 if ( 12 === $this->current_list_size ) {
256 $this->close_field_wrapper();
257 }
258 }
259
260 /**
261 * It is possible that there was still space for another field so the wrapper could still be open after looping the fields.
262 * If it is, make sure it's closed now.
263 *
264 * @return void
265 */
266 public function force_close_field_wrapper() {
267 if ( false !== $this->parent_li ) {
268 $this->close_field_wrapper();
269 }
270 }
271
272 /**
273 * @return void
274 */
275 private function close_field_wrapper() {
276 // Only an open section has a nested wrapper to close. A section helper that set_field() has
277 // just created belongs to the section about to start, so closing this row must leave it alone.
278 if ( $this->section_is_open ) {
279 $this->maybe_close_section_helper();
280 }
281
282 echo '</ul></li>';
283 $this->parent_li = false;
284 $this->current_list_size = 0;
285 $this->current_field_count = 0;
286 }
287
288 /**
289 * @return bool
290 */
291 private function can_support_current_layout() {
292 if ( 'end_divider' === $this->field->type ) {
293 return true;
294 }
295 return $this->can_support_an_additional_layout( $this->field_layout_class );
296 }
297
298 /**
299 * @param string $class
300 *
301 * @return bool
302 */
303 private function can_support_an_additional_layout( $class ) {
304 $size = self::get_size_of_class( $class );
305 return $this->current_list_size + $size <= 12;
306 }
307
308 /**
309 * @return array<string>
310 */
311 private static function get_grid_classes() {
312 return array(
313 'frm_full',
314 'frm_half',
315 'frm_third',
316 'frm_two_thirds',
317 'frm_fourth',
318 'frm_three_fourths',
319 'frm_sixth',
320 'frm1',
321 'frm2',
322 'frm3',
323 'frm4',
324 'frm5',
325 'frm6',
326 'frm7',
327 'frm8',
328 'frm9',
329 'frm10',
330 'frm11',
331 'frm12',
332 );
333 }
334 }
335