PluginProbe
SellKit – Funnel builder and checkout optimizer for WooCommerce to sell more, faster / trunk
SellKit – Funnel builder and checkout optimizer for WooCommerce to sell more, faster vtrunk
2.6.0 trunk 1.1.0 1.1.4 1.2.1 1.2.2 1.2.3 1.2.5 1.2.9 1.3.1 1.3.2 1.5.0 1.5.1 1.5.4 1.5.7 1.5.8 1.5.9 1.6.2 1.6.5 1.6.8 1.7.2 1.7.4 1.7.5 1.7.9 1.8.1 All 42 releases
sellkit / includes / elementor / modules / optin / fields / field-base.php

field-base.php in SellKit – Funnel builder and checkout optimizer for WooCommerce to sell more, faster trunk, at includes/elementor/modules/optin/fields/field-base.php

495 lines 11.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 defined( 'ABSPATH' ) || die();
4
5 use Sellkit_Elementor_Optin_Module as Module;
6
7 /**
8 * An abstract class to register new optin field.
9 *
10 * @since 1.5.0
11 * @abstract
12 * @SuppressWarnings(PHPMD.ExcessiveClassComplexitys)
13 */
14 abstract class Sellkit_Elementor_Optin_Field_Base {
15
16 /**
17 * Optin widget.
18 *
19 * Holds the optin widget instance.
20 *
21 * @access public
22 *
23 * @var object
24 */
25 public $widget;
26
27 /**
28 * Optin form field.
29 *
30 * Holds all the fields attributes.
31 *
32 * @access public
33 *
34 * @var array
35 */
36 public $field;
37
38 /**
39 * Depended scripts.
40 *
41 * Holds all the element depended scripts to enqueue.
42 *
43 * @since 1.5.0
44 * @access private
45 *
46 * @var array
47 */
48 private $depended_scripts = [];
49
50 /**
51 * Depended styles.
52 *
53 * Holds all the element depended styles to enqueue.
54 *
55 * @since 1.5.0
56 * @access private
57 *
58 * @var array
59 */
60 private $depended_styles = [];
61
62 public function __construct() {
63 add_action( 'elementor/frontend/after_enqueue_styles', [ $this, 'enqueue_styles' ] );
64 add_action( 'elementor/frontend/after_enqueue_scripts', [ $this, 'enqueue_scripts' ] );
65 }
66
67 /**
68 * Ready made array of type condition to be used in childs.
69 *
70 * @return array
71 *
72 * @since 1.5.0
73 * @access public
74 * @static
75 * @final
76 */
77 final public static function get_type_condition() {
78 return [
79 'name' => 'type',
80 'operator' => 'in',
81 'value' => [ static::get_field_type() ],
82 ];
83 }
84
85 /**
86 * Get field ID.
87 *
88 * Retrieve the field type.
89 *
90 * @return string Field ID.
91 *
92 * @since 1.5.0
93 * @access public
94 */
95 public function get_id() {
96 return $this->field['_id'];
97 }
98
99 /**
100 * Get input type of the field.
101 *
102 * The type that appears inside \<input\> tag.
103 * By default it equals the name of field type, except in select, acceptance etc. which should be overridden.
104 *
105 * @return string Field type.
106 *
107 * @since 1.5.0
108 * @access public
109 */
110 public function get_input_type() {
111 return $this->field['type'];
112 }
113
114 /**
115 * Get the real name of field type.
116 *
117 * @return string Field type.
118 *
119 * @since 1.5.0
120 * @access public
121 * @static
122 * @abstract
123 */
124 abstract public static function get_field_type();
125
126 /**
127 * Get field class.
128 *
129 * @return string Field class.
130 *
131 * @since 1.5.0
132 * @access public
133 */
134 public function get_class() {
135 return 'sellkit-field';
136 }
137
138 /**
139 * Retrieve the list of script dependencies the element requires.
140 *
141 * @return array Element scripts dependencies.
142 *
143 * @since 1.5.0
144 * @access public
145 */
146 public function get_script_depends() {
147 return $this->depended_scripts;
148 }
149
150 /**
151 * Registers all the scripts defined as element dependencies and enqueues
152 * them. Use `get_script_depends()` method to add custom script dependencies.
153 *
154 * @since 1.5.0
155 * @access public
156 * @final
157 */
158 final public function enqueue_scripts() {
159 foreach ( $this->get_script_depends() as $script ) {
160 wp_enqueue_script( $script );
161 }
162
163 }
164
165 /**
166 * Retrieve the list of style dependencies the element requires.
167 *
168 * @return array Element styles dependencies.
169 *
170 * @since 1.5.0
171 * @access public
172 */
173 public function get_style_depends() {
174 return $this->depended_styles;
175 }
176
177 /**
178 * Registers all the styles defined as element dependencies and enqueues
179 * them. Use `get_style_depends()` method to add custom style dependencies.
180 *
181 * @since 1.5.0
182 * @access public
183 * @final
184 */
185 final public function enqueue_styles() {
186 foreach ( $this->get_style_depends() as $style ) {
187 wp_enqueue_style( $style );
188 }
189 }
190
191 /**
192 * Render field label and content.
193 *
194 * @param object $widget Widget instance.
195 * @param array $field Field.
196 *
197 * @since 1.5.0
198 * @access public
199 */
200 public function render( $widget, $field ) {
201 $this->widget = $widget;
202 $this->field = $field;
203
204 $this->add_field_render_attribute();
205 $this->add_field_group_render_attribute();
206
207 ?>
208 <div <?php echo $this->widget->get_render_attribute_string( 'field-group-' . esc_attr( $this->get_id() ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Elementor-generated attributes. ?>>
209 <?php
210 $this->render_label();
211 $this->render_content();
212 ?>
213 </div>
214 <?php
215 }
216
217 /**
218 * Add render attributes for each field based on the settings.\
219 * Some field classes may override it if they have additional attributes.
220 *
221 * @since 1.5.0
222 * @access public
223 */
224 public function add_field_render_attribute() {
225 $attributes = [
226 'type' => $this->get_input_type(),
227 'name' => 'fields[' . $this->get_id() . ']',
228 'id' => 'optin-field-' . $this->get_id(),
229 'class' => $this->get_class(),
230 'data-type' => $this->field['type'],
231 ];
232
233 if ( isset( $this->field['required'] ) && 'true' === $this->field['required'] ) {
234 $attributes['required'] = 'required';
235 }
236
237 if ( ! empty( $this->field['placeholder'] ) ) {
238 $attributes['placeholder'] = $this->field['placeholder'];
239 }
240
241 if (
242 ! empty( $this->field['field_value'] ) &&
243 ! in_array( $this->get_input_type(), [ 'textarea', 'select' ], true )
244 ) {
245 $attributes['value'] = $this->field['field_value'];
246 }
247
248 $this->widget->add_render_attribute( 'field-' . $this->get_id(), $attributes );
249 }
250
251 /**
252 * Add render attributes div wrapper of the field.\
253 * Handles the responsive "width" control by adding a CSS var.
254 *
255 * @since 1.5.0
256 * @access public
257 * @final
258 */
259 final public function add_field_group_render_attribute() {
260
261 $this->widget->add_render_attribute(
262 'field-group-' . $this->get_id(),
263 [
264 'id' => 'sellkit-field-group-' . $this->get_id(),
265 'class' => 'sellkit-flex-wrap sellkit-field-group sellkit-field-type-' . $this->get_field_type() . ' elementor-column elementor-col-' . $this->field['width'],
266 ]
267 );
268
269 // We add responsive widths as css variables and apply them according to "data-elementor-device-mode" attribute of <body> element.
270 foreach ( Module::get_active_breakpoints() as $device => $value ) {
271 if ( 'desktop' !== $device && empty( $this->field[ "width_{$device}" ] ) ) {
272 continue;
273 }
274
275 $setting_key = 'desktop' === $device ? 'width' : "width_{$device}";
276
277 $this->widget->add_render_attribute(
278 'field-group-' . $this->get_id(),
279 'style',
280 "--sellkit-field-width-{$device}:" . $this->field[ $setting_key ] . '%;'
281 );
282 }
283 }
284
285 /**
286 * Render the label for each field.
287 *
288 * @since 1.5.0
289 * @access public
290 */
291 public function render_label() {
292 $settings = $this->widget->get_settings_for_display();
293
294 if (
295 empty( $this->field['label'] ) ||
296 'yes' !== $settings['label'] ||
297 in_array( $this->get_field_type(), [ 'hidden', 'acceptance' ], true )
298 ) {
299 return;
300 }
301
302 ?>
303 <label
304 for="optin-field-<?php echo esc_attr( $this->get_id() ); ?>"
305 class="sellkit-field-label">
306 <?php echo wp_kses_post( $this->field['label'] ); ?>
307 <?php if ( isset( $this->field['required'] ) && 'true' === $this->field['required'] ) : ?>
308 <span class="required-mark-label"></span>
309 <?php endif ?>
310 </label>
311 <?php
312 }
313
314 /**
315 * Render the field content.
316 *
317 * @since 1.5.0
318 * @access public
319 * @abstract
320 */
321 abstract public function render_content();
322
323 /**
324 * Ready made array of controls that are common among many fields, to be used in childs.
325 *
326 * @return array
327 *
328 * @since 1.5.0
329 * @access public
330 * @static
331 * @final
332 */
333 final public static function get_common_controls() {
334 return [
335 'label' => [
336 'label' => esc_html__( 'Label', 'sellkit' ),
337 'type' => 'text',
338 'conditions' => [ 'terms' => [ static::get_type_condition() ] ],
339 ],
340 'field_value' => [
341 'label' => esc_html__( 'Default Value', 'sellkit' ),
342 'type' => 'text',
343 'dynamic' => [ 'active' => true ],
344 'conditions' => [ 'terms' => [ static::get_type_condition() ] ],
345 ],
346 'placeholder' => [
347 'label' => esc_html__( 'Placeholder', 'sellkit' ),
348 'type' => 'text',
349 'conditions' => [ 'terms' => [ static::get_type_condition() ] ],
350 ],
351 'required' => [
352 'label' => esc_html__( 'Required', 'sellkit' ),
353 'type' => 'switcher',
354 'return_value' => 'true',
355 'conditions' => [ 'terms' => [ static::get_type_condition() ] ],
356 ],
357 'width_responsive' => [
358 'label' => esc_html__( 'Column Width', 'sellkit' ),
359 'type' => 'select',
360 'default' => '100',
361 'conditions' => [ 'terms' => [ static::get_type_condition() ] ],
362 'options' => [
363 '100' => '100%',
364 '80' => '80%',
365 '75' => '75%',
366 '66' => '66%',
367 '60' => '60%',
368 '50' => '50%',
369 '40' => '40%',
370 '33' => '33%',
371 '25' => '25%',
372 '20' => '20%',
373 ],
374 ],
375 ];
376 }
377
378 /**
379 * Get array of field controls params. Child classes must override it
380 * and to include common controls, they must use "get_common_controls"
381 * method inside this method.
382 *
383 * ►For responsive controls, please add a "_responsive" suffix to the name of control.\
384 * ►For group controls, please add a "_group" suffix to the name of control.
385 *
386 * @return array
387 *
388 * @since 1.5.0
389 * @access public
390 * @static
391 * @abstract
392 */
393 abstract public static function get_additional_controls();
394
395 /**
396 * Get final set of controls, ready to feed to field repeater's add control functions.
397 *
398 * @return array
399 *
400 * @since 1.5.0
401 * @access public
402 * @static
403 * @final
404 */
405 final public static function get_fields_controls() {
406 $controls = [];
407 $sort_helper = [];
408
409 foreach ( Module::$field_types as $type_class ) {
410 $controls = self::merge_controls( $controls, $type_class::get_additional_controls(), $sort_helper );
411 }
412
413 $controls = self::get_sorted_controls( $controls, $sort_helper );
414
415 return $controls;
416 }
417
418 // From here on, methods are private and are only used in
419 // process of preparing array of fields controls.
420 // phpcs:ignore
421 private static function merge_controls( array $accumulative, array $new_array, &$sort_helper ) {
422 $sort_helper[] = [];
423
424 foreach ( $new_array as $control => $props ) {
425 $sort_helper[ count( $sort_helper ) - 1 ][] = $control;
426
427 if ( ! array_key_exists( $control, $accumulative ) ) {
428 $accumulative[ $control ] = $props;
429 continue;
430 }
431
432 // Merge conditions.
433 $accum_type_key = array_search( 'type', array_column( $accumulative[ $control ]['conditions']['terms'], 'name' ), true );
434 $accum_type_values = $accumulative[ $control ]['conditions']['terms'][ $accum_type_key ]['value'];
435
436 $new_type_key = array_search( 'type', array_column( $props['conditions']['terms'], 'name' ), true );
437 $new_type_value = $props['conditions']['terms'][ $new_type_key ]['value'];
438
439 $accumulative
440 [ $control ]
441 ['conditions']
442 ['terms']
443 [ $accum_type_key ]
444 ['value'] = array_merge( $accum_type_values, $new_type_value );
445 }
446
447 return $accumulative;
448 }
449
450 private static function get_sorted_controls( $controls, $sort_helper ) {
451 $unique = array_unique( self::flatten( $sort_helper ) );
452
453 self::sort_recursive( $unique, $sort_helper );
454
455 foreach ( $unique as $control ) {
456 $result[ $control ] = $controls[ $control ];
457 }
458
459 return $result;
460 }
461
462 private static function sort_recursive( &$uniques, $sort_helper ) {
463 foreach ( $uniques as $rank => $control ) {
464
465 foreach ( $sort_helper as $group ) {
466
467 $pos = array_search( $control, $group, true );
468
469 if ( false === $pos ) {
470 continue;
471 }
472
473 foreach ( $group as $control_pos => $control_key ) {
474
475 $comp_rank = array_search( $control_key, $uniques, true );
476
477 if ( ( $pos < $control_pos && $rank > $comp_rank ) ) {
478 list( $uniques[ $rank ], $uniques[ $comp_rank ] ) = array( $uniques[ $comp_rank ], $uniques[ $rank ] );
479 return self::sort_recursive( $uniques, $sort_helper );
480 }
481 }
482 }
483 }
484 }
485
486 private static function flatten( array $array ) {
487 $return = array();
488 array_walk_recursive( $array, function( $a ) use ( &$return ) {
489 $return[] = $a;
490 } );
491
492 return $return;
493 }
494 }
495