PluginProbe
Page Builder: Pagelayer – Drag and Drop website builder / 2.2.0
Page Builder: Pagelayer – Drag and Drop website builder v2.2.0
2.2.1 2.2.0 2.1.9 2.1.8 2.1.7 2.1.6 2.1.5 2.1.4 2.1.3 trunk 0.9.0 0.9.1 0.9.2 0.9.3 0.9.4 0.9.5 0.9.6 0.9.7 0.9.8 0.9.9 1.0.0 1.0.2 1.0.3 1.0.4 1.0.5 All 129 releases
pagelayer / main / shortcode_functions.php

shortcode_functions.php in Page Builder: Pagelayer – Drag and Drop website builder 2.2.0, at main/shortcode_functions.php

2,025 lines 56.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 //////////////////////////////////////////////////////////////
4 //===========================================================
5 // class.php
6 //===========================================================
7 // PAGELAYER
8 // Inspired by the DESIRE to be the BEST OF ALL
9 // ----------------------------------------------------------
10 // Started by: Pulkit Gupta
11 // Date: 23rd Jan 2017
12 // Time: 23:00 hrs
13 // Site: http://pagelayer.com/wordpress (PAGELAYER)
14 // ----------------------------------------------------------
15 // Please Read the Terms of use at http://pagelayer.com/tos
16 // ----------------------------------------------------------
17 //===========================================================
18 // (c)Pagelayer Team
19 //===========================================================
20 //////////////////////////////////////////////////////////////
21
22 // Are we being accessed directly ?
23 if(!defined('PAGELAYER_VERSION')) {
24 exit('Hacking Attempt !');
25 }
26
27 // Is there a block ?
28 function pagelayer_render_blocks($pre_render, $parsed_block){
29
30 global $pagelayer;
31
32 if(empty($parsed_block)){
33 return $pre_render;
34 }
35
36 $block_name = $parsed_block['blockName'];
37 $tag = '';
38 $content = $parsed_block['innerHTML'];
39 $inner_blocks = array(
40 'blocks' => $parsed_block['innerBlocks'],
41 'content' => $parsed_block['innerContent']
42 );
43 $atts = $parsed_block['attrs'];
44 $atts['is_not_sc'] = 1;
45
46 if ( is_string( $block_name ) && 0 === strpos( $block_name, 'pagelayer/' ) ) {
47 $tag = substr( $block_name, 10 );
48 }
49
50 $allowed_tags = ['pl_inner_row', 'pl_inner_col'];
51
52 if( (empty($tag) || !array_key_exists($tag, $pagelayer->shortcodes) ) && ! in_array( $tag, $allowed_tags) ){
53 return $pre_render;
54 }
55
56 return pagelayer_render_shortcode($atts, $content, $tag, $inner_blocks);
57 }
58
59 // Is there a tag ?
60 function pagelayer_render_shortcode($atts, $content = '', $tag = '', $inner_blocks = array()){
61
62 global $pagelayer;
63
64 $is_block = 0;
65 $el = [];
66
67 // Is block ?
68 if(!empty($atts['is_not_sc'])){
69 $is_block = 1;
70 unset($atts['is_not_sc']);
71 }
72
73 $_tag = $class = $tag;
74 $final_tag = $tag;
75
76 // Check if the tag is inner row and col then change it to row and col tag
77 if($tag == 'pl_inner_row'){
78 $tag = 'pl_row';
79 }elseif($tag == 'pl_inner_col'){
80 $tag = 'pl_col';
81 $final_tag = $tag;
82 }
83
84 // Clear the pagelayer tags
85 if(substr($tag, 0, 3) == 'pl_'){
86 $_tag = str_replace('pl_', '', $final_tag);
87 $class = 'pagelayer-'.$_tag;
88 }
89
90 if(empty($atts)){
91 $atts = array();
92 }else{
93 $atts = (array) $atts;
94 }
95
96 // If global - > Get the post and replace $atts
97 if(!empty($atts['global_id'])){
98
99 if(!empty($pagelayer->global_widgets[$atts['global_id']])){
100 $content = $pagelayer->global_widgets[$atts['global_id']]['$'];
101 return pagelayer_change_id($content);
102 }
103
104 if(!empty($pagelayer->global_sections[$atts['global_id']])){
105 $content = $pagelayer->global_sections[$atts['global_id']]['$'];
106 return pagelayer_change_id($content);
107 }
108
109 // Set the global id as attr
110 $el['attr'][] = 'pagelayer-global-id="'.$atts['global_id'].'"';
111 }
112
113 // Is there any function ?
114 $func = pagelayer_isset($pagelayer->shortcodes[$tag], 'func');
115
116 // If not, we will search for a default func if prefix of tag is pl_
117 if(empty($func) && substr($tag, 0, 3) == 'pl_'){
118 $func = 'pagelayer_sc_'.substr($tag, 3);
119 }
120
121 // UnescapeHTML for the attributes, Fix for old shortcode method
122 if(empty($is_block)){
123 $atts = array_map('pagelayer_unescapeHTML', $atts);
124 }
125
126 // Create the element array. NOTE : This is similar to the JS el and is temporary
127 $el['atts'] = $atts;
128 $el['oAtts'] = $atts;
129 $el['id'] = !empty($atts['pagelayer-id']) ? $atts['pagelayer-id'] : pagelayer_create_id();
130 $el['tmp'] = [];
131 $el['tag'] = $final_tag;
132 $el['content'] = $content;
133 $el['inner_blocks'] = $inner_blocks;
134 $el['selector'] = '[pagelayer-id="'.$el['id'].'"]';
135 $el['cssSel'] = '.p-'.$el['id'];
136 $el['wrap'] = '[pagelayer-wrap-id="'.$el['id'].'"]';
137
138 // Remove pagelayer-id from attr
139 if( !empty($atts['pagelayer-id']) ){
140 unset($el['atts']['pagelayer-id']);
141 unset($el['oAtts']['pagelayer-id']);
142 }
143
144 $innerHTML = pagelayer_isset($pagelayer->shortcodes[$tag], 'innerHTML');
145 if(!empty($innerHTML) && !empty($content)){
146 $el['oAtts'][$innerHTML] = $content;
147 $el['atts'][$innerHTML] = $content;
148 }
149
150 // The default class
151 $el['classes'][] = 'p-'.$el['id'];
152 $el['classes'][] = $class;
153
154 // Register hook to filter $el
155 $el = apply_filters('pagelayer_do_shortcode_el', $el);
156
157 //pagelayer_print($el);
158
159 // Lets create the CSS, Classes, Attr. Also clean the dependent atts
160 foreach($pagelayer->tabs as $tab){
161
162 if(empty($pagelayer->shortcodes[$tag][$tab])){
163 continue;
164 }
165
166 foreach($pagelayer->shortcodes[$tag][$tab] as $section => $Lsection){
167
168 $props = empty($pagelayer->shortcodes[$tag][$section]) ? @$pagelayer->styles[$section] : @$pagelayer->shortcodes[$tag][$section];
169
170 //echo $tab.' - '.$section.' - <br>';
171
172 if(empty($props)){
173 continue;
174 }
175
176 foreach($props as $prop => $param){
177
178 //echo $tab.' - '.$section.' - '.$prop.'<br>';
179
180 // Handle the edit fields
181 if(!empty($param['edit'])){
182 $el['edit'][$prop] = $param['edit'];
183 }
184
185 // No value set
186 if(empty($el['atts'][$prop]) && empty($el['atts'][$prop.'_tablet']) && empty($el['atts'][$prop.'_mobile'])){
187 continue;
188 }
189
190 // Clean the not required atts
191 if(!empty($param['req'])){
192
193 $set = true;
194
195 foreach($param['req'] as $rk => $reqval){
196 $except = $rk[0] == '!' ? true : false;
197 $rk = $except ? substr($rk, 1) : $rk;
198 $val = pagelayer_isset($el['atts'], $rk);
199
200 //echo $prop.' - '.$rk.' : '.$reqval.' == '.$val.'<br>';
201
202 // The value should not be there
203 if($except){
204
205 if(!is_array($reqval) && $reqval == $val){
206 $set = false;
207 break;
208 }
209
210 // Its an array and a value is found, then dont show
211 if(is_array($reqval) && in_array($val, $reqval)){
212 $set = false;
213 break;
214 }
215
216 // The value must be equal
217 }else{
218
219 if(!is_array($reqval) && $reqval != $val){
220 $set = false;
221 break;
222 }
223
224 // Its an array and no value is found, then dont show
225 if(is_array($reqval) && !in_array($val, $reqval)){
226 $set = false;
227 break;
228 }
229 }
230
231 }
232
233 // Unset as we dont need
234 if(empty($set)){
235 unset($el['atts'][$prop]);
236 unset($el['atts'][$prop.'_tablet']);
237 unset($el['atts'][$prop.'_mobile']);
238 unset($el['tmp'][$prop]);
239 unset($el['tmp'][$prop.'_tablet']);
240 unset($el['tmp'][$prop.'_mobile']);
241 }
242
243 }
244
245 // We could have unset the value above, so we need to check again if the value is there
246 if(empty($el['atts'][$prop]) && empty($el['atts'][$prop.'_tablet']) && empty($el['atts'][$prop.'_mobile'])){
247 continue;
248 }
249
250 // Load any attachment values - This should go on top in the newer version @TODO
251 if( pagelayer_is_comment_mode() && !empty($param['edit']) && !(isset($param['ai']) && $param['ai'] === false) && !empty($el['atts'][$prop])){
252 $el['atts'][$prop] = $el['oAtts'][$prop] = !empty($el['atts']['comment_atts'][$prop]) ? $el['atts']['comment_atts'][$prop] : $el['atts'][$prop];
253 }
254
255 // Any image are skipped
256 if( pagelayer_is_comment_mode() && $param['type'] == 'image' && isset($el['atts']['comment_atts'][$prop])){
257 $el['atts'][$prop.'_ai'] = $el['oAtts'][$prop.'_ai'] = $el['atts']['comment_atts'][$prop];
258 }
259
260 if(in_array($param['type'], ['image', 'video', 'audio', 'media'])){
261
262 $attachment = ($param['type'] == 'image') ? pagelayer_image(@$el['atts'][$prop]) : pagelayer_attachment(@$el['atts'][$prop]);
263
264 if(!empty($attachment)){
265 foreach($attachment as $k => $v){
266 $el['tmp'][$prop.'-'.$k] = $v;
267 }
268 }
269
270 }
271
272 // Load any attachment values - This should go on top in the newer version @TODO
273 if($param['type'] == 'multi_image'){
274
275 $img_ids = pagelayer_maybe_explode(',', $el['atts'][$prop]);
276 $img_urls = [];
277
278 // Make the image URL
279 foreach($img_ids as $k => $v){
280 $image = pagelayer_image($v);
281 $img_urls['i'.$v] = @$image['url'];
282 }
283
284 $el['tmp'][$prop.'-urls'] = json_encode($img_urls);
285 }
286
287 // Backward compatibility of row
288 if($el['tag'] == 'pl_row' && $prop == 'content_pos' && !empty($el['atts'][$prop])){
289 if($el['atts'][$prop] == 'baseline'){
290 $el['atts'][$prop] = $el['oAtts'][$prop] = 'flex-start';
291 }else if($el['atts'][$prop] == 'end'){
292 $el['atts'][$prop] = $el['oAtts'][$prop] = 'flex-end';
293 }
294 }
295
296 // Backward compatibility of Icons
297 if($param['type'] == 'icon' && !empty($el['atts'][$prop]) && !preg_match('/\s/', $el['atts'][$prop])){
298 $el['atts'][$prop] = $el['oAtts'][$prop] = 'fa fa-'.$el['atts'][$prop];
299 }
300
301 // Backward compatibility of Box Shadow
302 if($param['type'] == 'box_shadow' && !empty($el['atts'][$prop])){
303 $shadow_atts = pagelayer_maybe_explode(',', $el['atts'][$prop]);
304 if(count($shadow_atts) == 4){
305 $shadow_atts[] = '0';
306 $shadow_atts[] = '';
307 $el['atts'][$prop] = $el['oAtts'][$prop] = $shadow_atts;
308 }
309 }
310
311 // Backward compatibility of units. And also for the default set value if it is numeric
312 if(!empty($param['units']) && isset($el['atts'][$prop]) && is_numeric($el['atts'][$prop])){
313 $el['atts'][$prop] = $el['oAtts'][$prop] = $el['atts'][$prop].$param['units'][0];
314 }
315
316 // Load permalink values
317 if($param['type'] == 'link'){
318
319 $link = $el['atts'][$prop];
320
321 if( is_array($el['atts'][$prop]) ){
322
323 // Link is required for check IF and IF-EXT in html
324 if(!isset($el['atts'][$prop]['link']) || strlen(trim($el['atts'][$prop]['link'])) < 1){
325 $link = '';
326 unset($el['atts'][$prop]);
327 continue;
328 }
329
330 $link = $el['atts'][$prop]['link'];
331
332 if(!empty($el['atts'][$prop]['target'])){
333 $el['attr'][][$param['selector']] = 'target="_blank"';
334 }
335
336 if(!empty($el['atts'][$prop]['rel'])){
337 $el['attr'][][$param['selector']] = 'rel="nofollow"';
338 }
339
340 if(!empty($el['atts'][$prop]['attrs'])){
341
342 $atts_ar = pagelayer_string_to_attributes($el['atts'][$prop]['attrs']);
343
344 if(!empty($atts_ar)){
345 foreach($atts_ar as $att => $value){
346 $el['attr'][][$param['selector']] = $att.'="'.esc_attr($value).'"';
347 }
348 }
349 }
350 }
351
352 $el['tmp'][$prop] = esc_url(pagelayer_permalink($link));
353 }
354
355 // Handle the AddClasses
356 if(!empty($param['addClass']) && !empty($el['atts'][$prop])){
357
358 // Convert to an array
359 if(!is_array($param['addClass'])){
360 $param['addClass'] = array($param['addClass']);
361 }
362
363 // Loop through
364 foreach($param['addClass'] as $k => $v){
365 $k = str_replace('{{element}}', '', $k);
366 $el['classes'][] = [trim($k) => str_replace('{{val}}', $el['atts'][$prop], $v)];
367 }
368
369 }
370
371 // Handle the AddAttributes
372 if(!empty($param['addAttr']) && !empty($el['atts'][$prop])){
373
374 // Convert to an array
375 if(!is_array($param['addAttr'])){
376 $param['addAttr'] = array($param['addAttr']);
377 }
378
379 // Loop through
380 foreach($param['addAttr'] as $k => $v){
381 $k = str_replace('{{element}}', '', $k);
382 $el['attr'][] = [trim($k) => $v];
383 }
384
385 }
386
387 $modes = [
388 'desktop' => '',
389 'tablet' => '_tablet',
390 'mobile' => '_mobile'
391 ];
392
393 $global_typo = ($param['type'] == 'typography') ? pagelayer_is_global_typo(@$el['atts'][$prop]) : '';
394
395 // Handle the CSS
396 if(!empty($param['css'])){
397 //echo $prop.'<br>';
398 // Convert to an array
399 if(!is_array($param['css'])){
400 $param['css'] = array($param['css']);
401 }
402
403 // Loop the modes and check for values
404 foreach($modes as $mk => $mv){
405
406 $M_prop = $prop.$mv;
407
408 $prop_val = pagelayer_isset($el['atts'], $M_prop);
409
410 // If is global font
411 if( $param['type'] == 'typography' && (!empty($prop_val) || !empty($global_typo)) ){
412 $prop_val = pagelayer_parse_typo($prop_val, $global_typo, $mk);
413 }
414
415 // Any value ?
416 if(empty($prop_val)){
417 continue;
418 }
419
420 // Global color handler
421 if($param['type'] == 'color'){
422 $prop_val = pagelayer_parse_color($prop_val);
423 }
424
425 // If there is global gradient color
426 if($param['type'] == 'gradient'){
427
428 $prop_val = pagelayer_maybe_explode(',', $prop_val);
429
430 foreach($prop_val as $grad_key => $grad_val){
431
432 if($grad_val[0] != '$'){
433 continue;
434 }
435
436 $prop_val[$grad_key] = pagelayer_parse_color($grad_val);
437
438 }
439
440 }
441
442 // Loop through
443 foreach($param['css'] as $k => $v){
444
445 // Make the selector
446 $selector = (!is_numeric($k) ? $k : $el['cssSel']);
447 $selector = pagelayer_parse_el_vars($selector, $el);
448
449 if($mk == 'tablet'){
450 $selector = '|pl_tablet|'.$selector;
451 }
452
453 if($mk == 'mobile'){
454 $selector = '|pl_mobile|'.$selector;
455 }
456
457 // Make the CSS
458 if(!empty($selector)){
459 $el['css'][$selector][] = rtrim( trim( pagelayer_css_render($v, $prop_val, pagelayer_isset($param, 'sep')) ), ';' );
460 }else{
461 $el['css'][][] = pagelayer_parse_el_vars($el['atts'][$M_prop],$el);
462 }
463 }
464
465 }
466
467 }
468
469 $font_cache = '';
470 // Loop the modes and check for values
471 foreach($modes as $mk => $mv){
472
473 $M_prop = $prop.$mv;
474
475 if($param['type'] == 'typography' && !empty($el['atts'][$M_prop])){
476
477 $prop_val = pagelayer_parse_typo($el['atts'][$M_prop], $global_typo, $mk);
478
479 $val = pagelayer_maybe_explode(',', $prop_val);
480
481 //For backward comaptibility
482 if($mk == 'desktop'){
483 $font_cache = $val[0];
484 }
485
486 $val[0] = empty($val[0]) ? $font_cache : $val[0];
487
488 if(!empty($val[0])){
489 pagelayer_load_font_family($val[0], pagelayer_isset($val, 3), pagelayer_isset($val, 2));
490
491 //pagelayer_print($pagelayer->runtime_fonts);
492 }
493 }
494
495 if($prop == 'font_family' && !empty($el['atts'][$M_prop])){
496 $val = $el['atts'][$M_prop];
497 if(!empty($val)){
498 pagelayer_load_font_family($val, pagelayer_isset($el['atts'], 'font_weight'.$mv), pagelayer_isset($el['atts'], 'font_style'.$mv));
499 }
500 }
501 }
502 }
503
504 }
505
506 }
507
508 //@pagelayer_print($el['css']);
509
510 // Is there a function of the tag ?
511 if(function_exists($func)){
512 call_user_func_array($func, array(&$el));
513 }
514
515 // Create the default atts and tmp atts
516 if(pagelayer_is_live()){
517 pagelayer_create_sc($el, $is_block);
518 }
519
520 $div = '<div pagelayer-id="'.$el['id'].'">
521 <style pagelayer-style-id="'.$el['id'].'"></style>';
522
523 $is_group = !empty($pagelayer->shortcodes[$tag]['has_group']) ? true : false;
524
525 // If there is an HTML AND you are not a GROUP, then make use of it, or append the real content
526 if(!empty($pagelayer->shortcodes[$tag]['html'])){
527
528 // Create the HTML object
529 $node = pagelayerQuery::parseStr($pagelayer->shortcodes[$tag]['html']);
530
531 // Remove the if-ext
532 foreach($node('[if-ext]') as $v){
533 $reqvar = pagelayer_var($v->attr('if-ext'));
534 $v->removeAttr('if-ext');
535
536 // Is the element there ?
537 if(empty($el['atts'][$reqvar])){
538 $ext_html = $v->html();
539 if(strlen($ext_html) > 0){
540 $v->after($ext_html);
541 }
542 $v->remove();
543 }
544 }
545
546 // Remove the if
547 foreach($node('[if]') as $v){
548 $reqvar = pagelayer_var($v->attr('if'));
549 $v->removeAttr('if');
550
551 // Is the element there ?
552 if(empty($el['atts'][$reqvar])){
553 $v->remove();
554 }
555 }
556
557 //die($node->html());
558
559 // Do we have a holder ? Mainly for groups
560 if(!empty($pagelayer->shortcodes[$tag]['holder'])){
561 $node->query($pagelayer->shortcodes[$tag]['holder'])->html('{{pagelayer_do_shortcode}}');
562 $do_shortcode = 1;
563 }
564
565 $html = pagelayer_parse_vars($node->html(), $el);
566
567 // Append to the DIV
568 $div .= $html;
569
570 // Is it a widget ?
571 }elseif(!empty($pagelayer->shortcodes[$tag]['widget'])){
572
573 $class = $pagelayer->shortcodes[$tag]['widget'];
574 $instance = [];
575
576 // Is there any existing data ?
577 if(!empty($el['atts']['widget_data'])){
578 $json = trim($el['atts']['widget_data']);
579 $json = json_decode($json, true);
580 //pagelayer_print($json);die();
581 if(!empty($json)){
582 $instance = $json;
583 }
584 }
585
586 ob_start();
587 the_widget($class, $instance, array('widget_id'=>'arbitrary-instance-'.$el['id'],
588 'before_widget' => '',
589 'after_widget' => '',
590 'before_title' => '',
591 'after_title' => ''
592 ));
593
594 $div .= ob_get_contents();
595 ob_end_clean();
596
597 }else{
598 $div .= '{{pagelayer_do_shortcode}}';
599 $do_shortcode = 1;
600 }
601
602 // End the tag
603 $div .= '</div>';
604
605 // Add classes and attributes
606 if(!empty($el['classes']) || !empty($el['attr']) || !empty($el['atts']['ele_attributes'])){
607
608 // Create the HTML object
609 $node = pagelayerQuery::parseStr($div);
610
611 // Add the editable values
612 if(!empty($el['edit']) && pagelayer_is_live()){
613
614 foreach($el['edit'] as $k => $v){
615 $node->query($v)->attr('pagelayer-editable', $k);
616 }
617
618 }
619
620 // Add the post data editable
621 if(pagelayer_is_live() && !empty($pagelayer->shortcodes[$tag]['edit_props']) && is_array($pagelayer->shortcodes[$tag]['edit_props'])){
622
623 $edit_props = $pagelayer->shortcodes[$tag]['edit_props'];
624
625 foreach($edit_props as $k => $v){
626 $node->query($k)->attr('pagelayer-props-editable', $v);
627 }
628
629 }
630
631 // Add the classes
632 if(!empty($el['classes'])){
633
634 //pagelayer_print($el['classes']);
635
636 foreach($el['classes'] as $k => $v){
637
638 if(!is_array($v)){
639 $v = [$v];
640 }
641
642 foreach($v as $kk => $vv){
643 //echo $kk.' - '.$vv."\n";
644 if(is_numeric($kk)){
645 $node->query($el['selector'])->addClass($vv);
646 }else{
647 $node->query($kk)->addClass($vv);
648 }
649
650 }
651
652 }
653
654 //echo $node->html();
655 //die();
656
657 }
658
659 // Add the attributes
660 if(!empty($el['attr'])){
661
662 //pagelayer_print($el['attr']);
663
664 foreach($el['attr'] as $k => $v){
665
666 if(!is_array($v)){
667 $v = [$v];
668 }
669
670 foreach($v as $kk => $vv){
671
672 $att = explode('=', $vv, 2);
673 $att[1] = pagelayer_parse_vars($att[1], $el);
674 $att[1] = trim($att[1], '"');
675
676 if(is_numeric($kk)){
677 $node->query($el['selector'])->attr($att[0], $att[1]);
678 }else{
679 $node->query($kk)->attr($att[0], $att[1]);
680 }
681
682 }
683
684 }
685
686 }
687
688 // Adding Custom Attributes
689 if(!empty($el['atts']['ele_attributes'])){
690
691 $val = pagelayer_string_to_attributes($el['atts']['ele_attributes']);
692 if(!empty($val)){
693 foreach($val as $att => $value ){
694
695 // Defense in depth at the sink. Unconditional : it must not
696 // depend on the viewer, the post author or a save time scan.
697 if(pagelayer_should_show_xss_warning() && !pagelayer_is_allowed_attribute($att)){
698 continue;
699 }
700
701 $node->query($el['selector'])->attr($att, esc_attr($value));
702 }
703 }
704
705 }
706
707 // Get font family form inline style
708 foreach($node->query('[style]') as $snode){
709 $ss = $snode->attr('style');
710
711 if(strpos($ss, 'font-family') === false){
712 continue;
713 }
714
715 $ss = explode(';', html_entity_decode($snode->attr('style')));
716 foreach($ss as $sss){
717
718 if(strpos($sss, 'font-family') === false){
719 continue;
720 }
721
722 $ff = explode(':', $sss);
723 $val = trim( trim($ff[1]), '"' );
724 $fw = array('100', '100i', '200', '200i', '300', '300i', '400', '400i', '500', '500i', '600', '600i', '700', '700i', '800', '800i', '900', '900i');
725
726 foreach($fw as $ww){
727 $pagelayer->runtime_fonts[$val][$ww] = $ww;
728 }
729 }
730 }
731
732 $div = $node->html();
733 //die($div);
734
735 }
736
737 // Add the CSS if any or remove it
738 $style = '';
739 if(!empty($el['css'])){
740
741 $screen_style = array('tablet' => '', 'mobile' => '');
742 $style = '<style pagelayer-style-id="'.$el['id'].'">';
743 foreach($el['css'] as $ck => $cv){
744 preg_match('/\|pl_(mobile|tablet)\|/is', $ck, $screen_matches);
745 $ck = str_replace(['|pl_mobile|', '|pl_tablet|'], '', $ck);
746 $media = pagelayer_isset($screen_matches, 1);
747
748 $merge_css = implode(';', $cv);
749 $combine_css = (!is_numeric($ck) ? $ck.'{'.$merge_css.'}' : $merge_css ).PHP_EOL;
750
751 // Mobile or tablet ?
752 if(!empty($media)){
753 $screen_style[$media] .= $combine_css;
754 continue;
755 }
756
757 $style .= $combine_css;
758 }
759
760 if(!empty($screen_style['tablet'])){
761 $style .= '@media (max-width: '.$pagelayer->settings['tablet_breakpoint'].'px) and (min-width: '.($pagelayer->settings['mobile_breakpoint'] + 1).'px){'.$screen_style['tablet'].'}'.PHP_EOL;
762 }
763
764 if(!empty($screen_style['mobile'])){
765 $style .= '@media (max-width: '.$pagelayer->settings['mobile_breakpoint'].'px){'.$screen_style['mobile'].'}'.PHP_EOL;
766 }
767
768 $style .= '</style>';
769 $style = pagelayer_parse_vars($style, $el);
770
771 if(!empty($pagelayer->shortcodes[$tag]['overide_css_selector'])){
772 $overide_css_selector = pagelayer_parse_el_vars($pagelayer->shortcodes[$tag]['overide_css_selector'], $el);
773 $style = str_replace($el['cssSel'], $overide_css_selector, $style);
774 $style = str_replace($el['wrap'], $overide_css_selector, $style);
775 }
776
777 $style = pagelayer_unescapeHTML($style);
778 }
779
780 $div = str_replace('<style pagelayer-style-id="'.$el['id'].'"></style>', $style, $div);
781
782 // Is there an inner content which requires a SHORTCODE ?
783 if(!empty($do_shortcode)){
784
785 $inner_content = pagelayer_render_inner_content($el);
786
787 $div = str_replace('{{pagelayer_do_shortcode}}', $inner_content, $div);
788 }
789
790 // Sanitize the content
791 $div = apply_filters( 'pagelayer_sanitize_do_shortcode', $div );
792
793 return $div;
794
795 }
796
797 // Render inner content
798 function pagelayer_render_inner_content(&$el){
799
800 $inner_content = '';
801
802 // Is block code?
803 if( !empty($el['inner_blocks']) ){
804
805 $index = 0;
806
807 foreach ( $el['inner_blocks']['content'] as $chunk ) {
808 if ( is_string( $chunk ) ) {
809
810 // If any string in Column the conver this is text widget in pagelayer live
811 if(!empty(trim($chunk)) && pagelayer_is_live() && $el['tag'] == 'pl_col'){
812 $parsed_block['blockName'] = 'pagelayer/pl_text';
813 $parsed_block['innerHTML'] = $chunk;
814 $parsed_block['attrs'] = [];
815 $inner_content .= render_block($parsed_block);
816 continue;
817 }
818
819 $inner_content .= $chunk;
820 continue;
821 }
822
823 $inner_block = $el['inner_blocks']['blocks'][ $index ];
824 $inner_content .= render_block($inner_block);
825 ++$index;
826 }
827 }else{
828 $inner_content .= do_shortcode($el['content']);
829 }
830
831 return $inner_content;
832 }
833
834 // Change pagelayer id in html
835 function pagelayer_change_id($content){
836 global $pagelayer;
837
838 preg_match_all('/pagelayer-id="(.*?)"/', $content, $matches);
839 $matches = array_unique($matches[1]);
840
841 foreach($matches as $val){
842 $id = pagelayer_create_id();
843 $content = str_replace($val, $id, $content);
844 }
845
846 return $content;
847 }
848
849 // Creates the shortcode and returns a base64 encoded files
850 function pagelayer_create_sc(&$el, $is_block = 0){
851
852 global $pagelayer;
853
854 $a = $tmp = array();
855
856 $pagelayer->data_attr[$el['id']] = ['attr' => $el['oAtts'], 'tmp' => $el['tmp']];
857
858 /*if(!empty($el['oAtts'])){
859
860 foreach($el['oAtts'] as $k => $v){
861 $v = str_replace('&', '&amp;', $v);
862 if($is_block){
863 $v = pagelayer_escapeHTML($v);
864 }
865 $el['attr'][] = 'pagelayer-a-'.$k.'="'.$v.'"';
866 }
867
868 }
869
870 // Tmp atts
871 if(!empty($el['tmp'])){
872
873 foreach($el['tmp'] as $k => $v){
874 $v = str_replace('&', '&amp;', $v);
875 if($is_block){
876 $v = pagelayer_escapeHTML($v);
877 }
878 $el['attr'][] = 'pagelayer-tmp-'.$k.'="'.$v.'"';
879 }
880
881 }*/
882
883 // Add the tag
884 $el['attr'][] = 'pagelayer-tag="'.$el['tag'].'"';
885
886 // Make it a Pagelayer element for editing
887 $el['classes'][] = 'pagelayer-ele';
888
889 }
890
891 // Converts {{val}} to val
892 function pagelayer_var($var){
893 return substr($var, 2, -2);
894 }
895
896 // Is the given global color
897 function pagelayer_is_global_typo($value){
898 global $pagelayer;
899
900 $typo_key = '';
901
902 // Backward compatibility
903 if(is_string($value) && $value[0] == '$'){
904 $typo_key = substr($value, 1);
905 }
906
907 if(is_array($value) && isset($value['global-font'])){
908 $typo_key = $value['global-font'];
909 }
910
911 // If global color not exist
912 if(!empty($typo_key)){
913 $typo_key = isset($pagelayer->global_fonts[$typo_key]) ? $typo_key : 'primary';
914 }
915
916 return $typo_key;
917
918 }
919
920 // Parse typography and handle Backward compatibility
921 function pagelayer_parse_typo($value, $desk_global = '', $mk = 'desktop'){
922 global $pagelayer;
923
924 $value = empty($value)? [] : $value;
925
926 // Backward compatibility for comma seperated val
927 if(!is_array($value) && $value[0] != '$'){
928 return $value;
929 }
930
931 $val = ['','','','','','','','','','',''];
932 $global_typo = pagelayer_is_global_typo($value);
933 $_desk_global = false;
934
935 if( empty($global_typo) ){
936 $global_typo = $desk_global;
937 $_desk_global = true;
938 }
939
940 // Apply global typo
941 foreach($pagelayer->typo_props as $typo => $typo_key){
942
943 // Backspace compatibility for normal array and if is set global in '$' format like $primary
944 if(is_array($value) && !empty($value[$typo])){
945 $val[$typo] = $value[$typo];
946 }
947
948 if(!empty($value[$typo_key])){
949 $val[$typo] = $value[$typo_key];
950 }
951
952 if(!empty($val[$typo]) || empty($global_typo)){
953 continue;
954 }
955
956 $global_val = $pagelayer->global_fonts[$global_typo]['value'];
957
958 if( empty($global_val[$typo_key]) || (is_array($global_val[$typo_key]) && empty($global_val[$typo_key][$mk])) || (!is_array($global_val[$typo_key]) && !empty($_desk_global) && $mk != 'desktop') ){
959 continue;
960 }
961
962 $val[$typo] = 'var(--pagelayer-font-'.$global_typo.'-'.$typo_key.')';
963 }
964
965 return $val;
966 }
967
968 // Parse color for global color
969 function pagelayer_parse_color($value, $var = true){
970 global $pagelayer;
971
972 // Global color handler
973 if($value[0] != '$' ){
974 return $value;
975 }
976
977 $gkey = substr($value, 1);
978 $gkey = isset($pagelayer->global_colors[$gkey]) ? $gkey : 'primary';
979
980 if(empty($var)){
981 return @$pagelayer->global_colors[$gkey]['value'];
982 }
983
984 return 'var(--pagelayer-color-'.$gkey.')';
985 }
986
987 // Replace the variables
988 function pagelayer_parse_el_vars($str, &$el){
989
990 global $pagelayer, $post;
991
992 // if is 404 then @$post->ID
993 if(!empty( $pagelayer->rendering_template_id ) && @$post->ID != $pagelayer->rendering_template_id){
994 $is_editable = false;
995 }else{
996 $is_editable = true;
997 }
998
999 $str = str_replace('{{element}}', $el['cssSel'], $str);
1000 $is_live = pagelayer_is_live();
1001 if(!empty($is_live) && $is_editable){
1002 $str = str_replace('{{wrap}}', $el['wrap'], $str);
1003 }else{
1004 $str = str_replace('{{wrap}}', $el['cssSel'], $str);
1005 }
1006 $str = str_replace('{{ele_id}}', $el['id'], $str);
1007
1008 return $str;
1009
1010 }
1011
1012 // Parse the variables
1013 function pagelayer_parse_vars($str, &$el){
1014
1015 if(empty($str)){
1016 return $str;
1017 }
1018
1019 //pagelayer_print($el);
1020 if(!empty($el['tmp']) && is_array($el['tmp'])){
1021 foreach($el['tmp'] as $k => $v){
1022 $str = str_replace('{{{'.$k.'}}}', pagelayer_maybe_implode($el['tmp'][$k]), $str);
1023 }
1024 }
1025
1026 if(is_array($el['atts'])){
1027 foreach($el['atts'] as $k => $v){
1028 $str = str_replace('{{'.$k.'}}', pagelayer_maybe_implode($el['atts'][$k]), $str);
1029 }
1030 }
1031
1032 return $str;
1033 }
1034
1035 // Make the rule
1036 function pagelayer_css_render($rule, $val, $sep = ','){
1037
1038 // Seperator
1039 $sep = empty($sep) ? ',' : $sep;
1040
1041 if(is_array($val)){
1042 $val = implode($sep, $val);
1043 }
1044
1045 // Replace the val
1046 $rule = pagelayer_css_val_replace('{{val}}', pagelayer_hex8_to_rgba($val), $rule);
1047
1048 // If there is an array
1049 if(preg_match('/\{val\[\d/is', $rule)){
1050 $val = explode($sep, $val);
1051 foreach($val as $k => $v){
1052 $rule = pagelayer_css_val_replace('{{val['.$k.']}}', pagelayer_hex8_to_rgba($v), $rule);
1053 }
1054 }
1055
1056 return $rule;
1057 }
1058
1059 // Make the rule
1060 function pagelayer_css_val_replace($val, $v, $rule){
1061
1062 // If value has css var then we remove units
1063 if(strripos($v, 'var(') !== false){
1064 $pattern = '/'.preg_quote($val, '/').'?[^\s|;]+/is';
1065 $rule = preg_replace($pattern, $v, $rule);
1066 return $rule;
1067 }
1068
1069 $rule = str_replace($val, $v, $rule);
1070 return $rule;
1071 }
1072
1073 // Post Property Handler
1074 function pagelayer_sc_post_props(&$el){
1075
1076 global $post;
1077
1078 if(empty($post)){
1079 return;
1080 }
1081
1082 $el['oAtts']['post_title'] = $post->post_title;
1083 $el['oAtts']['post_name'] = $post->post_name;
1084 $el['oAtts']['post_excerpt'] = $post->post_excerpt;
1085 $el['oAtts']['post_status'] = (empty($post->post_password)) ? $post->post_status : 'pass_protected';
1086 $el['oAtts']['post_password'] = $post->post_password;
1087 $el['oAtts']['featured_image'] = get_post_thumbnail_id($post);
1088 $el['oAtts']['comment_status'] = ($post->comment_status == 'open') ? 'true' : '';
1089 $el['oAtts']['ping_status'] = ($post->ping_status == 'open') ? 'true' : '';
1090 $el['oAtts']['post_date'] = $post->post_date;
1091 $el['oAtts']['post_sticky'] = is_sticky($post->ID) ? 'true' : '';
1092 $el['oAtts']['post_parent'] = $post->post_parent;
1093 $el['oAtts']['menu_order'] = $post->menu_order;
1094 $el['oAtts']['post_author'] = $post->post_author;
1095 $el['oAtts']['post_category'] = '';
1096 $el['oAtts']['post_tags'] = '';
1097
1098 $tag_name = pagelayer_post_type_tag($post->post_type);
1099 if(!empty($tag_name)){
1100 $postTags = wp_get_post_terms( $post->ID, $tag_name );
1101 $el['oAtts']['post_tags'] = array_column((array)$postTags, 'name');
1102 }
1103
1104 $cat_name = pagelayer_post_type_category($post->post_type);
1105 if(!empty($cat_name)){
1106 $category = get_the_terms( $post->ID, $cat_name );
1107 $el['oAtts']['post_category'] = array_column((array)$category, 'term_id');
1108 }
1109
1110 // Load featured image details
1111 if(!empty($el['oAtts']['featured_image'])){
1112
1113 $attachment = pagelayer_image($el['oAtts']['featured_image']);
1114
1115 if(!empty($attachment)){
1116 foreach($attachment as $k => $v){
1117 $el['tmp']['featured_image-'.$k] = $v;
1118 }
1119 }
1120
1121 }
1122
1123 }
1124
1125 // ROW Handler
1126 function pagelayer_sc_row(&$el){
1127
1128 pagelayer_bg_video($el);
1129
1130 if(!empty($el['atts']['row_shape_type_top'])){
1131 $path_top = PAGELAYER_DIR.'/images/shapes/'.$el['atts']['row_shape_type_top'].'-top.svg';
1132 $el['atts']['svg_top'] = file_get_contents($path_top);
1133 }
1134
1135 if(!empty($el['atts']['row_shape_type_bottom'])){
1136 $path_bottom = PAGELAYER_DIR.'/images/shapes/'.$el['atts']['row_shape_type_bottom'].'-bottom.svg';
1137 $el['atts']['svg_bottom'] = file_get_contents($path_bottom);
1138 }
1139
1140 // Row background slider
1141 if(!empty($el['atts']['bg_slider'])){
1142 $ids = pagelayer_maybe_explode(',', $el['atts']['bg_slider']);
1143 $urls = [];
1144 $el['atts']['slider'] = '';
1145
1146 // Make the image URL
1147 foreach($ids as $k => $v){
1148
1149 $image = pagelayer_image($v);
1150 $urls['i'.$v] = @$image['url'];
1151
1152 $el['atts']['slider'] .= '<div class="pagelayer-bgimg-slide" style="background-image:url(\''.$image['url'].'\')"></div>';
1153
1154 }
1155
1156 if(!empty($urls)){
1157 $el['tmp']['bg_slider-urls'] = json_encode($urls);
1158 }
1159
1160 }
1161
1162 // Row background parallax image.
1163 if(!empty($el['atts']['parallax_img'])){
1164 $img_size = @$el['tmp']['parallax_img-'.$el['atts']['parallax_id_size'].'-url'];
1165 $el['atts']['parallax_img_src'] = empty($img_size) ? @$el['tmp']['parallax_img-url'] : $img_size;
1166 }
1167
1168 }
1169
1170 // Column Handler
1171 function pagelayer_sc_col(&$el){
1172
1173 // Add the default col class
1174 $el['classes'][] = 'pagelayer-col';
1175
1176 //return do_shortcode($el['content']);
1177
1178 pagelayer_bg_video($el);
1179
1180 // Column background slider
1181 if(!empty($el['atts']['bg_slider'])){
1182 $ids = pagelayer_maybe_explode(',', $el['atts']['bg_slider']);
1183 $urls = [];
1184 $el['atts']['slider'] = '';
1185
1186 // Make the image URL
1187 foreach($ids as $k => $v){
1188
1189 $image = pagelayer_image($v);
1190 $urls['i'.$v] = @$image['url'];
1191
1192 $el['atts']['slider'] .= '<div class="pagelayer-bgimg-slide" style="background-image:url(\''.$image['url'].'\')"></div>';
1193
1194 }
1195
1196 if(!empty($urls)){
1197 $el['tmp']['bg_slider-urls'] = json_encode($urls);
1198 }
1199
1200 }
1201
1202 // Col background parallax image.
1203 if(!empty($el['atts']['parallax_img'])){
1204 $img_size = @$el['tmp']['parallax_img-'.$el['atts']['parallax_id_size'].'-url'];
1205 $el['atts']['parallax_img_src'] = empty($img_size) ? @$el['tmp']['parallax_img-url'] : $img_size;
1206 }
1207
1208 }
1209
1210 // Just for BG handling
1211 function pagelayer_bg_video(&$el){
1212
1213 if(empty($el['tmp']['bg_video_src-url'])){
1214 return false;
1215 }
1216
1217 // Get the video URL for the iframe
1218 $iframe_atts = pagelayer_video_url($el['tmp']['bg_video_src-url'], true);
1219
1220 $source = esc_url( $el['tmp']['bg_video_src-url'] );
1221 $source = str_replace('&amp;', '&', $source);
1222 $url = parse_url($source);
1223
1224 $iframe_atts['src'] .= substr_count($iframe_atts['src'], '?') > 0 ? '' : '?';
1225
1226 if(!empty($el['atts']['mute'])){
1227 $iframe_atts['src'] .= "&mute=1";
1228 $el['atts']['mute'] = " muted ";
1229 }else{
1230 $iframe_atts['src'] .= "&mute=0";
1231 $el['atts']['mute'] = "";
1232 }
1233
1234 if(empty($el['atts']['stop_loop'])){
1235 $iframe_atts['src'] .= "&loop=1";
1236 $el['atts']['stop_loop'] = " loop ";
1237 }else{
1238 $iframe_atts['src'] .= "&loop=0";
1239 $el['atts']['stop_loop'] = "";
1240 }
1241
1242 if (!empty($source)) {
1243
1244 if ($iframe_atts['type'] == 'youtube') {
1245
1246 $settings = ' data-loop="'.( !empty($el['atts']['stop_loop']) ? 1 : 0 ).'" data-mute="'.( !empty($el['atts']['mute']) ? 1 : 0 ).'" data-videoid = "'.( $iframe_atts['id'] ).'"';
1247
1248 $el['atts']['vid_src'] = '<div class = "pagelayer-youtube-video" '. $settings .'></div>';
1249
1250 } else if ($iframe_atts['type'] == 'vimeo') {
1251
1252 $el['atts']['vid_src'] = '<iframe src="'.$iframe_atts['src'].'&background=1&autoplay=1&byline=0&title=0" allowfullscreen="1" webkitallowfullscreen="1" mozallowfullscreen="1" frameborder="0"></iframe>';
1253
1254 }else{
1255
1256 $el['atts']['vid_src'] = '<video autoplay playsinline '.$el['atts']['mute'].$el['atts']['stop_loop'].'>'.
1257 '<source src="'.$iframe_atts['src'].'" type="video/mp4">'.
1258 '</video>';
1259
1260 }
1261 }
1262 }
1263
1264 // Heading Handler
1265 function pagelayer_sc_heading(&$el){
1266 //Backward compatibility for new link props
1267 pagelayer_add_link_backward($el, array('rel' => '', 'selector' => '.pagelayer-link-sel'));
1268 }
1269
1270 // Heading Handler
1271 function pagelayer_sc_icon(&$el){
1272 //Backward compatibility for new link props
1273 pagelayer_add_link_backward($el, array('rel' => '', 'selector' => '.pagelayer-ele-link'));
1274 }
1275
1276 // Heading Handler
1277 function pagelayer_sc_badge(&$el){
1278 //Backward compatibility for new link props
1279 pagelayer_add_link_backward($el, array(
1280 'link' => 'badge_url',
1281 'rel' => '',
1282 'target' => 'badge_target',
1283 'selector' => '.pagelayer-ele-link'
1284 ));
1285 }
1286
1287 // Heading Handler
1288 function pagelayer_sc_btn(&$el){
1289 //Backward compatibility for new link props
1290 pagelayer_add_link_backward($el, array('selector' => '.pagelayer-btn-holder'));
1291 }
1292
1293 // Image Handler
1294 function pagelayer_sc_social(&$el){
1295
1296 //Backward compatibility for new link props
1297 pagelayer_add_link_backward($el, array(
1298 'link' => 'social_url',
1299 'rel' => '',
1300 'selector' => '.pagelayer-ele-link'
1301 ));
1302
1303 if(empty($el['atts']['icon'])) return;
1304 $icon = explode(' fa-', $el['atts']['icon']);
1305 $el['classes'][] = ['.pagelayer-icon-holder' => 'pagelayer-'.$icon[1]];
1306 }
1307
1308 // Image Handler
1309 function pagelayer_sc_image(&$el){
1310
1311 // Decide the image URL
1312 $el['atts']['func_id'] = @$el['tmp']['id-'.$el['atts']['id-size'].'-url'];
1313 $el['atts']['func_id'] = empty($el['atts']['func_id']) ? @$el['tmp']['id-url'] : $el['atts']['func_id'];
1314 $el['atts']['pagelayer-srcset'] = $el['atts']['func_id'].', '.$el['atts']['func_id'].' 1x, ';
1315
1316 $image_atts = array(
1317 'name' => 'id',
1318 'size' => 'id-size'
1319 );
1320
1321 pagelayer_get_img_srcset($el, $image_atts);
1322
1323 // What is the link ?
1324 if(!empty($el['atts']['link_type'])){
1325
1326 // Custom url
1327 if($el['atts']['link_type'] == 'custom_url'){
1328
1329 // Backward compatibility for new link props
1330 pagelayer_add_link_backward($el, array( 'rel' => '', 'selector' => '.pagelayer-ele-link'));
1331
1332 $el['atts']['func_link'] = @$el['tmp']['link'];
1333 }
1334
1335 // Link to the media file itself
1336 if($el['atts']['link_type'] == 'media_file'){
1337 $el['atts']['func_link'] = $el['atts']['func_id'];
1338 }
1339
1340 // Lightbox
1341 if($el['atts']['link_type'] == 'lightbox'){
1342 $el['atts']['func_link'] = $el['atts']['func_id'];
1343 }
1344
1345 }
1346
1347 //pagelayer_print($el);
1348
1349 }
1350
1351 // Image Slider Handler
1352 function pagelayer_sc_image_slider(&$el){
1353
1354 // Backward compatibility for new link props
1355 if( !empty($el['atts']['link_type']) && $el['atts']['link_type'] == 'custom_url' ){
1356 pagelayer_add_link_backward($el, array( 'rel' => '', 'selector' => '.pagelayer-link-sel'));
1357 }
1358
1359 if(empty($el['atts']['ids'])){
1360 $el['atts']['ids'] = '';
1361 }
1362
1363 $ids = pagelayer_maybe_explode(',', $el['atts']['ids']);
1364 $urls = [];
1365 $all_urls = [];
1366 $final_urls = [];
1367 $ul = [];
1368 $size = $el['atts']['size'];
1369
1370 // Make the image URL
1371 foreach($ids as $k => $v){
1372
1373 $image = pagelayer_image($v);
1374
1375 $final_urls[$v] = empty($image[$size.'-url']) ? @$image['url'] : $image[$size.'-url'];
1376
1377 $urls['i'.$v] = @$image['url'];
1378
1379 foreach($image as $kk => $vv){
1380 $si = strstr($kk, '-url', true);
1381 if(!empty($si)){
1382 $all_urls['i'.$v][$si] = $vv;
1383 }
1384 }
1385
1386 $li = '<li class="pagelayer-slider-item">';
1387
1388 // Any Link ?
1389 if(!empty($el['atts']['link_type'])){
1390 $link = ($el['atts']['link_type'] == 'media_file' ? (!empty($image['url']) ? $image['url'] : $final_urls[$v]) : @$el['tmp']['link']);
1391 $li .= '<a href="'.$link.'" class="pagelayer-link-sel">';
1392 }
1393
1394 // The Image
1395 $li .= '<img class="pagelayer-img" src="'.$final_urls[$v].'" title="'.$image['title'].'" alt="'.$image['alt'].'">';
1396
1397 if(!empty($el['atts']['link_type'])){
1398 $li .= '</a>';
1399 }
1400
1401 $li .= '</li>';
1402
1403 $ul[] = $li;
1404
1405 }
1406
1407 //pagelayer_print($urls);
1408 //pagelayer_print($final_urls);
1409 //pagelayer_print($all_urls);
1410
1411 // Make the TMP vars
1412 if(!empty($urls)){
1413 $el['tmp']['ids-urls'] = json_encode($urls);
1414 $el['tmp']['ids-all-urls'] = json_encode($all_urls);
1415 $el['atts']['ul'] = implode('', $ul);
1416
1417 // Which arrows to show
1418 if(in_array(@$el['atts']['controls'], ['arrows', 'none'])){
1419 $el['attr'][] = ['.pagelayer-image-slider-ul' => 'data-pager="false"'];
1420 }
1421
1422 if(in_array(@$el['atts']['controls'], ['pager', 'none'])){
1423 $el['attr'][] = ['.pagelayer-image-slider-ul' => 'data-controls="false"'];
1424 }
1425 }
1426
1427 };
1428
1429 //Grid Gallery Handler
1430 function pagelayer_sc_grid_gallery(&$el){
1431
1432 if(empty($el['atts']['ids'])){
1433 $el['atts']['ids'] = '';
1434 }
1435
1436 $ids = pagelayer_maybe_explode(',', $el['atts']['ids']);
1437 $urls = [];
1438 $all_urls = [];
1439 $final_urls = [];
1440 $ul = [];
1441 $pagin = '<li class="pagelayer-grid-page-item active">1</li>';
1442 $size = $el['atts']['size'];
1443 $i = 0;
1444 $j = 1;
1445 $img_Page = $el['atts']['images_no'];
1446 $gallery_rand = 'gallery-id-'.floor((rand() * 100) + 1);
1447
1448 $ul[] = '<ul class="pagelayer-grid-gallery-ul">';
1449 // Make the image URL
1450 foreach($ids as $k => $v){
1451
1452 $image = pagelayer_image($v);
1453
1454 $final_urls[$v] = empty($image[$size.'-url']) ? @$image['url'] : $image[$size.'-url'];
1455
1456 $urls['i'.$v] = @$image['url'];
1457 $links['i'.$v] = @$image['link'];
1458 $titles['i'.$v] = @$image['title'];
1459 $captions['i'.$v] = @$image['caption'];
1460
1461 foreach($image as $kk => $vv){
1462 $si = strstr($kk, '-url', true);
1463 if(!empty($si)){
1464 $all_urls['i'.$v][$si] = $vv;
1465 }
1466 }
1467
1468 if($img_Page != 0 && ($i % $img_Page) == 0 && $i != 0 ){
1469 $ul[] = '</ul><ul class="pagelayer-grid-gallery-ul">';
1470 $j++;
1471 $pagin .= '<li class="pagelayer-grid-page-item">'.$j.'</li>';
1472 }
1473
1474 $li = '<li class="pagelayer-gallery-item" >';
1475
1476 if(empty($el['atts']['link_to'])){
1477 $li .= '<div>';
1478 }
1479
1480 // Any Link ?
1481 if(!empty($el['atts']['link_to']) && $el['atts']['link_to'] == 'media_file'){
1482 $link = ($el['atts']['link_to'] == 'media_file' ? $final_urls[$v] : @$el['atts']['link']);
1483 $li .= '<a href="'.$link.'" class="pagelayer-ele-link">';
1484 }
1485
1486 // Any Link ?
1487 if(!empty($el['atts']['link_to']) && $el['atts']['link_to'] == 'attachment' ){
1488 $link = $image['link'];
1489 $li .= '<a href="'.$link.'" class="pagelayer-ele-link">';
1490 }
1491
1492 if(!empty($el['atts']['link_to']) && $el['atts']['link_to'] == 'lightbox'){
1493 $li .= '<a href="'.$image['url'].'" data-lightbox-gallery="'.$gallery_rand.'" alt="'.$image['alt'].'" class="pagelayer-ele-link" pagelayer-grid-gallery-type="'.$el['atts']['link_to'].'">';
1494 }
1495 // The Image
1496 $li .= '<img class="pagelayer-img" src="'.$final_urls[$v].'" title="'.$image['title'].'" alt="'.$image['alt'].'">';
1497
1498 if(!empty($el['atts']['caption'])){
1499 $li .= '<span class="pagelayer-grid-gallery-caption">'.$image['caption'].'</span>';
1500 }
1501
1502 if(!empty($el['atts']['link_to'])){
1503 $li .= '</a>';
1504 }
1505
1506 if(empty($el['atts']['link_to'])){
1507 $li .= '</div>';
1508 }
1509
1510 $li .= '</li>';
1511
1512 $ul[] = $li;
1513 $i++;
1514 }
1515
1516 $ul[] = '</ul>';
1517
1518 $pagiComplete[] = '<div class="pagelayer-grid-gallery-pagination"><ul class="pagelayer-grid-page-ul">'.'<li class="pagelayer-grid-page-item">&laquo;</li>'.$pagin.'<li class="pagelayer-grid-page-item">&raquo;</li>'.'</ul></div>';
1519 //pagelayer_print($urls);
1520 //pagelayer_print($final_urls);
1521 //pagelayer_print($all_urls);
1522
1523 // Make the TMP vars
1524 if(!empty($urls)){
1525 $el['tmp']['ids-urls'] = json_encode($urls);
1526 $el['tmp']['ids-all-urls'] = json_encode($all_urls);
1527 $el['tmp']['ids-all-links'] = json_encode($links);
1528 $el['tmp']['ids-all-titles'] = json_encode($titles);
1529 $el['tmp']['ids-all-captions'] = json_encode($captions);
1530 $el['atts']['ul'] = implode('', $ul);
1531 $el['atts']['pagin'] = ($j>1) ? implode('', $pagiComplete) : '';
1532 $el['tmp']['gallery-random-id'] = $gallery_rand;
1533
1534 }
1535 }
1536
1537 // Testimonial Handler
1538 function pagelayer_sc_testimonial(&$el){
1539
1540 if(empty($el['atts']['avatar']) || !empty($el['tmp']['avatar-no-image-set'])){
1541 $el['atts']['avatar'] = '';
1542 }
1543
1544 $custom_size = empty($el['atts']['custom_size']) ? '' : @$el['tmp']['avatar-'.$el['atts']['custom_size'].'-url'];
1545 $el['atts']['func_image'] = empty($custom_size) ? @$el['tmp']['avatar-url'] : $custom_size;
1546
1547 }
1548
1549 // Video Handler
1550 function pagelayer_sc_video(&$el){
1551
1552 $el['atts']['custom_size'] = empty($el['atts']['custom_size']) ? '' : $el['atts']['custom_size'];
1553 $el['tmp']['video_overlay_image-url'] = empty($el['tmp']['video_overlay_image-url']) ? '' : $el['tmp']['video_overlay_image-url'];
1554 $el['atts']['video_overlay_image'] = empty($el['atts']['video_overlay_image']) ? '' : $el['atts']['video_overlay_image'];
1555
1556 $el['atts']['video_overlay_image-url'] = empty($el['tmp']['video_overlay_image-'.$el['atts']['custom_size'].'-url']) ? $el['tmp']['video_overlay_image-url'] : $el['tmp']['video_overlay_image-'.$el['atts']['custom_size'].'-url'];
1557 $el['atts']['video_overlay_image-url'] = empty($el['atts']['video_overlay_image-url']) ? $el['atts']['video_overlay_image'] : $el['atts']['video_overlay_image-url'];
1558
1559 // Get the video URL for the iframe
1560 $vid_atts = pagelayer_video_url($el['tmp']['src-url'], true);
1561
1562 $vid_atts['src'] .= substr_count($vid_atts['src'], '?') > 0 ? '' : '?';
1563
1564 $vid_atts['src'] .= !empty($el['atts']['autoplay']) ? '&autoplay=1' : '&autoplay=0' ;
1565
1566 $mute = !empty($el['atts']['mute']) ? 1 : 0;
1567 $vid_atts['src'] .='&'.($vid_atts['type'] == 'vimeo' ? 'muted' : 'mute').'='.$mute;
1568
1569 $vid_atts['src'] .= !empty($el['atts']['loop']) == 'true' ? '&loop=1' : '&loop=0' ;
1570
1571 $el['atts']['vid_src'] = $vid_atts['src'].($vid_atts['type'] == 'youtube' ? '&playlist='.$vid_atts['id'] : '');
1572
1573 $el['tmp']['ele_id'] = $el['id'];
1574
1575 }
1576
1577 // Shortcodes Handler
1578 function pagelayer_sc_shortcodes(&$el){
1579 $is_live = pagelayer_is_live();
1580 if(empty($is_live)){
1581 $el['tmp']['shortcode'] = pagelayer_the_content($el['atts']['data']);
1582 }
1583 }
1584
1585 // Missing Handler
1586 function pagelayer_sc_missing(&$el){
1587 if(pagelayer_is_live()){
1588 $el['tmp']['missing_msg'] = __('The pagelayer doesn’t support this content. You can leave this block intact or remove it completely.');
1589 }
1590 }
1591
1592 // Shortcodes Handler
1593 function pagelayer_sc_wp_widgets(&$el){
1594
1595 global $wp_registered_sidebars;
1596
1597 $data = '';
1598 foreach($wp_registered_sidebars as $v){
1599 if($el['atts']['sidebar'] == $v['id']){
1600 ob_start();
1601 dynamic_sidebar($v['id']);
1602 $data = ob_get_clean();
1603 }
1604 }
1605
1606 $el['tmp']['data'] = $data;
1607 }
1608
1609 // Service Handler
1610 function pagelayer_sc_service(&$el){
1611
1612 //Backward compatibility for new link props
1613 pagelayer_add_link_backward($el, array(
1614 'link' => 'box_url',
1615 'rel' => '',
1616 'target' => 'box_target',
1617 'selector' => '.pagelayer-box-link'
1618 ));
1619
1620 //Backward compatibility for new link props
1621 pagelayer_add_link_backward($el, array(
1622 'link' => 'heading_url',
1623 'rel' => '',
1624 'target' => 'heading_target',
1625 'selector' => '.pagelayer-service-heading-link'
1626 ));
1627
1628 //Backward compatibility for new link props
1629 pagelayer_add_link_backward($el, array(
1630 'link' => 'service_button_url',
1631 'rel' => '',
1632 'target' => 'service_button_target',
1633 'selector' => '.pagelayer-service-btn'
1634 ));
1635
1636 if(!empty($el['atts']['service_image'])){
1637
1638 // Decide the image URL
1639 $el['atts']['func_image'] = @$el['tmp']['service_image-'.$el['atts']['service_image_size'].'-url'];
1640 $el['atts']['func_image'] = empty($el['atts']['func_image']) ? @$el['tmp']['service_image-url'] : $el['atts']['func_image'];
1641 $el['atts']['pagelayer-srcset'] = $el['atts']['func_image'].', '.$el['atts']['func_image'].' 1x, ';
1642
1643 $image_atts = array(
1644 'name' => 'service_image',
1645 'size' => 'service_image_size'
1646 );
1647
1648 pagelayer_get_img_srcset($el, $image_atts);
1649
1650 }
1651 }
1652
1653 // Icon box Handler
1654 function pagelayer_sc_iconbox(&$el){
1655
1656 //Backward compatibility for new link props
1657 pagelayer_add_link_backward($el, array(
1658 'link' => 'box_url',
1659 'rel' => '',
1660 'target' => 'box_target',
1661 'selector' => '.pagelayer-box-link'
1662 ));
1663
1664 //Backward compatibility for new link props
1665 pagelayer_add_link_backward($el, array(
1666 'link' => 'heading_url',
1667 'rel' => '',
1668 'target' => 'heading_target',
1669 'selector' => '.pagelayer-service-heading-link',
1670 ));
1671
1672 }
1673
1674 // Anchor Handler
1675 function pagelayer_sc_anchor(&$el){
1676 $el['atts']['title'] = empty($el['atts']['title']) ? '' : esc_attr(sanitize_html_class( $el['atts']['title']));
1677 }
1678
1679 function pagelayer_sc_google_maps(&$el){
1680
1681 $el['atts']['show_v2'] = true;
1682
1683 if(empty($el['atts']['api_version'])){
1684 $el['atts']['src_code'] = '';
1685 return;
1686 }
1687
1688 $el['atts']['show_v2'] = false;
1689 $api_key = @$el['atts']['api_key'];
1690
1691 $gmaps_api = get_option('pagelayer-gmaps-api-key');
1692
1693 if( empty($api_key) && !empty($gmaps_api) ){
1694 $api_key = $gmaps_api;
1695 }
1696
1697 if($el['atts']['map_modes'] == 'view'){
1698 $el['atts']['center'] = empty($el['atts']['center']) ? '-33.8569,151.2152' : $el['atts']['center'];
1699 }
1700
1701 $src_code = (empty($el['atts']['center']) ? '' : '&center='.$el['atts']['center']).($el['atts']['map_modes'] == 'streetview' ? '' : '&maptype='.$el['atts']['map_type'].'&zoom='.$el['atts']['zoom']);
1702
1703 switch($el['atts']['map_modes']){
1704 case 'place':
1705 $src_code .= '&q='.(empty($el['atts']['address']) ? 'New York, New York, USA' : urlencode($el['atts']['address']) );
1706 break;
1707
1708 case 'directions':
1709 $src_code .= '&origin='.(empty($el['atts']['direction_origin']) ? 'Oslow Norway' : urlencode($el['atts']['direction_origin']) );
1710 $src_code .= '&destination='.(empty($el['atts']['direction_destination']) ? 'Telemark Norway' : urlencode($el['atts']['direction_destination']) );
1711 $src_code .= (empty($el['atts']['direction_waypoints']) ? '' : '&waypoints='.join('|', explode(' ', trim($el['atts']['direction_waypoints']))) );
1712 $src_code .= (empty($el['atts']['direction_modes']) ? '' : '&mode='.$el['atts']['direction_modes'] );
1713 $src_code .= (empty($el['atts']['direction_avoid']) ? '' : '&avoid='.join('|', explode(',', $el['atts']['direction_avoid'])) );
1714 $src_code .= (empty($el['atts']['direction_units']) ? '' : '&units='.$el['atts']['direction_units'] );
1715 break;
1716
1717 case 'streetview':
1718 $src_code .= '&pano='.(empty($el['atts']['streetview_pano']) ? 'eTnPNGoy4bxR9LpjjfFuOw' : $el['atts']['streetview_pano'] );
1719 $src_code .= '&location='.(empty($el['atts']['streetview_location']) ? '46.414382,10.013988' : $el['atts']['streetview_location'] );
1720 $src_code .= (empty($el['atts']['streetview_heading']) ? '' : '&heading='.$el['atts']['streetview_heading'] );
1721 $src_code .= (empty($el['atts']['streetview_pitch']) ? '' : '&pitch='.$el['atts']['streetview_pitch'] );
1722 $src_code .= (empty($el['atts']['streetview_fov']) ? '' : '&fov='.$el['atts']['streetview_fov'] );
1723 break;
1724
1725 case 'search':
1726 $src_code .= '&q='.(empty($el['atts']['search_term']) ? 'Record stores in Seattle' : urlencode($el['atts']['search_term']) );
1727 break;
1728
1729 }
1730
1731 $src_iframe = 'https://www.google.com/maps/embed/v1/'.$el['atts']['map_modes'].'?key='.$api_key.$src_code;
1732
1733 $el['atts']['src_code'] = '<iframe width="600" height="450" style="border:0" loading="lazy" allowfullscreen src="'.$src_iframe.'"></iframe>';
1734
1735 }
1736
1737 /*pagelayer_print($atts);
1738 pagelayer_print($content);
1739 die();*/
1740
1741 /////////////////////////////////////
1742 // Miscellaneous Shortcode Functions
1743 /////////////////////////////////////
1744
1745 // The font family list
1746 function pagelayer_font_family(){
1747 return array(
1748 'arial' => 'Arial',
1749 'terminal' => 'Terminal'
1750 );
1751 }
1752
1753 // Supported Icons
1754 function pagelayer_icon_class_list(){
1755 return array();
1756 }
1757
1758 // The attribute names Pagelayer is allowed to emit from a user supplied
1759 // attribute string. This is an ALLOWLIST and it is enforced at parse time,
1760 // so it applies to every call site (Custom Attributes, link attrs, anything
1761 // added later), to every visitor and to content stored by any version.
1762 function pagelayer_allowed_attributes(){
1763
1764 static $allowed = null;
1765
1766 if(!is_null($allowed)){
1767 return $allowed;
1768 }
1769
1770 $allowed = array(
1771 // Generic / structural
1772 'id', 'class', 'style', 'title', 'lang', 'dir', 'tabindex', 'hidden',
1773 'role', 'name', 'value', 'type', 'slot', 'translate', 'draggable',
1774 'spellcheck', 'accesskey', 'itemprop', 'itemtype', 'itemscope', 'itemid',
1775 // Links
1776 'href', 'target', 'rel', 'download', 'hreflang', 'referrerpolicy', 'ping',
1777 // Media / images
1778 'src', 'srcset', 'sizes', 'alt', 'width', 'height', 'loading', 'decoding',
1779 'crossorigin', 'usemap', 'ismap', 'poster', 'preload', 'controls',
1780 'controlslist', 'loop', 'muted', 'autoplay', 'playsinline', 'kind',
1781 'srclang', 'label', 'default', 'disablepictureinpicture',
1782 'disableremoteplayback',
1783 // Forms
1784 'placeholder', 'required', 'disabled', 'readonly', 'pattern', 'min',
1785 'max', 'step', 'maxlength', 'minlength', 'multiple', 'size', 'checked',
1786 'selected', 'autocomplete', 'autofocus', 'for', 'form', 'action',
1787 'method', 'enctype', 'novalidate', 'accept', 'accept-charset', 'cols',
1788 'rows', 'wrap', 'list', 'inputmode', 'formaction', 'formmethod',
1789 'formenctype', 'formtarget', 'formnovalidate',
1790 // Tables
1791 'colspan', 'rowspan', 'headers', 'scope', 'abbr', 'span',
1792 // Misc
1793 'datetime', 'cite', 'open', 'start', 'reversed', 'coords', 'shape',
1794 'high', 'low', 'optimum', 'media', 'content'
1795 );
1796
1797 // Add-ons can register extra attribute names. Event handlers are dropped
1798 // by pagelayer_is_allowed_attribute() whatever this filter returns.
1799 $allowed = apply_filters('pagelayer_allowed_attributes', $allowed);
1800 $allowed = array_map('strtolower', (array) $allowed);
1801
1802 return $allowed;
1803 }
1804
1805 // Can this attribute name be emitted ?
1806 function pagelayer_is_allowed_attribute($att){
1807
1808 $att = strtolower(trim((string) $att));
1809
1810 if($att === ''){
1811 return false;
1812 }
1813
1814 // Never emit an event handler, whatever the allowlist says
1815 if(strpos($att, 'on') === 0){
1816 return false;
1817 }
1818
1819 // data-* and aria-* never execute
1820 if(strpos($att, 'data-') === 0 || strpos($att, 'aria-') === 0){
1821 return true;
1822 }
1823
1824 return in_array($att, pagelayer_allowed_attributes());
1825 }
1826
1827 // Does this URL carry a scheme that can execute script ?
1828 function pagelayer_attribute_url_is_safe($url){
1829
1830 $url = pagelayer_optimized_decode_entities((string) $url);
1831
1832 // Browsers also decode a numeric entity that was not closed with a
1833 // semicolon (jav&#x09ascript:), so decode those the same way
1834 $url = preg_replace_callback('/&#x([0-9a-f]+);?/i', function($m){
1835 return chr(hexdec($m[1]) & 0xFF);
1836 }, $url);
1837
1838 $url = preg_replace_callback('/&#(\d+);?/', function($m){
1839 return chr(((int) $m[1]) & 0xFF);
1840 }, $url);
1841
1842 // Browsers ignore control characters and whitespace inside a scheme
1843 $url = preg_replace('/[\x00-\x20\x7f]/', '', $url);
1844
1845 if($url === ''){
1846 return true;
1847 }
1848
1849 // No colon means a relative URL, nothing to check
1850 $scheme = strstr($url, ':', true);
1851
1852 if($scheme === false){
1853 return true;
1854 }
1855
1856 // A colon inside a path, a query or a fragment is not a scheme
1857 if(preg_match('#[/?\#]#', $scheme)){
1858 return true;
1859 }
1860
1861 // What is left is flattened to letters, so that a stray character cannot
1862 // hide the scheme from us
1863 $scheme = strtolower(preg_replace('/[^a-z]/i', '', $scheme));
1864
1865 // javascript:, vbscript:, livescript: and any other script scheme
1866 if(strpos($scheme, 'script') !== false){
1867 return false;
1868 }
1869
1870 // Only plain raster data URIs are allowed, no SVG and no blob/file/about
1871 if(in_array($scheme, array('data', 'blob', 'about', 'file', 'filesystem'))){
1872 return (bool) preg_match('/^data:image\/(png|jpe?g|gif|webp|bmp|x-icon|vnd\.microsoft\.icon);base64,[a-z0-9+\/=]+$/i', $url);
1873 }
1874
1875 return true;
1876 }
1877
1878 // Sanitize the value of an allowed attribute. Returns NULL if the whole
1879 // attribute must be dropped.
1880 function pagelayer_sanitize_attribute_value($att, $value){
1881
1882 $att = strtolower(trim((string) $att));
1883 $value = (string) $value;
1884
1885 // Attributes that hold one or more URLs
1886 $url_atts = array('href', 'src', 'srcset', 'poster', 'action', 'formaction',
1887 'cite', 'ping', 'usemap', 'itemtype', 'itemid');
1888
1889 if(in_array($att, $url_atts)){
1890
1891 // srcset and ping can hold a list of URLs
1892 $parts = preg_split('/[,\s]+/', trim($value), -1, PREG_SPLIT_NO_EMPTY);
1893
1894 if(!empty($parts)){
1895 foreach($parts as $part){
1896 if(!pagelayer_attribute_url_is_safe($part)){
1897 return null;
1898 }
1899 }
1900 }
1901
1902 return $value;
1903 }
1904
1905 // Inline CSS can execute in some engines
1906 if($att == 'style'){
1907
1908 $test = pagelayer_optimized_decode_entities($value);
1909 $test = preg_replace('/[\x00-\x20\x7f]/', '', $test);
1910
1911 if(preg_match('/(expression\(|-moz-binding|behavior:|@import|script:)/i', $test)){
1912 return null;
1913 }
1914 }
1915
1916 return $value;
1917 }
1918
1919 // Function to convert string into set of attributes and their corresponding values.
1920 function pagelayer_string_to_attributes($val){
1921
1922 $final_att = [];
1923 $semi_arr = explode(';', $val);
1924
1925 foreach($semi_arr as $att){
1926
1927 $attrs = preg_split("/=/", trim($att), 2);
1928
1929 if(empty($attrs[0]) || !preg_match("/^[a-z_]+[\w:.-]*$/i", $attrs[0]) ){
1930 continue;
1931 }
1932
1933 $name = strtolower(trim($attrs[0]));
1934
1935 // SECURITY : only attribute names we support are emitted. The check
1936 // lives here, at the parser, so it does not depend on the call site,
1937 // on who is viewing the page or on when the content was stored.
1938 if(pagelayer_should_show_xss_warning() && !pagelayer_is_allowed_attribute($name)){
1939 continue;
1940 }
1941
1942 $value = isset($attrs[1]) ? $attrs[1] : '';
1943 $value = pagelayer_sanitize_attribute_value($name, $value);
1944
1945 // Dropped by the value check ?
1946 if(is_null($value)){
1947 continue;
1948 }
1949
1950 $final_att[$name] = $value;
1951 }
1952
1953 return $final_att;
1954
1955 }
1956
1957 // Retina image setting attribute.
1958 function pagelayer_get_img_srcset(&$el, $image_atts){
1959
1960 // Check if retina images is set
1961 if(isset($el['tmp'][$image_atts['name'].'-retina-url']) && strpos($el['tmp'][$image_atts['name'].'-retina-url'],'default-image') == false){
1962 $retina_image = @$el['tmp'][$image_atts['name'].'-retina-'.$el['atts'][$image_atts['size']].'-url'];
1963 $retina_image = empty($retina_image) ? @$el['tmp'][$image_atts['name'].'-retina-url'] : $retina_image;
1964 $el['atts']['pagelayer-srcset'] .= $retina_image.' 2x, ';
1965 }
1966
1967 // Check if retina mobile images is set
1968 if(isset($el['tmp'][$image_atts['name'].'-retina-mobile-url']) && strpos($el['tmp'][$image_atts['name'].'-retina-mobile-url'],'default-image') == false){
1969 $retina_image_mobile = @$el['tmp'][$image_atts['name'].'-retina-mobile-'.$el['atts'][$image_atts['size']].'-url'];
1970 $retina_image_mobile = empty($retina_image_mobile) ? @$el['tmp'][$image_atts['name'].'-retina-mobile-url'] : $retina_image_mobile;
1971 $el['atts']['pagelayer-srcset'] .= $retina_image_mobile.' 3x';
1972 }
1973 }
1974
1975 // Backward compatibility of target and rel attrs for link
1976 function pagelayer_add_link_backward(&$el, $atts = array()){
1977 global $pagelayer;
1978
1979 $defaults = array(
1980 'link' => 'link',
1981 'target' => 'target',
1982 'rel' => 'rel',
1983 'selector' => 0,
1984 );
1985
1986 $_atts = wp_parse_args( $atts, $defaults );
1987
1988 if(empty($el['atts'][$_atts['link']])){
1989 return;
1990 }
1991
1992 $link = array();
1993
1994 if(!empty($_atts['target']) && !empty($el['atts'][$_atts['target']]) ){
1995 $link['target'] = true;
1996 unset($el['oAtts'][$_atts['target']]);
1997 }
1998
1999 if(!empty($_atts['rel']) && !empty($el['atts'][$_atts['rel']]) ){
2000 $link['attrs'] = 'rel='.$el['atts'][$_atts['rel']];
2001 unset($el['oAtts'][$_atts['rel']]);
2002 }
2003
2004 if(empty($link)){
2005 return;
2006 }
2007
2008 // Set Attributes for backward compatibility
2009 if(!empty($link['target'])){
2010 $el['attr'][][$_atts['selector']] = 'target="_blank"';
2011 }
2012
2013 // Set Attributes for backward compatibility
2014 if(!empty($link['attrs']) ){
2015 $el['attr'][][$_atts['selector']] = $link['attrs'];
2016 }
2017
2018 if(!is_array($el['atts'][$_atts['link']])){
2019 $link['link'] = @$el['atts'][$_atts['link']];
2020 }
2021
2022 $el['oAtts'][$_atts['link']] = $link;
2023 $el['atts'][$_atts['link']] = $link;
2024 }
2025