PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.32.1
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.32.1
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 / models / fields / FrmFieldProduct.php

FrmFieldProduct.php in Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More 6.32.1, at classes/models/fields/FrmFieldProduct.php

461 lines 11.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if ( ! defined( 'ABSPATH' ) ) {
4 die( 'You are not allowed to call this page directly.' );
5 }
6
7 /**
8 * @since 6.30 This is copied from FrmProFieldProduct.php in Formidable Pro.
9 */
10 class FrmFieldProduct extends FrmFieldType {
11
12 protected $type = 'product';
13
14 /**
15 * We use this because of the display cases of checkbox and radio. Dropdown can
16 * still manage with the aria-labelledby="field_[key]_label" in the custom html.
17 *
18 * @var bool
19 */
20 protected $has_for_label = false;
21
22 /**
23 * @inheritDoc
24 */
25 protected function input_html() {
26 return $this->multiple_input_html();
27 }
28
29 /**
30 * @inheritDoc
31 */
32 protected function include_form_builder_file() {
33 return $this->include_front_form_file();
34 }
35
36 /**
37 * @inheritDoc
38 */
39 protected function new_field_settings() {
40 return array(
41 'options' => serialize(
42 array(
43 '',
44 __( 'Product 1', 'formidable' ),
45 )
46 ),
47 );
48 }
49
50 /**
51 * @inheritDoc
52 */
53 protected function field_settings_for_type() {
54 $settings = parent::field_settings_for_type();
55
56 $settings['options'] = true;
57 $settings['default_value'] = true;
58
59 /**
60 * So that we can have placeholder and size in Advanced settings
61 * because of the possibility of displaying like a select field.
62 */
63 $settings['clear_on_focus'] = true;
64 $settings['size'] = true;
65
66 return $settings;
67 }
68
69 /**
70 * @param array $args
71 */
72 protected function show_priority_field_choices( $args = array() ) {
73 include FrmAppHelper::plugin_path() . '/classes/views/frm-fields/back-end/radio-images.php';
74 }
75
76 /**
77 * @param array $args
78 */
79 public function show_primary_options( $args ) {
80 $field = $args['field'];
81 $data_types = $this->get_data_type_settings();
82 include FrmAppHelper::plugin_path() . '/classes/views/frm-fields/back-end/product-options.php';
83 parent::show_primary_options( $args );
84 }
85
86 /**
87 * @return array
88 */
89 private function get_data_type_settings() {
90 return array(
91 'select' => __( 'Dropdown', 'formidable' ),
92 'radio' => __( 'Radio Buttons', 'formidable' ),
93 'checkbox' => __( 'Checkboxes', 'formidable' ),
94 'single' => __( 'Single Product', 'formidable' ),
95 'user_def' => __( 'User Defined (Pro)', 'formidable' ),
96 );
97 }
98
99 /**
100 * @inheritDoc
101 */
102 protected function extra_field_opts() {
103 $form_id = $this->get_field_column( 'form_id' );
104
105 return array_merge(
106 parent::extra_field_opts(),
107 array(
108 'data_type' => 'select',
109 /* 'align' is needed for the checkbox and radio 'data_type' cases. */
110 'align' => FrmStylesController::get_style_val( 'check_align', $form_id ? $form_id : 'default' ),
111 )
112 );
113 }
114
115 /**
116 * @param array|object $field
117 */
118 public function displayed_field_type( $field ) {
119 return array(
120 $this->type => true,
121 );
122 }
123
124 /**
125 * Remove the frm_opt_container class for dropdowns.
126 *
127 * @param array $args
128 * @param string $html
129 *
130 * @return string
131 */
132 protected function after_replace_html_shortcodes( $args, $html ) {
133 $data_type = FrmField::get_option( $this->field, 'data_type' );
134
135 if ( 'radio' !== $data_type && 'checkbox' !== $data_type ) {
136 $html = str_replace( '"frm_opt_container', '"frm_data_container', $html );
137 }
138
139 $form_id = $args['parent_form_id'] ?? 0;
140
141 if ( ! $form_id ) {
142 $form_id = $this->get_field_column( 'form_id' );
143 }
144
145 FrmCurrencyHelper::add_currency_to_global( $form_id );
146
147 return $html;
148 }
149
150 /**
151 * @inheritDoc
152 */
153 protected function include_front_form_file() {
154 if ( is_array( $this->field ) && ! is_array( $this->field['options'] ) ) {
155 $this->field['options'] = array();
156 }
157
158 $product_type = FrmField::get_option( $this->field, 'data_type' );
159 $file = FrmAppHelper::plugin_path() . '/classes/views/frm-fields/front-end/product-';
160
161 if ( $product_type === 'checkbox' ) {
162 $file .= 'radio.php';
163 } elseif ( array_key_exists( $product_type, self::get_data_type_settings() ) ) {
164 $file .= str_replace( '_', '-', $product_type ) . '.php';
165 } else {
166 $file .= 'select.php';
167 }
168
169 return $file;
170 }
171
172 /**
173 * @param array $args
174 *
175 * @return bool
176 */
177 protected function should_continue_to_field_options( $args ) {
178 return true;
179 }
180
181 /**
182 * @inheritDoc
183 */
184 protected function get_bulk_edit_string() {
185 return __( 'Bulk Edit Products', 'formidable' );
186 }
187
188 /**
189 * @param array $args
190 */
191 protected function show_single_option( $args ) {
192 self::single_option( $args['field'] );
193 }
194
195 /**
196 * @inheritDoc
197 */
198 protected function extra_field_choices_class() {
199 $data_type = FrmField::get_option( $this->field, 'data_type' );
200 $type_class = '';
201
202 if ( 'single' === $data_type ) {
203 $type_class = ' frm_prod_type_' . $data_type;
204 }
205
206 return ' frmjs_product_choices' . $type_class;
207 }
208
209 /**
210 * @param array $args
211 */
212 protected function field_choices_heading_attrs( $args ) {
213 echo ' class="frm_prod_options_heading"';
214 }
215
216 /**
217 * @param array $args
218 *
219 * @return array
220 */
221 public function validate( $args ) {
222 $parent_errors = parent::validate( $args );
223
224 if ( $parent_errors || empty( $args['value'] ) ) {
225 return $parent_errors;
226 }
227
228 global $frm_products;
229
230 if ( ! $frm_products ) {
231 $frm_products = array();
232 }
233
234 $product_field_key = $this->get_field_column( 'id' ) . '_' . $args['parent_field_id'] . '_' . $args['key_pointer'];
235
236 if ( ! isset( $frm_products[ $product_field_key ] ) || ! is_array( $frm_products[ $product_field_key ] ) ) {
237 $frm_products[ $product_field_key ] = array();
238 }
239 $frm_products[ $product_field_key ]['price'] = $this->get_posted_price( $args['value'] );
240 $frm_products[ $product_field_key ]['key_pointer'] = $args['key_pointer'];
241 $frm_products[ $product_field_key ]['parent_field_id'] = $args['parent_field_id'];
242
243 return array();
244 }
245
246 /**
247 * @param array|string $posted_value
248 *
249 * @return array|float
250 */
251 public function get_posted_price( $posted_value ) {
252 $price = 0;
253 $options = $this->get_field_column( 'options' );
254
255 if ( ! is_array( $options ) ) {
256 return $price;
257 }
258
259 if ( ! is_array( $posted_value ) ) {
260 $this->get_price( $options, $posted_value, $price );
261 return $price;
262 }
263
264 $price = array();
265
266 foreach ( $posted_value as $value ) {
267 $this->get_price( $options, $value, $price );
268 }
269
270 return $price;
271 }
272
273 /**
274 * @param array $options
275 * @param mixed $value
276 * @param array|int $price
277 *
278 * @return void
279 */
280 private function get_price( $options, $value, &$price ) {
281 foreach ( $options as $option ) {
282 if ( ! is_array( $option ) ) {
283 continue;
284 }
285
286 // In Lite, since separate values is not available, we can always use label.
287 $check_key = 'label';
288
289 if ( ! isset( $option[ $check_key ] ) || $option[ $check_key ] !== $value ) {
290 continue;
291 }
292
293 if ( isset( $option['price'] ) && trim( $option['price'] ) ) {
294 if ( is_array( $price ) ) {
295 $price[] = trim( $option['price'] );
296 } else {
297 $price = trim( $option['price'] );
298 }
299 }
300 break;
301 }//end foreach
302 }
303
304 /**
305 * @param array $field
306 *
307 * @return void
308 */
309 public static function single_option( $field ) {
310 self::hidden_field_option( $field );
311
312 if ( ! is_array( $field['options'] ) ) {
313 return;
314 }
315
316 $base_name = 'default_value_' . $field['id'];
317 $html_id = $field['html_id'] ?? FrmFieldsHelper::get_html_id( $field );
318 $default_type = self::get_default_value_type( $field );
319 $options_count = count( $field['options'] );
320
321 foreach ( $field['options'] as $opt_key => $opt ) {
322 $field_val = FrmFieldsHelper::get_value_from_array( $opt, $opt_key, $field );
323 $price = self::get_price_from_array( $opt, $opt_key, $field );
324 $opt = FrmFieldsHelper::get_label_from_array( $opt, $opt_key, $field );
325 $field_name = $base_name . ( $default_type === 'checkbox' ? '[' . $opt_key . ']' : '' );
326 $checked = isset( $field['default_value'] ) && ( is_array( $field['default_value'] )
327 ? in_array( $field_val, $field['default_value'], true )
328 : $field['default_value'] === $field_val );
329
330 require FrmAppHelper::plugin_path() . '/classes/views/frm-fields/back-end/product-single-option.php';
331
332 unset( $checked );
333 }
334 }
335
336 /**
337 * @param array $field
338 *
339 * @return void
340 */
341 private static function hidden_field_option( $field ) {
342 $opt_key = '000';
343 $field_val = __( 'New Product', 'formidable' );
344 $opt = $field_val;
345 $price = '';
346 $checked = false;
347 $field_name = 'default_value_' . $field['id'];
348 $html_id = $field['html_id'] ?? FrmFieldsHelper::get_html_id( $field );
349
350 $default_type = self::get_default_value_type( $field );
351 $field_name .= $default_type === 'checkbox' ? '[' . $opt_key . ']' : '';
352
353 require FrmAppHelper::plugin_path() . '/classes/views/frm-fields/back-end/product-single-option.php';
354 }
355
356 /**
357 * @param array $field
358 *
359 * @return string
360 */
361 private static function get_default_value_type( $field ) {
362 $data_type = FrmField::get_option_in_array( $field, 'data_type' );
363 return 'checkbox' === $data_type ? $data_type : 'radio';
364 }
365
366 /**
367 * @param array $opt {
368 * The option.
369 *
370 * @type string $price
371 * }
372 *
373 * @param string $opt_key
374 * @param array $field
375 *
376 * @return string
377 */
378 public static function get_price_from_array( $opt, $opt_key, $field ) {
379 /**
380 * Filter the product option before getting the price.
381 *
382 * @since 6.30
383 *
384 * @param array|string $opt
385 * @param string $opt_key
386 * @param array $field
387 */
388 $opt = apply_filters( 'frm_field_price_saved', $opt, $opt_key, $field );
389 return is_array( $opt ) ? (string) ( $opt['price'] ?? '' ) : '';
390 }
391
392 /**
393 * Format price when show=price.
394 *
395 * @param array|string $value
396 * @param array $atts {
397 * The args.
398 *
399 * @type string $show
400 * @type string $sep
401 * }
402 *
403 * @return array|string
404 */
405 protected function prepare_display_value( $value, $atts ) {
406 if ( ! isset( $atts['show'] ) || $atts['show'] !== 'price' ) {
407 return $value;
408 }
409
410 $options = is_array( $this->field ) ? $this->field['options'] : $this->field->options;
411
412 if ( ! is_array( $options ) ) {
413 return $value;
414 }
415
416 $is_array = is_array( $value );
417
418 // Temporary turn value into array.
419 if ( ! $is_array ) {
420 $value = ! empty( $atts['sep'] ) && is_string( $atts['sep'] ) ? explode( $atts['sep'], $value ) : (array) $value;
421 }
422
423 $format = $atts['format'] ?? 'currency';
424
425 // Lite does not support separate values, so always check label.
426 // In Pro, this will check for "value" instead when separate values is enabled.
427 $check_key = 'label';
428
429 if ( 'single' === FrmField::get_option( $this->field, 'data_type' ) ) {
430 foreach ( $options as $option ) {
431 if ( is_array( $option ) ) {
432 $options = array( $option );
433 break;
434 }
435 }
436 }
437
438 /**
439 * @var array $value
440 */
441
442 foreach ( $value as $k => $v ) {
443 foreach ( $options as $option ) {
444 if ( ! is_array( $option ) || ! isset( $option['price'] ) ) {
445 continue;
446 }
447
448 if ( ! isset( $option[ $check_key ] ) || $option[ $check_key ] !== $v ) {
449 continue;
450 }
451
452 $value[ $k ] = 'number' === $format ? $option['price'] : FrmCurrencyHelper::format_price( $option['price'] );
453
454 break;
455 }
456 }
457
458 return $is_array ? $value : implode( $atts['sep'], $value );
459 }
460 }
461