PluginProbe
Themify Builder / 7.7.0
Themify Builder v7.7.0
7.8.1 7.8.0 7.7.9 7.7.8 7.7.7 7.7.6 7.7.5 7.7.4 7.7.3 7.7.2 trunk 7.6.0 7.6.1 7.6.2 7.6.3 7.6.4 7.6.5 7.6.6 7.6.7 7.6.8 7.6.9 7.7.0 7.7.1
themify-builder / includes / components / module.php

module.php in Themify Builder 7.7.0, at includes/components/module.php

2,195 lines 79.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * This file contain abstraction class to create module object.
5 *
6 * Themify_Builder_Component_Module class should be used as main class and
7 * create any child extend class for module.
8 *
9 *
10 * @package Themify_Builder
11 * @subpackage Themify_Builder/classes
12 */
13 defined('ABSPATH') || exit;
14
15 /**
16 * The abstract class for Module.
17 *
18 * Abstraction class to initialize module object, don't initialize
19 * this class directly but please create child class of it.
20 *
21 *
22 * @package Themify_Builder
23 * @subpackage Themify_Builder/classes
24 * @author Themify
25 */
26 class Themify_Builder_Component_Module {
27
28 /**
29 * Module Name.
30 *
31 * @access public
32 * @var string $name
33 */
34 public $name = ''; //deprecated
35
36 /**
37 * Module Slug.
38 *
39 * @access public
40 * @var string $slug
41 */
42 public $slug = ''; //deprecated
43
44 /**
45 * Module Category.
46 *
47 * @access public
48 * @var string $category
49 */
50 public $category = null; //deprecated
51
52 private static $assets = array();
53 public static $isFirstModule = false;
54 public static $disable_inline_edit = false;
55
56 public static function get_module_class(string $slug):string{
57 $name=\explode('-',$slug);
58 $items=['TB'];
59 foreach($name as $v){
60 $items[]= \ucfirst($v);
61 }
62 $items[]='Module';
63 $className= \implode('_',$items);
64 if(!class_exists('\\'.$className,false)){//bakward
65 if($slug==='pro-image'){
66 $className= 'TB_Image_Pro_Module';
67 }
68 elseif($slug==='typewriter'){
69 $className= 'TB_Typewriter';
70 }
71 elseif($slug==='stats'){
72 $className= 'TB_Statistics_Module';
73 }
74 elseif($slug==='readtime'){
75 $className= 'TB_Read_Time_Module';
76 }
77 elseif($slug==='ab-image'){
78 $className= 'TB_AB_Image_Module';
79 }
80 }
81 return '\\'.$className;
82 }
83
84 public static function get_js_css():array {
85 return array();
86 }
87
88 public static function get_module_icon():string {
89 return '';
90 }
91
92 public static function get_module_name():string {
93 return '';
94 }
95
96 public static function is_available():bool{
97 return true;
98 }
99
100 public static function get_json_file():array {
101 return array();
102 }
103
104 public static function get_styles_json():array {
105 $keys=array();
106 $loadFiles=apply_filters('tb_json_files', []);
107 $res=[THEMIFY_BUILDER_URI.'/json/style.json?ver='.THEMIFY_VERSION];
108 foreach($loadFiles as $file){
109 $res[]=$file['f'].'?ver='.$file['v'];
110 }
111 unset($loadFiles);
112 $modules=self::load_modules();
113 foreach ($modules as $id=>$module) {
114 $file=$module::get_json_file();
115 if(!empty($file)){
116 $files[]=$file;
117 $keys[]=$id.$file['v'];
118 }
119 }
120 if(!empty($files)){
121 if ( ! themify_is_dev_mode() && count( $files ) > 2 ) {
122 sort($keys);
123 $jsonDir='/json/';
124 $jsonName=$jsonDir.crc32(implode('',$keys)).'.json';
125 $jsonF=THEMIFY_BUILDER_DIR. $jsonName;
126 unset($keys);
127 $hasError=false;
128 if (!is_file($jsonF)) {
129 $jsonData=$fallback=[];
130 foreach($files as $file){
131 $content=$hasError===false?Themify_Filesystem::get_file_content($file['f']):null;
132 if(!empty($content)){
133 $content=json_decode($content,true);
134 if(!empty($content)){
135 $jsonData=array_merge($jsonData, $content);
136 }
137 }
138 if($hasError===false && empty($content)){
139 $hasError=true;
140 $jsonData=null;
141 }
142 $fallback[]=$file['f'].'?ver='.$file['v'];
143 }
144 if($hasError===false){
145 $tmpF=THEMIFY_BUILDER_DIR.$jsonDir. uniqid('tmp_');
146 $jsonData=json_encode($jsonData);
147 if(empty($jsonData) || !file_put_contents($tmpF, $jsonData) || !rename($tmpF,$jsonF)){
148 $hasError=true;
149 if(is_file($tmpF)){
150 unlink($tmpF);
151 }
152 }
153 $jsonData=null;
154 }
155 if($hasError===true){
156 $res=array_merge($res,$fallback);
157 }
158 unset($fallback);
159 }
160 if($hasError===false){
161 $res[]=THEMIFY_BUILDER_URI.$jsonName.'?ver='.THEMIFY_VERSION;
162 }
163 }
164 else{
165 foreach($files as $file){
166 $res[]=$file['f'].'?ver='.$file['v'];
167 }
168 }
169 }
170 return $res;
171 }
172
173 //will be need later
174 public static function add_inline_edit_icon() {
175
176 }
177
178 /**
179 * Get checkbox data
180 * @param $setting
181 * @return string
182 */
183 public static function get_checkbox_data(string $setting):string {
184 return \implode(' ', \explode('|', $setting));
185 }
186
187 /**
188 * Return only value setting
189 * @param $string
190 * @return string
191 */
192 public static function get_param_value(string $string):string {
193 return \explode('|', $string)[0];
194 }
195
196
197 /**
198 * Retrieve builder templates
199 * @param $template_name
200 * @param array $args
201 * @param string $template_path
202 * @param string $default_path
203 * @param bool $echo
204 * @return string|VOID
205 */
206 public static function retrieve_template(string $template_name,$args = array(),string $template_path = '', string $default_path = '', bool $echo = true) {
207 if ($echo === false) {
208 ob_start();
209 }
210 self::get_template($template_name, $args, $template_path, $default_path);
211 if ($echo === false) {
212 return ob_get_clean();
213 }
214 }
215
216 /**
217 * Get template builder
218 * @param $template_name
219 * @param array $args
220 * @param string $template_path
221 * @param string $default_path
222 */
223 protected static function get_template(string $template_name, &$args = array(),string $template_path = '',string $default_path = '') {
224 static $paths = array();
225 $key = $template_path . $template_name;
226 if (!isset($paths[$key])) {
227 $paths[$key] = self::locate_template($template_name, $template_path, $default_path);
228 }
229 if (isset($paths[$key]) && $paths[$key] !== '') {
230 global $ThemifyBuilder;//deprecated
231 include($paths[$key]);
232 }
233 }
234
235 /**
236 * Locate a template and return the path for inclusion.
237 *
238 * This is the load order:
239 *
240 * yourtheme / $template_path / $template_name
241 * $default_path / $template_name
242 */
243 public static function locate_template(string $template_name,string $template_path = '',string $default_path = ''):string {
244 static $theme_dir = null;
245 static $child_dir = null;
246 $template = '';
247
248 $DS = DIRECTORY_SEPARATOR;
249 if ($theme_dir === null) {
250 $builderDir = $DS . 'themify-builder' . $DS;
251 $theme_dir = get_template_directory() . $builderDir;
252 if (!\is_dir($theme_dir)) {
253 $theme_dir = false;
254 }
255 if (is_child_theme()) {
256 $child_dir = get_stylesheet_directory() . $builderDir;
257 if (!\is_dir($child_dir)) {
258 $child_dir = false;
259 }
260 }
261 $builderDir = null;
262 }
263 if ($theme_dir !== false || $child_dir !== null || $child_dir !== false) {
264 $templates = array();
265 if ($child_dir !== null && $child_dir !== false) {
266 $templates[] = $child_dir;
267 }
268 if ($theme_dir !== false) {
269 $templates[] = $theme_dir;
270 }
271 foreach ($templates as $dir) {//is theme file
272 if (\is_file($dir . $template_name)) {
273 $template = $dir . $template_name;
274 break;
275 }
276 }
277 unset($templates);
278 }
279 if ($template === '') {
280 if ($template_path === '') {
281 $modulesPath = \Themify_Builder_Model::get_directory_path();
282 if (\strpos($template_name, 'template-') === 0) {
283 $module = str_replace(array('template-', '.php'), '', $template_name);
284 if (isset($modulesPath[$module])) {
285 $template = pathinfo($modulesPath[$module], PATHINFO_DIRNAME) . $DS . 'templates' . $DS . $template_name;
286 }
287 }
288 if ($template === '') {
289 $dir = rtrim(THEMIFY_BUILDER_TEMPLATES_DIR, $DS) . $DS;
290 if (\is_file($dir . $template_name)) {
291 $template = $dir . $template_name;
292 }
293 // Get default template
294 if ($template === '') {
295 foreach ($modulesPath as $m) {//backward
296 $dir = pathinfo($m, PATHINFO_DIRNAME) . $DS . 'templates' . $DS . $template_name;
297 if (\is_file($dir)) {
298 $template = $dir;
299 break;
300 }
301 }
302 if ($template === '') {
303 $template = $default_path . $template_name;
304 if (\is_file($template)) {
305 $template = '';
306 }
307 }
308 }
309 }
310 } else {
311 $template = \rtrim($template_path, $DS) . $DS . $template_name;
312 }
313 }
314 // Return what we found
315 return apply_filters('themify_builder_locate_template', $template, $template_name, $template_path);
316 }
317
318
319 /**
320 * Sticky Element props attributes, also handles Motion Effects
321 * @param array $props
322 * @param array $fields_args
323 * @param string $mod_name
324 * @param string $module_ID
325 * @return array
326 */
327 public static function sticky_element_props( array &$props,array $fields_args, string $motion_option_prefix = '' ) {
328 if (!empty($fields_args['stick_at_check']) || !empty($fields_args['stick_at_check_t']) || !empty($fields_args['stick_at_check_tl']) || !empty($fields_args['stick_at_check_m'])) {
329 static $is_sticky = null;
330 if ($is_sticky === null) {
331 $is_sticky = \Themify_Builder_Model::is_sticky_scroll_active();
332 }
333 if ($is_sticky !== false) {
334 $_arr = array('d', 'tl', 't', 'm');
335 $settings = array();
336 foreach ($_arr as $v) {
337 $key = $v === 'd' ? '' : '_' . $v;
338 if (($key === '' && !empty($fields_args['stick_at_check'])) || ($key !== '' && isset($fields_args['stick_at_check' . $key]) && $fields_args['stick_at_check' . $key] !== '')) {
339 $settings[$v] = array();
340 if ($key !== '' && $fields_args['stick_at_check' . $key] !== '1') {
341 $settings[$v] = 0;
342 } else {
343 if (isset($fields_args['stick_at_position' . $key]) && $fields_args['stick_at_position' . $key] === 'bottom') {
344 $settings[$v]['stick'] = array();
345 $settings[$v]['stick']['p'] = $fields_args['stick_at_position' . $key];
346 }
347 if (!empty($fields_args['stick_at_pos_val' . $key])) {
348 if (!isset($settings[$v]['stick'])) {
349 $settings[$v] = array('stick' => array());
350 }
351 $settings[$v]['stick']['v'] = $fields_args['stick_at_pos_val' . $key];
352 if (isset($fields_args['stick_at_pos_val_unit' . $key]) && $fields_args['stick_at_pos_val_unit' . $key] !== 'px') {
353 $settings[$v]['stick']['u'] = $fields_args['stick_at_pos_val_unit' . $key];
354 }
355 }
356
357 if (!empty($fields_args['unstick_when_check' . $key])) {
358 $unstick = array();
359 if (isset($fields_args['unstick_when_element' . $key]) && $fields_args['unstick_when_element' . $key] !== 'builder_end') {
360 if (isset($fields_args['unstick_when_condition' . $key]) && $fields_args['unstick_when_condition' . $key] !== 'hits') {
361 $unstick['r'] = $fields_args['unstick_when_condition' . $key];
362 }
363 $unstick['type'] = $fields_args['unstick_when_element' . $key];
364 if ($unstick['type'] === 'row' && isset($fields_args['unstick_when_el_row_id' . $key]) && $fields_args['unstick_when_el_row_id' . $key] !== 'row') {
365 $unstick['el'] = $fields_args['unstick_when_el_row_id' . $key];
366 } elseif ($unstick['type'] === 'module' && !empty($fields_args['unstick_when_el_mod_id' . $key])) {
367 $unstick['el'] = $fields_args['unstick_when_el_mod_id' . $key];
368 } else {
369 continue;
370 }
371
372 if (isset($fields_args['unstick_when_pos' . $key]) && $fields_args['unstick_when_pos' . $key] !== 'this') {
373 $unstick['cur'] = $fields_args['unstick_when_pos' . $key];
374 if (!empty($fields_args['unstick_when_pos_val' . $key])) {
375 $unstick['v'] = $fields_args['unstick_when_pos_val' . $key];
376 if (isset($fields_args['unstick_when_pos_val_unit' . $key]) && $fields_args['unstick_when_pos_val_unit' . $key] !== 'px') {
377 $unstick['u'] = $fields_args['unstick_when_pos_val_unit' . $key];
378 }
379 }
380 }
381 } else {
382 $unstick['type'] = 'builder';
383 }
384 if (!empty($unstick)) {
385 $settings[$v]['unstick'] = $unstick;
386 }
387 }
388 }
389 }
390 }
391 if (!empty($settings)) {
392 unset($_arr);
393 $props['data-sticky-active'] = \json_encode($settings);
394 if ($is_sticky !== 'done') {
395 $is_sticky = 'done';
396 \Themify_Enqueue_Assets::addPrefetchJs(THEMIFY_BUILDER_JS_MODULES . 'sticky.js', THEMIFY_VERSION);
397 }
398 }
399 }
400 }//Add custom attributes html5 data to module container div to show parallax options.
401 elseif (Themify_Builder::$frontedit_active === false && (!empty($fields_args[ $motion_option_prefix . 'motion_effects' ] ) || !empty($fields_args['custom_parallax_scroll_speed']) )) {
402 static $is_lax = null;
403 if ($is_lax === null) {
404 $is_lax = \Themify_Builder_Model::is_scroll_effect_active();
405 }
406 if ($is_lax !== false) {
407 $has_lax = false; /* validate Lax settings */
408 // Check settings from Floating tab to apply them to Lax library
409 if (!empty($fields_args['custom_parallax_scroll_speed'])) {
410 $has_lax = true;
411 $props['data-parallax-element-speed'] = $fields_args['custom_parallax_scroll_speed'];
412
413 $speed = self::map_animation_speed($fields_args['custom_parallax_scroll_speed']);
414
415 if (!isset($fields_args['custom_parallax_scroll_reverse']) || $fields_args['custom_parallax_scroll_reverse'] === '|') {
416 $speed = '-' . $speed;
417 }
418 $props['data-lax-translate-y'] = 'vh 1,0 ' . $speed;
419 if (!empty($fields_args['custom_parallax_scroll_fade']) && $fields_args['custom_parallax_scroll_fade'] !== '|') {
420 $props['data-lax-opacity'] = 'vh 1,0 0';
421 }
422 }
423 // Add motion effects from Motion tab
424 $effects = isset($fields_args[ $motion_option_prefix . 'motion_effects' ] ) ? $fields_args[ $motion_option_prefix . 'motion_effects' ] : array();
425 if (!isset($effects['t'])) {
426 $props['data-lax-optimize'] = 'true';
427 }
428 // Vertical
429 if (!empty($effects['v']['val']['v_dir'])) {
430 $has_lax = true;
431 $v_speed = isset($effects['v']['val']['v_speed']) ? $effects['v']['val']['v_speed'] : 1;
432 $v_speed = self::map_animation_speed($v_speed);
433 $viewport = isset($effects['v']['val']['v_vp']) ? explode(',', $effects['v']['val']['v_vp']) : array(0, 100);
434 $bottom = 1 - ( (int) $viewport[0] / 100 );
435 $top = 1 - ( (int) $viewport[1] / 100 );
436 $props['data-lax-translate-y'] = $effects['v']['val']['v_dir'] === 'up' ? '(vh*' . $bottom . ') 0,(vh*' . $top . ') -' . $v_speed : '(vh*' . $bottom . ') 0,(vh*' . $top . ') ' . $v_speed;
437 }
438 // Horizontal
439 if (!empty($effects['h']['val']['h_dir'])) {
440 $has_lax = true;
441 $h_speed = isset($effects['h']['val']['h_speed']) ? $effects['h']['val']['h_speed'] : 9;
442 $h_speed=self::map_animation_speed($h_speed);
443 $viewport = isset($effects['h']['val']['h_vp']) ? explode(',', $effects['h']['val']['h_vp']) : array(0, 100);
444 $bottom = 1 - ( (int) $viewport[0] / 100 );
445 $top = 1 - ( (int) $viewport[1] / 100 );
446 $props['data-lax-translate-x'] = $effects['h']['val']['h_dir'] === 'toleft' ? '(vh*' . $bottom . ') 0,(vh*' . $top . ') -' . $h_speed : '(vh*' . $bottom . ') 0,(vh*' . $top . ') ' . $h_speed;
447 }
448 // Opacity
449 if (!empty($effects['t']['val']['t_dir'])) {
450 $has_lax = true;
451 $viewport = isset($effects['t']['val']['t_vp']) ? explode(',', $effects['t']['val']['t_vp']) : array(0, 100);
452 $bottom = 1 - ( (int) $viewport[0] / 100 );
453 $top = 1 - ( (int) $viewport[1] / 100 );
454 $center = ( $bottom - ( ( $bottom - $top ) / 2 ) );
455 if ($effects['t']['val']['t_dir'] === 'fadein') {
456 $props['data-lax-opacity'] = '(vh*' . $bottom . ') 0,(vh*' . $top . ') 1';
457 } elseif ($effects['t']['val']['t_dir'] === 'fadeout') {
458 $props['data-lax-opacity'] = '(vh*' . $bottom . ') 1,(vh*' . $top . ') 0';
459 } elseif ($effects['t']['val']['t_dir'] === 'fadeoutin') {
460 $props['data-lax-opacity'] = '(vh*' . $bottom . ') 1,(vh*' . $center . ') 0,(vh*' . $top . ') 1';
461 } elseif ($effects['t']['val']['t_dir'] === 'fadeinout') {
462 $props['data-lax-opacity'] = '(vh*' . $bottom . ') 0,(vh*' . $center . ') 1,(vh*' . $top . ') 0';
463 }
464 } elseif (!isset($fields_args['animation_effect_delay'])) {
465 unset($props['data-lax-opacity'], $props['data-lax-optimize']);
466 }
467 // Blur
468 if (!empty($effects['b']['val']['b_dir'])) {
469 $has_lax = true;
470 $b_level = isset($effects['b']['val']['b_level']) ? $effects['b']['val']['b_level']: 5;
471 $b_level=self::map_animation_speed($b_level, 'blur');
472 $viewport = isset($effects['b']['val']['b_vp']) ? explode(',', $effects['b']['val']['b_vp']) : array(0, 100);
473 $bottom = 1 - ( (int) $viewport[0] / 100 );
474 $top = 1 - ( (int) $viewport[1] / 100 );
475 $props['data-lax-blur'] = $effects['b']['val']['b_dir'] === 'fadein' ? '(vh*' . $bottom . ') ' . $b_level . ',(vh*' . $top . ') 0' : '(vh*' . $bottom . ') 0,(vh*' . $top . ') ' . $b_level;
476 }
477 // Rotate
478 if (!empty($effects['r']['val']['r_dir'])) {
479 $has_lax = true;
480 $viewport = isset($effects['r']['val']['r_vp']) ? explode(',', $effects['r']['val']['r_vp']) : array(0, 100);
481 $rotates = isset($effects['r']['val']['r_num']) ? (float) $effects['r']['val']['r_num'] * 360 : 360;
482 $bottom = 1 - ( (int) $viewport[0] / 100 );
483 $top = 1 - ( (int) $viewport[1] / 100 );
484 $props['data-lax-rotate'] = $effects['r']['val']['r_dir'] === 'toleft' ? '(vh*' . $bottom . ') 0,(vh*' . $top . ') -' . $rotates : '(vh*' . $bottom . ') 0,(vh*' . $top . ') ' . $rotates;
485 if (isset($effects['r']['val']['r_origin'])) {
486 $props['data-box-position'] = self::map_transform_origin($effects['r']['val']['r_origin']);
487 }
488 }
489 // Scale
490 if (!empty($effects['s']['val']['s_dir'])) {
491 $has_lax = true;
492 $viewport = isset($effects['s']['val']['s_vp']) ? explode(',', $effects['s']['val']['s_vp']) : array(0, 100);
493 $ratio = isset($effects['s']['val']['s_ratio']) ? (float) $effects['s']['val']['s_ratio'] : 3;
494 $bottom = 1 - ( (int) $viewport[0] / 100 );
495 $top = 1 - ( (int) $viewport[1] / 100 );
496 $props['data-lax-scale'] = $effects['s']['val']['s_dir'] === 'up' ? '(vh*' . $bottom . ') 1,(vh*' . $top . ') ' . $ratio : '(vh*' . $bottom . ') 1,(vh*' . $top . ') ' . number_format(1 / $ratio, 3);
497 if (isset($effects['s']['val']['s_origin'])) {
498 $props['data-box-position'] = self::map_transform_origin($effects['s']['val']['s_origin']);
499 }
500 }
501 if ($has_lax === true) {
502 $props['data-lax'] = 'true';
503 }
504 if ($is_lax !== 'done') {
505 $is_lax = 'done';
506 \Themify_Enqueue_Assets::addPrefetchJs(THEMIFY_URI . '/js/modules/lax.js', THEMIFY_VERSION);
507 }
508 }
509 }
510 if (isset($fields_args['custom_css_id'])) {
511 $props['id'] = $fields_args['custom_css_id'];
512 }
513 return $props;
514 }
515
516 /**
517 * Map animation speed parameter and returns new speed
518 *
519 * @param string $val Initial speed value
520 * @param string $attr attribute name
521 *
522 * @return float|int Returns speed of element based on initial value
523 */
524 private static function map_animation_speed(float $val,string $attr = ''):float {
525 if($val<0 || $val>10){
526 $val=5;
527 }
528 if($attr === 'blur'){
529 $speed = 2*$val;
530 }
531 else{
532 $speed = $val===3?200:($val<3?(70*$val):(670-(10-$val)*70));
533 }
534 return $speed;
535 }
536
537 /**
538 * Map initial origin value and returns transform origin property
539 *
540 * @param string $props Initial origin value
541 *
542 * @return string Returns transform origin value of element based on initial value
543 */
544 private static function map_transform_origin(string $props):string {
545 switch ($props) {
546 case '0,0':
547 $output = 'top left';
548 break;
549
550 case '50,0':
551 $output = 'top center';
552 break;
553
554 case '100,0':
555 $output = 'top right';
556 break;
557
558 case '0,50':
559 $output = 'left center';
560 break;
561
562 case '50,50':
563 $output = 'center center';
564 break;
565
566 case '100,50':
567 $output = 'right center';
568 break;
569
570 case '0,100':
571 $output = 'bottom left';
572 break;
573
574 case '50,100':
575 $output = 'bottom center';
576 break;
577
578 case '100,100':
579 $output = 'bottom right';
580 break;
581
582 default:
583 $perc = \explode(',', $props);
584 $output = $perc[0] . '% ' . $perc[1] . '%';
585 }
586
587 return $output;
588 }
589
590 /**
591 * Return the correct animation css class name
592 * @param string $effect
593 * @return string
594 */
595 public static function parse_animation_effect($settings, array $attr = array(), array $option_names = [] ) {
596 /* backward compatibility for addons */
597 if (!is_array($settings)) {
598 return '';
599 }
600 static $has = null;
601 if ($has === null) {
602 $has = \Themify_Builder_Model::is_animation_active();
603 }
604 if ($has !== false) {
605
606 $option_names = wp_parse_args( $option_names, [
607 'effect' => 'animation_effect',
608 'delay' => 'animation_effect_delay',
609 'repeat' => 'animation_effect_repeat',
610 'effect_hover' => 'hover_animation_effect'
611 ] );
612
613 if (!empty($settings[ $option_names['effect_hover'] ])) {
614 $attr['data-tf-animation_hover'] = $settings[ $option_names['effect_hover'] ];
615 if (isset($attr['class'])) {
616 $attr['class'] .= ' hover-wow';
617 } else {
618 $attr['class'] = 'hover-wow';
619 }
620 if ($has !== 'done') {
621 $has = 'load';
622 }
623 }
624 if (!empty($settings[ $option_names['effect'] ])) {
625 $attr['data-tf-animation'] = $settings[ $option_names['effect'] ];
626 if (!in_array($settings[ $option_names['effect'] ], array('fade-in', 'fly-in', 'slide-up'), true)) {
627 if (isset($attr['class'])) {
628 $attr['class'] .= ' wow';
629 } else {
630 $attr['class'] = 'wow';
631 }
632 }
633 if (!empty($settings[ $option_names['delay'] ])) {
634 $attr['data-tf-animation_delay'] = $settings[ $option_names['delay'] ];
635 }
636 if (!empty($settings[ $option_names['repeat'] ])) {
637 $attr['data-tf-animation_repeat'] = $settings[ $option_names['repeat'] ];
638 }
639 if ($has !== 'done') {
640 $has = 'load';
641 }
642 }
643 if ($has === 'load') {
644 $has = 'done';
645 \Themify_Enqueue_Assets::preFetchAnimtion();
646 }
647 }
648 return $attr;
649 }
650
651 /**
652 * Load builder modules
653 */
654 public static function load_modules(string $mod_name = 'active', bool $ignore = false) {
655 // load modules
656
657 if ($mod_name !== 'active' && $mod_name !== 'all') {
658 if(isset(Themify_Builder_Model::$modules[$mod_name])){//backward will be removed in the future
659 return Themify_Builder_Model::$modules[$mod_name];
660 }
661 $className=self::get_module_class($mod_name);
662 if(class_exists($className,false)){
663 return $className::is_available()?$className:'';
664 }
665 $dir = \Themify_Builder_Model::get_modules($mod_name,$ignore);
666
667 if($dir!==''){
668 if($dir === true ){
669 $dir=THEMIFY_BUILDER_MODULES_DIR;
670 }
671 require $dir . '/module-' . $mod_name . '.php';
672 $className=self::get_module_class($mod_name);//the second call need for backward
673 return isset(Themify_Builder_Model::$modules[$mod_name])?Themify_Builder_Model::$modules[$mod_name]:($className::is_available()?$className:'');
674 }
675 return '';
676 }
677 $modules=[];
678 $items = \Themify_Builder_Model::get_modules($mod_name);
679 foreach ($items as $m => $dir) {
680 if ($dir === true) {
681 $dir = THEMIFY_BUILDER_MODULES_DIR;
682 }
683 require_once $dir . '/module-' . $m . '.php';
684 if(isset(Themify_Builder_Model::$modules[$m])){
685 $item=Themify_Builder_Model::$modules[$m];
686 }else{
687 $className=self::get_module_class($m);
688 if(!$className::is_available()){
689 continue;
690 }
691 $item=$className;
692 }
693 $modules[$m]=$item;
694 }
695 return $modules;
696 }
697
698 public static function get_modules_assets():array {
699 return self::$assets;
700 }
701
702 public static function add_modules_assets($k, $item):void {
703 self::$assets[$k] = $item;
704 }
705
706 public static function render(string $slug, string $mod_id, $builder_id, array &$settings = array(), bool $echo = false) {
707 $template = $slug === 'highlight' || $slug === 'testimonial' || $slug === 'post' || $slug === 'portfolio' ? 'blog' : $slug;
708
709 $vars = array(
710 'module_ID' => $mod_id,
711 'mod_name' => $slug,
712 'builder_id' => $builder_id,
713 'mod_settings' => $settings
714 );
715 $vars = apply_filters('themify_builder_module_render_vars', $vars, $slug);
716
717 return self::retrieve_template('template-' . $template . '.php', $vars, '', '', $echo);
718 }
719
720 /**
721 * If there's not an options tab in Themify Custom Panel meta box already defined for this post type, like "Portfolio Options", add one.
722 *
723 * @since 2.3.8
724 *
725 * @param array $meta_boxes
726 *
727 * @return array
728 */
729 public static function cpt_meta_boxes(array $meta_boxes = array()):array {
730 Themify_Builder_Model::load_general_metabox(); // setup common fields
731
732 $meta_box_id = static::SLUG . '-options';
733 if (!in_array($meta_box_id, wp_list_pluck($meta_boxes, 'id'), true)) {
734 $options = static::get_metabox();
735 if (!empty($options)) {
736 $meta_boxes = array_merge($meta_boxes, array(
737 array(
738 'name' => sprintf(__('%s Options', 'themify'), self::get_module_name()),
739 'id' => $meta_box_id,
740 'options' => $options,
741 'pages' => static::SLUG
742 )
743 ));
744 }
745 }
746
747 return $meta_boxes;
748 }
749
750 public static function get_module_title(array $fields_args,string $key = 'mod_title'):string {
751 if (isset($fields_args[$key]) && $fields_args[$key] !== '') {
752 $titleTag=apply_filters('themify_builder_module_title_tag', 'h3');
753 $startTag='<'.$titleTag.' class="module-title"';
754 if($key!=='' && (Themify_Builder::$frontedit_active === true || Themify_Builder_Model::is_front_builder_activate())){
755 $startTag.=' data-name="'.$key.'" contenteditable="false"';
756 }
757 return $startTag .'>'. $fields_args[$key] . '</'.$titleTag.'>';
758 }
759 return '';
760 }
761
762
763
764 /**
765 * Get query page
766 */
767 public static function get_paged_query():int {
768 global $wp;
769 if (isset($_GET['tf-page']) && is_numeric($_GET['tf-page'])) {
770 $page = (int) $_GET['tf-page'];
771 }
772 else {
773 $qpaged = get_query_var('paged');
774 if (!empty($qpaged)) {
775 $page = (int)$qpaged;
776 }
777 else {
778 $qpaged = wp_parse_args($wp->matched_query);
779 $page = isset($qpaged['paged']) && $qpaged['paged'] > 0?(int)$qpaged['paged']:1;
780 }
781 }
782 return $page;
783 }
784
785 public static function query(array $args):WP_Query {
786 $isPaged = isset($args['paged']) && $args['paged'] > 1;
787 $hasSticky = isset($args['ignore_sticky_posts']) && $args['ignore_sticky_posts'] === false;
788 $maxPage = (int) $args['posts_per_page'];
789 if ($hasSticky === true) {
790 $sticky_posts = get_option('sticky_posts');
791 if (empty($sticky_posts)) {
792 $hasSticky = false;
793 } else {
794 $sticky_posts = array_slice($sticky_posts, 0, $maxPage);
795 }
796 }
797 if ($hasSticky === true && $isPaged === false) {
798 $params = array(
799 'post_status' => 'publish',
800 'post_type' => $args['post_type'],
801 'post__in' => $sticky_posts,
802 'orderby' => 'post__in',
803 'posts_per_page' => $maxPage,
804 'ignore_sticky_posts' => true
805 );
806 if (isset($args['tax_query'])) {
807 $params['tax_query'] = $args['tax_query'];
808 }
809 if (isset($args['meta_key'])) {
810 $params['meta_key'] = $args['meta_key'];
811 }
812 if (isset($args['post__not_in'])) {
813 $params['post__not_in'] = $args['post__not_in'];
814 }
815 $the_query = new WP_Query($params);
816 if ($the_query->post_count < $maxPage) {
817 if (isset($args['post__not_in'])) {
818 $args['post__not_in'] = array_merge($args['post__not_in'],$sticky_posts);;
819 } else {
820 $args['post__not_in'] = $sticky_posts;
821 }
822 $args['ignore_sticky_posts'] = true;
823 $args['posts_per_page'] = $maxPage - $the_query->post_count;
824 $q = new WP_Query($args);
825 $the_query->found_posts = $q->found_posts;
826 $the_query->posts = array_merge($the_query->posts, $q->posts);
827 $the_query->post_count = count($the_query->posts);
828 $the_query->max_num_pages = ceil($the_query->found_posts / $maxPage);
829 unset($q, $args);
830 }
831 } else {
832 if ($isPaged === true && $hasSticky === true) {
833 if (isset($args['post__not_in'])) {
834 $args['post__not_in']= array_merge($args['post__not_in'],$sticky_posts);
835 } else {
836 $args['post__not_in'] = $sticky_posts;
837 }
838 }
839 $the_query = new WP_Query($args);
840 }
841
842 return $the_query;
843 }
844
845 /**
846 * Returns Pagination
847 * @param string Markup to show before pagination links
848 * @param string Markup to show after pagination links
849 * @param object WordPress query object to use
850 * @param original_offset number of posts configured to skip over
851 * @return string
852 */
853 public static function get_pagination($before = '', $after = '', $query = false, $original_offset = 0, $max_page = 0, $paged = 0):string {
854 if (false == $query) {
855 global $wp_query;
856 $query = $wp_query;
857 }
858 if ($paged === 0) {
859 $paged = (int) self::get_paged_query();
860 }
861 if ($max_page === 0) {
862 $numposts = $query->found_posts;
863 $original_offset = (int) $original_offset;
864 // $query->found_posts does not take offset into account, we need to manually adjust that
865 if ($original_offset > 0) {
866 $numposts -= $original_offset;
867 }
868 $max_page = ceil($numposts / $query->query_vars['posts_per_page']);
869 }
870 if ($max_page > 1) {
871 Themify_Builder_Model::loadCssModules('pagenav', THEMIFY_BUILDER_CSS_MODULES . 'pagenav.css', THEMIFY_VERSION);
872 if (!is_string($query) && is_single()) {
873 $query = 'tf-page';
874 }
875 }
876 return themify_get_pagenav($before, $after, $query, $max_page, $paged);
877 }
878
879
880
881
882 /**
883 * Get template for module
884 * @param $mod
885 * @param int $builder_id
886 * @param bool $echo
887 * @return string
888 */
889 public static function template(array &$mod, $builder_id = 0,bool $echo = true) {
890 if (Themify_Builder::$frontedit_active === false) {
891 /* allow addons to control the display of the modules */
892 $display = apply_filters('themify_builder_module_display', true, $mod, $builder_id);
893 if (false === $display || ( isset($mod['mod_settings']['visibility_all']) && $mod['mod_settings']['visibility_all'] === 'hide_all' )) {
894 return '';
895 }
896 }
897 if (!isset($mod['mod_name'])) {
898 return '';
899 }
900 $output = '';
901 $slug = $mod['mod_name'];
902 static $isLoaded = array();
903 self::$isFirstModule = false;
904 if (!isset($isLoaded[$slug])) {//load only the modules in the page
905 $module = self::load_modules($slug);
906 if($module===''){// check whether module active or not
907 return '';
908 }
909 $isLoaded[$slug] = true;
910 if (Themify_Builder::$frontedit_active === false && empty($mod['mod_settings']['_render_plain_content'])) {
911 $assets = \is_string($module) ? $module::get_js_css() : $module->get_assets();
912 static $count = 0; //only need to load the modules styles in concate for the first 2 modules to show LCP asap,even if they should load as async
913 if (!empty($assets)) {
914 $ver = isset($assets['ver']) ? $assets['ver'] : THEMIFY_VERSION;
915 self::$isFirstModule = $count < 2;
916 if (isset($assets['css']) && ($count < 2 || !isset($assets['async']))) {
917 if ($echo === true) {
918 $assets['css'] = (array) $assets['css'];
919 $content_url=content_url();
920 foreach ($assets['css'] as $k => $s) {
921 $key = is_int($k) ? $slug : $k;
922 if ($s === 1) {
923 $s = THEMIFY_BUILDER_CSS_MODULES . $slug . '.css';
924 } else {
925 if (\strpos($s, 'http') === false && \strpos($s,$content_url)===false) {
926 $s = THEMIFY_BUILDER_CSS_MODULES . $s;
927 }
928 if (\strpos($s, '.css') === false) {
929 $s .= '.css';
930 }
931 }
932 \Themify_Builder_Model::loadCssModules($key, $s, $ver);
933 }
934 }
935 unset($assets['css']);
936 }
937 if (isset($assets['js']) || isset($assets['css'])) {
938 if (self::$isFirstModule === true && isset($assets['js'])) {
939 $u = $assets['js'];
940 if ($u === 1) {
941 $u = THEMIFY_BUILDER_JS_MODULES . $slug . '.js';
942 } else {
943 if (\strpos($u, 'http') === false && \strpos($s, content_url())===false) {
944 $u = THEMIFY_BUILDER_JS_MODULES . $u;
945 }
946 if (\strpos($u, '.js') === false) {
947 $u .= '.js';
948 }
949 }
950 \Themify_Enqueue_Assets::addPrefetchJs($u, $ver);
951 }
952 unset($assets['async']);
953 self::$assets[$slug] = $assets;
954 }
955 if ($slug === 'feature' || $slug === 'menu' || $slug === 'tab' || $slug === 'accordion') {
956 \Themify_Enqueue_Assets::addPrefetchJs(THEMIFY_BUILDER_JS_MODULES . $slug . '.js', $ver);
957 }
958 unset($assets, $ver);
959 }
960 ++$count;
961 }
962 }
963 $mod['mod_settings'] = isset($mod['mod_settings']) ? $mod['mod_settings'] : array();
964 if ($echo !== true) {
965 $output .= PHP_EOL; // add line break
966 ob_start();
967 }
968 do_action('themify_builder_background_styling', $builder_id, array('styling' => $mod['mod_settings'], 'mod_name' => $slug, 'element_id' => $mod['element_id']), 'module', '');
969 if ($echo !== true) {
970 $output .= ob_get_clean() . PHP_EOL;
971 }
972 elseif ($slug === 'slider' && Themify_Builder::$frontedit_active === false) {
973 $isEcho = true;
974 $echo = false;
975 }
976 // render the module
977 $res = self::render($slug, 'tb_' . $mod['element_id'], $builder_id, $mod['mod_settings'], $echo);
978 if (!empty($res)) {
979 $output .= $res;
980 }
981 if ($echo === true) {
982 echo $output;
983 }
984 else {
985 if ($slug === 'slider' && Themify_Builder::$frontedit_active === false) {
986 $output = \themify_make_lazy($output, false);
987 if (isset($isEcho) && $isEcho === true) {
988 echo $output;
989 return;
990 }
991 }
992 return $output . PHP_EOL;
993 }
994 }
995
996
997 /**
998 * Retrieve saved settings for a module
999 *
1000 * @return array
1001 */
1002 public static function get_element_settings( $post_id, $element_id ):array {
1003 $data = Themify_Builder::get_builder_modules_list( $post_id );
1004 if ( ! empty( $data ) ) {
1005 foreach ( $data as $module ) {
1006 if ( isset( $module['element_id'], $module['mod_settings'] ) && $module['element_id'] === $element_id ) {
1007 return $module['mod_settings'];
1008 }
1009 }
1010 }
1011
1012 return [];
1013 }
1014
1015 /**
1016 * Get plain content of the module output.
1017 *
1018 * @param array $module
1019 * @return string
1020 */
1021 public static function get_static_content(array $module):string {
1022 if (isset($module['mod_settings'])) {
1023 $module['mod_settings']['_render_plain_content'] = true;
1024 // Remove format text filter including do_shortcode
1025 if (!Themify_Builder_Model::is_front_builder_activate()) {
1026 remove_filter('themify_builder_module_content', array('Themify_Builder_Model', 'format_text'));
1027 }
1028 } else {
1029 $module['mod_settings'] = array('_render_plain_content' => true);
1030 }
1031 return self::template($module, 0, false);
1032 }
1033
1034
1035 /**
1036 * Add z-index option to styling tab
1037 *
1038 * @return array
1039 */
1040 private static function add_zindex_filed(array &$styling) {//@deprecated has been moved to js
1041 $field = self::get_expand('zi',
1042 array(
1043 self::get_zindex('', 'custom_parallax_scroll_zindex')
1044 )
1045 );
1046 if (isset($styling['type']) && 'tabs' === $styling['type']) {
1047 $k = key($styling['options']);
1048 if (isset($styling['options'][$k]['options'])) {
1049 $styling['options'][$k]['options'][] = $field;
1050 } else {
1051 $styling['options'][$k][] = $field;
1052 }
1053 } else {
1054 $styling[] = $field;
1055 }
1056 return $styling;
1057 }
1058
1059 /**
1060 * Add Transform options to styling tab
1061 *
1062 * @return array
1063 */
1064 private static function add_transform_filed(array &$styling) {//@deprecated has been moved to js
1065 $field = self::get_expand('tr', array(
1066 self::get_tab(array(
1067 'n' => array(self::get_transform()),
1068 'h' => array(self::get_transform('', 'tr', 'h'))
1069 ))
1070 ));
1071 if (isset($styling['type']) && 'tabs' === $styling['type']) {
1072 $k = key($styling['options']);
1073 if (isset($styling['options'][$k]['options'])) {
1074 $styling['options'][$k]['options'][] = $field;
1075 } else {
1076 $styling['options'][$k][] = $field;
1077 }
1078 } else {
1079 $styling[] = $field;
1080 }
1081 return $styling;
1082 }
1083
1084 public function __construct($slug) {//@deprecated
1085 if (is_string($slug)) {
1086 $this->slug = $slug;
1087 $this->name = $this->get_name();
1088 } else {
1089 $this->name = $slug['name'];
1090 $this->slug = $slug['slug'];
1091 if (isset($slug['category'])) {
1092 $this->category = $slug['category'];
1093 }
1094 }
1095 Themify_Builder_Model::$modules[$this->slug] = $this;
1096 }
1097
1098 public function get_form_settings($tab = '') {//@deprecated has been moved to js
1099 $styles = $this->get_styling();
1100 if (empty($styles)) {
1101 return array();
1102 }
1103 // Add Z-index to all modules
1104 self::add_zindex_filed($styles);
1105 self::add_transform_filed($styles);
1106 return $styles;
1107 }
1108
1109 /**
1110 * Get Module Title.
1111 *
1112 * @access public
1113 * @param object $module
1114 */
1115 public function get_title($module) {//@deprecated
1116 return '';
1117 }
1118
1119 public function get_assets() {//@deprecated use get_js_css
1120 }
1121
1122 /**
1123 * Get module styling options.
1124 *
1125 * @access public
1126 */
1127 public function get_styling() {//@deprecated has been moved to js
1128 return array();
1129 }
1130
1131 public function get_icon() {//@deprecated use get_module_icon
1132 return '';
1133 }
1134
1135 public function get_name() {//@deprecated use get_module_name
1136 return '';
1137 }
1138
1139 /**
1140 * Get module options.
1141 *
1142 * @access public
1143 */
1144 public function get_options() {//@deprecated has been moved to js.
1145 return array();
1146 }
1147
1148 protected function _visual_template() {//@deprecated has been moved to js.
1149 }
1150
1151 public function get_default_settings() {//@deprecated
1152 return false;
1153 }
1154
1155 public function get_default_args() {//@deprecated
1156 return array();
1157 }
1158
1159 public function get_live_default() {//@deprecated has been moved to js.
1160 return false;
1161 }
1162
1163 public function get_visual_type() {//@deprecated has been moved to js.
1164 return 'live';
1165 }
1166
1167 public function get_group() {//@deprecated has been moved to js.
1168 return false;
1169 }
1170
1171 public function print_template($echo = false, $ignoreLocal = false) {//@deprecated has been moved to js
1172 }
1173
1174
1175 public static function get_element_attributes(array $props) {//@deprecated use themify_get_element_attributes
1176 return themify_get_element_attributes($props);
1177 }
1178
1179 //add inline editing fields
1180 public static function add_inline_edit_fields( $name, $condition = true, $hasEditor = false, $repeat = false, $index = -1, $echo = true) {//@deprecated
1181 return '';
1182 }
1183
1184
1185
1186 public static function get_module_args($key = '') {//@deprecated
1187 return apply_filters('themify_builder_module_args', array('before_title' => '<h3 class="module-title">', 'after_title' => '</h3>'));
1188 }
1189
1190 /**
1191 * Render a module, as a plain text
1192 *
1193 * @return string
1194 */
1195 public function get_plain_text($module) {//@deprecated
1196 $options = $this->get_options();
1197 if (empty($options)) {
1198 return '';
1199 }
1200 $out = array();
1201
1202 foreach ($options as $field) {
1203 // sanitization, check for existence of needed keys
1204 if (!isset($field['type'], $field['id'], $module[$field['id']])) {
1205 continue;
1206 }
1207 // text, textarea, and wp_editor field types
1208 if (in_array($field['type'], array('text', 'textarea', 'wp_editor'), true)) {
1209 $out[] = $module[$field['id']];
1210 }
1211 // builder field type
1212 elseif ($field['type'] === 'builder' && is_array($module[$field['id']])) {
1213 // gather text field types included in the "builder" field type
1214 $text_fields = array();
1215 foreach ($field['options'] as $row_field) {
1216 if (isset($row_field['type']) && in_array($row_field['type'], array('text', 'textarea', 'wp_editor'), true)) {
1217 $text_fields[] = $row_field['id'];
1218 }
1219 }
1220 foreach ($module[$field['id']] as $row) {
1221 // separate fields from the row that have text fields
1222 $texts = array_intersect_key($row, array_flip($text_fields));
1223 // add them to the output
1224 $out = array_merge(array_values($texts), $out);
1225 }
1226 }
1227 }
1228
1229 return implode(' ', $out);
1230 }
1231
1232
1233 public static function get_pagenav($before = '', $after = '', $query = false, $original_offset = 0) {//backward compatibility for addons,deprecated use get_pagination
1234 return self::get_pagination($before, $after, $query, $original_offset);
1235 }
1236
1237 public function get_plain_content($module) {//@deprecated use get_static_content
1238 return self::get_static_content($module);
1239 }
1240
1241 public static function get_tab(array $options, $fullwidth = false, $cl = '') {//@deprecated has been moved to js
1242 $opt = array(
1243 'type' => 'tabs',
1244 'options' => $options
1245 );
1246 if ($fullwidth === true) {
1247 if ($cl !== '') {
1248 $cl .= ' tb_tabs_fullwidth';
1249 } else {
1250 $cl = 'tb_tabs_fullwidth';
1251 }
1252 }
1253 if ($cl !== '') {
1254 $opt['class'] = $cl;
1255 }
1256 return $opt;
1257 }
1258
1259 public static function get_seperator($label = false) {//@deprecated has been moved to js
1260 $opt = array(
1261 'type' => 'separator'
1262 );
1263 if ($label !== false) {
1264 $opt['label'] = $label;
1265 }
1266 return $opt;
1267 }
1268
1269 public static function get_expand($label, array $options) {//@deprecated has been moved to js
1270 return array(
1271 'type' => 'expand',
1272 'label' => $label,
1273 'options' => $options
1274 );
1275 }
1276
1277 protected static function get_font_family($selector = '', $id = 'font_family', $state = '') {//@deprecated has been moved to js
1278 if ($state !== '') {
1279 $id .= '_' . $state;
1280 }
1281 $res = array(
1282 'id' => $id,
1283 'type' => 'font_select',
1284 'prop' => 'font-family',
1285 'selector' => $selector
1286 );
1287 if ($state === 'h' || $state === 'hover') {
1288 $res['ishover'] = true;
1289 }
1290 return $res;
1291 }
1292
1293 protected static function get_element_font_weight($selector = '', $id = 'element_font_weight', $state = '') {//backward compatibility
1294 }
1295
1296 protected static function get_font_size($selector = '', $id = 'font_size', $label = '', $state = '') {//@deprecated has been moved to js
1297 if ($state !== '') {
1298 $id .= '_' . $state;
1299 }
1300 $res = array(
1301 'id' => $id,
1302 'type' => 'fontSize',
1303 'selector' => $selector,
1304 'prop' => 'font-size'
1305 );
1306 if ($label !== '') {
1307 $res['label'] = $label;
1308 }
1309 if ($state === 'h' || $state === 'hover') {
1310 $res['ishover'] = true;
1311 }
1312 return $res;
1313 }
1314
1315 protected static function get_line_height($selector = '', $id = 'line_height', $state = '') {//@deprecated has been moved to js
1316 if ($state !== '') {
1317 $id .= '_' . $state;
1318 }
1319 $res = array(
1320 'id' => $id,
1321 'type' => 'lineHeight',
1322 'selector' => $selector,
1323 'prop' => 'line-height'
1324 );
1325 if ($state === 'h' || $state === 'hover') {
1326 $res['ishover'] = true;
1327 }
1328 return $res;
1329 }
1330
1331 protected static function get_letter_spacing($selector = '', $id = 'letter_spacing', $state = '') {//@deprecated has been moved to js
1332 if ($state !== '') {
1333 $id .= '_' . $state;
1334 }
1335 $res = array(
1336 'id' => $id,
1337 'type' => 'letterSpace',
1338 'selector' => $selector,
1339 'prop' => 'letter-spacing'
1340 );
1341 if ($state === 'h' || $state === 'hover') {
1342 $res['ishover'] = true;
1343 }
1344 return $res;
1345 }
1346
1347 protected static function get_flex_align($selector = '', $id = 'align', $state = '') {//@deprecated has been moved to js
1348 if ($state !== '') {
1349 $id .= '_' . $state;
1350 }
1351 $res = array(
1352 'id' => $id,
1353 'label' => 't_a',
1354 'type' => 'icon_radio',
1355 'falign' => true,
1356 'prop' => 'align-content',
1357 'selector' => $selector
1358 );
1359 if ($state === 'h' || $state === 'hover') {
1360 $res['ishover'] = true;
1361 }
1362 return $res;
1363 }
1364
1365 protected static function get_flex_align_items($selector = '', $id = 'align', $state = '') {//@deprecated has been moved to js
1366 if ($state !== '') {
1367 $id .= '_' . $state;
1368 }
1369 $res = array(
1370 'id' => $id,
1371 'label' => 't_a',
1372 'type' => 'icon_radio',
1373 'falign' => true,
1374 'prop' => 'align-items',
1375 'selector' => $selector
1376 );
1377 if ($state === 'h' || $state === 'hover') {
1378 $res['ishover'] = true;
1379 }
1380 return $res;
1381 }
1382
1383 protected static function get_flex_align_content($selector = '', $id = 'align', $state = '') {//@deprecated has been moved to js
1384 if ($state !== '') {
1385 $id .= '_' . $state;
1386 }
1387 $res = array(
1388 'id' => $id,
1389 'label' => 't_a',
1390 'type' => 'icon_radio',
1391 'falign' => true,
1392 'prop' => 'align-content',
1393 'selector' => $selector
1394 );
1395 if ($state === 'h' || $state === 'hover') {
1396 $res['ishover'] = true;
1397 }
1398 return $res;
1399 }
1400
1401 protected static function get_text_align($selector = '', $id = 'text_align', $state = '') {//@deprecated has been moved to js
1402 if ($state !== '') {
1403 $id .= '_' . $state;
1404 }
1405 $res = array(
1406 'id' => $id,
1407 'label' => 't_a',
1408 'type' => 'icon_radio',
1409 'aligment' => true,
1410 'prop' => 'text-align',
1411 'selector' => $selector
1412 );
1413 if ($state === 'h' || $state === 'hover') {
1414 $res['ishover'] = true;
1415 }
1416 return $res;
1417 }
1418
1419 protected static function get_text_transform($selector = '', $id = 'text_transform', $state = '') {//@deprecated has been moved to js
1420 if ($state !== '') {
1421 $id .= '_' . $state;
1422 }
1423 $res = array(
1424 'id' => $id,
1425 'label' => 't_t',
1426 'type' => 'icon_radio',
1427 'text_transform' => true,
1428 'prop' => 'text-transform',
1429 'selector' => $selector
1430 );
1431 if ($state === 'h' || $state === 'hover') {
1432 $res['ishover'] = true;
1433 }
1434 return $res;
1435 }
1436
1437 protected static function get_text_decoration($selector = '', $id = 'text_decoration', $state = '') {//@deprecated has been moved to js
1438 if ($state !== '') {
1439 $id .= '_' . $state;
1440 }
1441 $res = array(
1442 'id' => $id,
1443 'type' => 'icon_radio',
1444 'label' => 't_d',
1445 'text_decoration' => true,
1446 'prop' => 'text-decoration',
1447 'selector' => $selector
1448 );
1449 if ($state === 'h' || $state === 'hover') {
1450 $res['ishover'] = true;
1451 }
1452 return $res;
1453 }
1454
1455 protected static function get_font_style($selector = '', $id = 'font_style', $id2 = 'font_weight', $state = '') {//@deprecated has been moved to js
1456 if ($state !== '') {
1457 $id .= '_' . $state;
1458 $id2 .= '_' . $state;
1459 }
1460 $res = array(
1461 'id' => $id,
1462 'id2' => $id2,
1463 'type' => 'fontStyle',
1464 'prop' => 'font-style',
1465 'selector' => $selector
1466 );
1467 if ($state === 'h' || $state === 'hover') {
1468 $res['ishover'] = true;
1469 }
1470
1471 return $res;
1472 }
1473
1474 protected static function get_color($selector = '', $id = '', $label = null, $prop = 'color', $state = '') {//@deprecated has been moved to js
1475 if ($state !== '') {
1476 $id .= '_' . $state;
1477 }
1478 if ($prop === null) {
1479 $prop = 'color';
1480 }
1481 $color = array(
1482 'id' => $id,
1483 'type' => 'color',
1484 'prop' => $prop,
1485 'selector' => $selector
1486 );
1487 if ($label !== null) {
1488 $color['label'] = $label;
1489 }
1490 if ($state === 'h' || $state === 'hover') {
1491 $color['ishover'] = true;
1492 }
1493 return $color;
1494 }
1495
1496 protected static function get_image($selector = '', $id = 'background_image', $colorId = 'background_color', $repeatId = 'background_repeat', $posId = 'background_position', $state = '') {//@deprecated has been moved to js
1497 if ($state !== '') {
1498 $id .= '_' . $state;
1499 if ($colorId !== '') {
1500 $colorId .= '_' . $state;
1501 }
1502 if ($repeatId !== '') {
1503 $repeatId .= '_' . $state;
1504 }
1505 if ($posId !== '') {
1506 $posId .= '_' . $state;
1507 }
1508 }
1509 $res = array(
1510 'id' => $id,
1511 'type' => 'imageGradient',
1512 'prop' => 'background-image',
1513 'selector' => $selector,
1514 'origId' => $id,
1515 'colorId' => $colorId,
1516 'repeatId' => $repeatId,
1517 'posId' => $posId
1518 );
1519 if ($state === 'h' || $state === 'hover') {
1520 $res['ishover'] = true;
1521 }
1522 return $res;
1523 }
1524
1525 // CSS Filters
1526 protected static function get_blend($selector = '', $id = 'bl_m', $state = '', $filters_id = 'css_f') {//@deprecated has been moved to js
1527 if ($state !== '') {
1528 $id .= '_' . $state;
1529 $filters_id .= '_' . $state;
1530 }
1531 $res = array(
1532 'id' => $filters_id,
1533 'mid' => $id,
1534 'type' => 'filters',
1535 'prop' => 'filter',
1536 'selector' => $selector
1537 );
1538 if ($state === 'h' || $state === 'hover') {
1539 $res['ishover'] = true;
1540 }
1541 return $res;
1542 }
1543
1544 protected static function get_repeat($selector = '', $id = 'background_repeat', $state = '') {//@deprecated has been moved to js
1545 if ($state !== '') {
1546 $id .= '_' . $state;
1547 }
1548 $res = array(
1549 'id' => $id,
1550 'type' => 'select',
1551 'repeat' => true,
1552 'prop' => 'background-mode',
1553 'selector' => $selector,
1554 'wrap_class' => 'tb_group_element_image tb_image_options'
1555 );
1556 if ($state === 'h' || $state === 'hover') {
1557 $res['ishover'] = true;
1558 }
1559 return $res;
1560 }
1561
1562 protected static function get_position($selector = '', $id = 'background_position', $state = '') {//@deprecated has been moved to js
1563 if ($state !== '') {
1564 $id .= '_' . $state;
1565 }
1566 $res = array(
1567 'id' => $id,
1568 'type' => 'position_box',
1569 'prop' => 'background-position',
1570 'selector' => $selector
1571 );
1572 if ($state === 'h' || $state === 'hover') {
1573 $res['ishover'] = true;
1574 }
1575 return $res;
1576 }
1577
1578 protected static function get_padding($selector = '', $id = 'padding', $state = '') {//@deprecated has been moved to js
1579 if ($id === '') {
1580 $id = 'padding';
1581 }
1582 if ($state !== '') {
1583 $id .= '_' . $state;
1584 }
1585 $res = array(
1586 'id' => $id,
1587 'type' => 'padding',
1588 'prop' => 'padding',
1589 'selector' => $selector
1590 );
1591 if ($state === 'h' || $state === 'hover') {
1592 $res['ishover'] = true;
1593 }
1594 return $res;
1595 }
1596
1597 protected static function get_margin($selector = '', $id = 'margin', $state = '') {//@deprecated has been moved to js
1598 if ($id === '') {
1599 $id = 'margin';
1600 }
1601 if ($state !== '') {
1602 $id .= '_' . $state;
1603 }
1604 $res = array(
1605 'id' => $id,
1606 'type' => 'margin',
1607 'prop' => 'margin',
1608 'selector' => $selector
1609 );
1610 if ($state === 'h' || $state === 'hover') {
1611 $res['ishover'] = true;
1612 }
1613 return $res;
1614 }
1615
1616 protected static function get_gap($selector = '', $id = 'gap', $prop = 'gap', $state = '', $percent = false, $label = '') {//@deprecated has been moved to js
1617 if ($id === '') {
1618 $id = 'gap';
1619 }
1620 if ($state !== '') {
1621 $id .= '_' . $state;
1622 }
1623 $units = array(
1624 'px' => array(
1625 'max' => 1000
1626 ),
1627 'em' => array(
1628 'max' => 50
1629 )
1630 );
1631 if ($percent !== false && $percent !== '') {
1632 $units['%'] = $percent === true ? '' : $percent;
1633 }
1634 $res = array(
1635 'id' => $id,
1636 'type' => 'range',
1637 'label' => $label === '' ? ($prop === 'column-gap' ? 'ng' : ($prop === 'row-gap' ? 'rg' : 'gap')) : $label,
1638 'prop' => $prop,
1639 'selector' => $selector,
1640 'grid_gap' => 1,
1641 'units' => $units
1642 );
1643 if ($state === 'h' || $state === 'hover') {
1644 $res['ishover'] = true;
1645 }
1646 return $res;
1647 }
1648
1649 protected static function get_column_gap($selector = '', $id = 'cgap', $state = '', $percent = false, $label = '') {//@deprecated has been moved to js
1650 if ($id === '') {
1651 $id = 'cgap';
1652 }
1653 return self::get_gap($selector, $id, 'column-gap', $state, $percent, $label);
1654 }
1655
1656 protected static function get_row_gap($selector = '', $id = 'rgap', $state = '', $percent = false, $label = '') {//@deprecated has been moved to js
1657 if ($id === '') {
1658 $id = 'rgap';
1659 }
1660 return self::get_gap($selector, $id, 'row-gap', $state, $percent, $label);
1661 }
1662
1663 protected static function get_margin_top_bottom_opposity($selector = '', $topId = 'margin-top', $bottomId = 'margin-bottom', $state = '') {//@deprecated has been moved to js
1664 if ($state !== '') {
1665 $topId .= '_' . $state;
1666 $bottomId .= '_' . $state;
1667 }
1668 $res = array(
1669 'topId' => $topId,
1670 'bottomId' => $bottomId,
1671 'type' => 'margin_opposity',
1672 'prop' => '',
1673 'selector' => $selector
1674 );
1675 if ($state === 'h' || $state === 'hover') {
1676 $res['ishover'] = true;
1677 }
1678 return $res;
1679 }
1680
1681 protected static function get_border($selector = '', $id = 'border', $state = '') {//@deprecated has been moved to js
1682 if ($state !== '') {
1683 $id .= '_' . $state;
1684 }
1685 $res = array(
1686 'id' => $id,
1687 'type' => 'border',
1688 'prop' => 'border',
1689 'selector' => $selector
1690 );
1691 if ($state === 'h' || $state === 'hover') {
1692 $res['ishover'] = true;
1693 }
1694 return $res;
1695 }
1696
1697 protected static function get_outline($selector = '', $id = 'o', $state = '') {//@deprecated has been moved to js
1698 if ($state !== '') {
1699 $id .= '_' . $state;
1700 }
1701 $res = array(
1702 'id' => $id,
1703 'type' => 'outline',
1704 'prop' => 'outline',
1705 'selector' => $selector
1706 );
1707 if ($state === 'h' || $state === 'hover') {
1708 $res['ishover'] = true;
1709 }
1710 return $res;
1711 }
1712
1713 protected static function get_aspect_ratio($selector = '', $id = 'asp', $state = '') {//@deprecated has been moved to js
1714 if ($state !== '') {
1715 $id .= '_' . $state;
1716 }
1717
1718 $res = array(
1719 'id' => $id,
1720 'type' => 'aspectRatio',
1721 'prop' => 'aspect-ratio',
1722 'selector' => $selector,
1723 );
1724 if ($state === 'h' || $state === 'hover') {
1725 $res['ishover'] = true;
1726 }
1727 return $res;
1728 }
1729
1730 protected static function get_multi_columns_count($selector = '', $id = 'column', $state = '') {//@deprecated has been moved to js
1731 if ($state !== '') {
1732 $id .= '_' . $state;
1733 }
1734 $res = array(
1735 'id' => $id . '_count',
1736 'type' => 'multiColumns',
1737 'prop' => 'column-count',
1738 'selector' => $selector
1739 );
1740 if ($state === 'h' || $state === 'hover') {
1741 $res['ishover'] = true;
1742 }
1743 return $res;
1744 }
1745
1746 protected static function get_color_type($selector = '', $state = '', $id = '', $solid_id = '', $gradient_id = '') {//@deprecated has been moved to js
1747 if ($state !== '') {
1748 if ($id === '') {
1749 $id = 'f_c_t';
1750 }
1751 if ($solid_id === '') {
1752 $solid_id = 'f_c';
1753 }
1754 if ($gradient_id === '') {
1755 $gradient_id = 'f_g_c';
1756 }
1757 $id .= '_' . $state;
1758 $solid_id .= '_' . $state;
1759 $gradient_id .= '_' . $state;
1760 } else {
1761 if ($id === '') {
1762 $id = 'font_color_type';
1763 }
1764 if ($solid_id === '') {
1765 $solid_id = 'font_color';
1766 }
1767 if ($gradient_id === '') {
1768 $gradient_id = 'font_gradient_color';
1769 }
1770 }
1771
1772 $res = array(
1773 'id' => $id,
1774 'type' => 'fontColor',
1775 'selector' => $selector,
1776 'prop' => 'radio',
1777 's' => $solid_id,
1778 'g' => $gradient_id
1779 );
1780 if ($state === 'h' || $state === 'hover') {
1781 $res['ishover'] = true;
1782 }
1783 return $res;
1784 }
1785
1786 // Get Rounded Corners
1787 protected static function get_border_radius($selector = '', $id = 'b_ra', $state = '') {//@deprecated has been moved to js
1788 if ($state !== '') {
1789 $id .= '_' . $state;
1790 }
1791 $res = array(
1792 'id' => $id,
1793 'type' => 'border_radius',
1794 'prop' => 'border-radius',
1795 'selector' => $selector
1796 );
1797 if ($state === 'h' || $state === 'hover') {
1798 $res['ishover'] = true;
1799 }
1800 return $res;
1801 }
1802
1803 // Get Box Shadow
1804 protected static function get_box_shadow($selector = '', $id = 'b_sh', $state = '') {//@deprecated has been moved to js
1805 if ($state !== '') {
1806 $id .= '_' . $state;
1807 }
1808 $res = array(
1809 'id' => $id,
1810 'type' => 'box_shadow',
1811 'prop' => 'box-shadow',
1812 'selector' => $selector
1813 );
1814 if ($state === 'h' || $state === 'hover') {
1815 $res['ishover'] = true;
1816 }
1817 return $res;
1818 }
1819
1820 // Get Text Shadow
1821 protected static function get_text_shadow($selector = '', $id = 'text-shadow', $state = '') {//@deprecated has been moved to js
1822 if ($state !== '') {
1823 $id .= '_' . $state;
1824 }
1825 $res = array(
1826 'id' => $id,
1827 'type' => 'text_shadow',
1828 'prop' => 'text-shadow',
1829 'selector' => $selector
1830 );
1831 if ($state === 'h' || $state === 'hover') {
1832 $res['ishover'] = true;
1833 }
1834 return $res;
1835 }
1836
1837 // Get z-index
1838 protected static function get_zindex($selector = '', $id = 'zi') {//@deprecated has been moved to js
1839 return array(
1840 'id' => $id,
1841 'selector' => $selector,
1842 'prop' => 'z-index',
1843 'type' => 'zIndex'
1844 );
1845 }
1846
1847 protected static function get_width($selector = '', $id = 'width', $state = '') {//@deprecated has been moved to js
1848 if ($state !== '') {
1849 $id .= '_' . $state;
1850 }
1851
1852 $res = array(
1853 'id' => $id,
1854 'type' => 'width',
1855 'prop' => 'width',
1856 'selector' => $selector,
1857 );
1858 if ($state === 'h' || $state === 'hover') {
1859 $res['ishover'] = true;
1860 }
1861 return $res;
1862 }
1863
1864 // Get Height Options plus Auto Height
1865 protected static function get_height($selector = '', $id = 'ht', $state = '', $minH = '', $maxH = '') {//@deprecated has been moved to js
1866 if ($state !== '') {
1867 $id .= '_' . $state;
1868 }
1869
1870 $res = array(
1871 'id' => $id,
1872 'type' => 'height',
1873 'prop' => 'height',
1874 'selector' => $selector
1875 );
1876 if ($minH !== '') {
1877 $res['minid'] = $minH;
1878 }
1879 if ($maxH !== '') {
1880 $res['maxid'] = $maxH;
1881 }
1882 if ($state === 'h' || $state === 'hover') {
1883 $res['ishover'] = true;
1884 }
1885 return $res;
1886 }
1887
1888 // Get CSS Position
1889 protected static function get_css_position($selector = '', $id = 'po', $state = '') {//@deprecated has been moved to js
1890 if ($state !== '') {
1891 $id .= '_' . $state;
1892 }
1893 $res = array(
1894 'id' => $id,
1895 'type' => 'position',
1896 'prop' => 'position',
1897 'selector' => $selector
1898 );
1899 if ($state === 'h' || $state === 'hover') {
1900 $res['ishover'] = true;
1901 }
1902 return $res;
1903 }
1904
1905 // CSS Display
1906 protected static function get_display($selector = '', $id = 'disp') {//@deprecated has been moved to js
1907 $va_id = $id . '_va';
1908 $res = array();
1909 $res[] = array(
1910 'id' => $id,
1911 'label' => 'disp',
1912 'type' => 'select',
1913 'prop' => 'display',
1914 'selector' => $selector,
1915 'binding' => array(
1916 'empty' => array('hide' => $va_id),
1917 'block' => array('hide' => $va_id),
1918 'none' => array('hide' => $va_id),
1919 'inline-block' => array('show' => $va_id)
1920 ),
1921 'display' => true
1922 );
1923 $res[] = array(
1924 'id' => $va_id,
1925 'label' => 'valign',
1926 'type' => 'select',
1927 'prop' => 'vertical-align',
1928 'selector' => $selector,
1929 'origID' => $id,
1930 'va_display' => true
1931 );
1932 return $res;
1933 }
1934
1935 // Get transform
1936 protected static function get_transform($selector = '', $id = 'tr', $state = '') {//@deprecated has been moved to js
1937 if ($state !== '') {
1938 $id .= '-' . $state;
1939 }
1940 $res = array(
1941 'id' => $id,
1942 'type' => 'transform',
1943 'prop' => 'transform',
1944 'selector' => $selector
1945 );
1946 if ($state === 'h' || $state === 'hover') {
1947 $res['ishover'] = true;
1948 }
1949 return $res;
1950 }
1951
1952
1953 protected static function get_min_width($selector = '', $id = 'mi_w') {//deprecated, included in width field
1954 return array();
1955 }
1956
1957 // Get Min Height Option
1958 protected static function get_min_height($selector = '', $id = 'mi_h') {//deprecated, included in height field
1959 return array();
1960 }
1961
1962 // Get Max Height Option
1963 protected static function get_max_height($selector = '', $id = 'mx_h') {//deprecated, included in height field
1964 return array();
1965 }
1966
1967
1968 protected static function get_margin_top($selector = '', $id = 'margin-top', $state = '') {//deprecated
1969 return array();
1970 }
1971
1972 protected static function get_margin_bottom($selector = '', $id = 'margin-bottom', $state = '') {//deprecated
1973 return array();
1974 }
1975
1976 protected static function get_multi_columns_gap($selector = '', $id = 'column', $state = '') {//backward compatibility
1977 }
1978
1979 protected static function get_multi_columns_divider($selector = '', $id = 'column', $state = '') {//backward compatibility
1980 }
1981
1982 protected static function get_heading_margin_multi_field($selector = '', $h_level = 'h1', $margin_side = 'top', $state = '', $id = '') {//deprecated use get_margin_top_bottom_opposity
1983 $id = $id === '' ? $h_level : $id;
1984 if ($h_level === '') {
1985 $h_level .= ' ';
1986 }
1987 $id = $id . '_margin_' . $margin_side;
1988 if ($state !== '') {
1989 $id .= '_' . $state;
1990 }
1991 if ($selector !== '' && is_array($selector)) {
1992 foreach ($selector as $key => $val) {
1993 $selector[$key] = $val . ' ' . $h_level;
1994 }
1995 } else {
1996 $selector .= ' ' . $h_level;
1997 }
1998 $res = array(
1999 'label' => ('top' === $margin_side ? 'm' : ''),
2000 'id' => $id,
2001 'type' => 'range',
2002 'prop' => 'margin-' . $margin_side,
2003 'selector' => $selector,
2004 'description' => '<span class="tb_range_after">' . sprintf(__('%s', 'themify'), $margin_side) . '</span>',
2005 'units' => array(
2006 'px' => array(
2007 'min' => -1000,
2008 'max' => 1000
2009 ),
2010 'em' => array(
2011 'min' => -50,
2012 'max' => 50
2013 ),
2014 '%' => ''
2015 )
2016 );
2017 if ($state === 'h' || $state === 'hover') {
2018 $res['ishover'] = true;
2019 }
2020 return $res;
2021 }
2022
2023 protected function module_title_custom_style() {//@deprecated has been moved to js
2024 return array(
2025 // Background
2026 self::get_expand('bg', array(
2027 self::get_tab(array(
2028 'n' => array(
2029 self::get_color('.module .module-title', 'background_color_module_title', 'bg_c', 'background-color')
2030 ),
2031 'h' => array(
2032 self::get_color('.module .module-title', 'bg_c_m_t', 'bg_c', 'background-color', 'h')
2033 )
2034 ))
2035 )),
2036 // Font
2037 self::get_expand('f', array(
2038 self::get_tab(array(
2039 'n' => array(
2040 self::get_font_family('.module .module-title', 'font_family_module_title'),
2041 self::get_color('.module .module-title', 'font_color_module_title'),
2042 self::get_font_size('.module .module-title', 'font_size_module_title'),
2043 self::get_line_height('.module .module-title', 'line_height_module_title'),
2044 self::get_text_align('.module .module-title', 'text_align_module_title'),
2045 self::get_text_shadow('.module .module-title', 't_sh_m_t'),
2046 ),
2047 'h' => array(
2048 self::get_font_family('.module .module-title', 'f_f_m_t', 'h'),
2049 self::get_color('.module .module-title', 'f_c_m_t', null, null, 'h'),
2050 self::get_font_size('.module .module-title', 'f_s_m_t', '', 'h'),
2051 self::get_text_shadow('.module .module-title', 't_sh_m_t', 'h'),
2052 )
2053 ))
2054 ))
2055 );
2056 }
2057
2058 /**
2059 * Returns a list of image/imageGradient fields in module's Styling
2060 */
2061 public static function get_styling_image_fields() : array {
2062 return [];
2063 }
2064
2065 /**
2066 * Return a list of module fields that need translating in WPML
2067 *
2068 * Format:
2069 * [
2070 * 'value' => String,
2071 * 'title' => Optional title displayed in WPML translation screeen
2072 * 'id' => field ID,
2073 * 'type' => 'TEXTAREA', 'VISUAL', 'LINK', or default: 'LINE'
2074 * ]
2075 *
2076 * @note: "link" field is being registered as LINE instead, so they show up in translation editor
2077 */
2078 public static function get_translatable_fields( $module, $classname ) : array {
2079 $fields = [];
2080 foreach ( array_merge( $classname::get_translatable_text_fields( $module ), $classname::get_translatable_link_fields( $module ) ) as $field_id ) {
2081 if ( isset( $module['mod_settings'][ $field_id ] ) ) {
2082 $fields[] = [
2083 'value' => $module['mod_settings'][ $field_id ],
2084 'id' => $field_id
2085 ];
2086 }
2087 }
2088 foreach ( $classname::get_translatable_textarea_fields( $module ) as $field_id ) {
2089 if ( isset( $module['mod_settings'][ $field_id ] ) ) {
2090 $fields[] = [
2091 'value' => $module['mod_settings'][ $field_id ],
2092 'id' => $field_id,
2093 'type' => 'TEXTAREA'
2094 ];
2095 }
2096 }
2097
2098 foreach ( $classname::get_translatable_repeatable_fields( $module ) as $repeater_field_id => $repeater_field_childs ) {
2099 if ( ! empty( $module['mod_settings'][ $repeater_field_id ] ) ) {
2100 foreach ( $module['mod_settings'][ $repeater_field_id ] as $repeater_row_index => &$repeater_row_value ) {
2101 foreach ( $repeater_field_childs as $item_id => $item_type ) {
2102 if ( isset( $repeater_row_value[ $item_id ] ) ) {
2103 $fields[] = [
2104 'value' => $repeater_row_value[ $item_id ],
2105 'id' => $repeater_field_id . '::' . $repeater_row_index . '::' . $item_id,
2106 'type' => $item_type === 'LINK' ? 'LINE' : $item_type
2107 ];
2108 }
2109 }
2110 }
2111 }
2112 }
2113
2114 return $fields;
2115 }
2116
2117 /**
2118 * Translate module data
2119 */
2120 public static function translate_module( $module, $translations ) {
2121 /* convert $translation array for repeatable fields */
2122 $m = Themify_Builder_WPML_Integration::get_module( $module['mod_name'] );
2123 if ( $m ) {
2124 $repeter_fields = $m::get_translatable_repeatable_fields( $module );
2125 if ( ! empty( $repeter_fields ) ) {
2126 foreach ( $repeter_fields as $repeater_field_id => $repeater_field_childs ) {
2127 foreach ( $translations as $translation_key => $translation_value ) {
2128 if ( str_contains( $translation_key, $repeater_field_id . '::' ) ) { // this value is for a repeatable field, need to unpack
2129 list( $_repeater_id, $row_id, $item_id ) = explode( '::', $translation_key );
2130 if ( isset( $module['mod_settings'][ $repeater_field_id ][ $row_id ][ $item_id ] ) ) {
2131 $module['mod_settings'][ $repeater_field_id ][ $row_id ][ $item_id ] = $translation_value;
2132 unset( $translations[ $translation_key ] );
2133 }
2134 }
2135 }
2136 }
2137 }
2138 }
2139
2140 $module['mod_settings'] = array_merge( $module['mod_settings'], $translations );
2141 return $module;
2142 }
2143
2144 public static function get_translatable_text_fields( $module ) {
2145 return [];
2146 }
2147
2148 public static function get_translatable_textarea_fields( $module ) {
2149 return [];
2150 }
2151
2152 public static function get_translatable_link_fields( $module ) {
2153 return [];
2154 }
2155
2156 public static function get_translatable_repeatable_fields( $module ) {
2157 return [];
2158 }
2159 }
2160
2161 if (!function_exists('themify_builder_testimonial_author_name')) :
2162
2163 function themify_builder_testimonial_author_name($post, $show_author) {
2164 $out = '';
2165 if ('yes' === $show_author) {
2166 if ($author = get_post_meta($post->ID, '_testimonial_name', true))
2167 $out = '<span class="dash"></span><cite class="testimonial-name">' . $author . '</cite> <br/>';
2168
2169 if ($position = get_post_meta($post->ID, '_testimonial_position', true))
2170 $out .= '<em class="testimonial-title">' . $position;
2171
2172 if ($link = get_post_meta($post->ID, '_testimonial_link', true)) {
2173 if ($position) {
2174 $out .= ', ';
2175 } else {
2176 $out .= '<em class="testimonial-title">';
2177 }
2178 $out .= '<a href="' . esc_url($link) . '">';
2179 }
2180
2181 if ($company = get_post_meta($post->ID, '_testimonial_company', true))
2182 $out .= $company;
2183 else
2184 $out .= $link;
2185
2186 if ($link)
2187 $out .= '</a>';
2188
2189 $out .= '</em>';
2190 }
2191 return $out;
2192 }
2193
2194 endif;
2195