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
← All changes | main/shortcode_functions.php +2024 -1014 1.0.22.2.0 View file →
@@ -1,1014 +1,2024 @@
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 tag ?
28 -function pagelayer_render_shortcode($atts, $content = '', $tag = ''){
29 -
30 - global $pagelayer;
31 -
32 - $_tag = $class = $tag;
33 - $final_tag = $tag;
34 -
35 - // Check if the tag is inner row and col then change it to row and col tag
36 - if($tag == 'pl_inner_row'){
37 - $tag = 'pl_row';
38 - }elseif($tag == 'pl_inner_col'){
39 - $tag = 'pl_col';
40 - $final_tag = $tag;
41 - }
42 -
43 - // Clear the pagelayer tags
44 - if(substr($tag, 0, 3) == 'pl_'){
45 - $_tag = str_replace('pl_', '', $final_tag);
46 - $class = 'pagelayer-'.$_tag;
47 - }
48 -
49 - // Is there any function ?
50 - $func = @$pagelayer->shortcodes[$tag]['func'];
51 - $atts = (array) $atts;
52 - // Create the element array. NOTE : This is similar to the JS el and is temporary
53 - $el = [];
54 - $el['atts'] = $atts;
55 - $el['oAtts'] = $atts;
56 - $el['id'] = pagelayer_RandomString(16);
57 - $el['tmp'] = [];
58 - $el['tag'] = $final_tag;
59 - $el['content'] = $content;
60 - $el['selector'] = '[pagelayer-id="'.$el['id'].'"]';
61 - $el['wrap'] = '[pagelayer-wrap-id="'.$el['id'].'"]';
62 -
63 - $innerHTML = @$pagelayer->shortcodes[$tag]['innerHTML'];
64 - if(!empty($innerHTML) && !empty($content)){
65 - $el['oAtts'][$innerHTML] = $content;
66 - $el['atts'][$innerHTML] = $content;
67 - }
68 -
69 - // The default class
70 - $el['classes'][] = $class;
71 -
72 - //pagelayer_print($el);
73 -
74 - // Lets create the CSS, Classes, Attr. Also clean the dependent atts
75 - foreach($pagelayer->tabs as $tab){
76 -
77 - if(empty($pagelayer->shortcodes[$tag][$tab])){
78 - continue;
79 - }
80 -
81 - foreach($pagelayer->shortcodes[$tag][$tab] as $section => $Lsection){
82 -
83 - $props = empty($pagelayer->shortcodes[$tag][$section]) ? @$pagelayer->styles[$section] : @$pagelayer->shortcodes[$tag][$section];
84 -
85 - //echo $tab.' - '.$section.' - <br>';
86 -
87 - if(empty($props)){
88 - continue;
89 - }
90 -
91 - foreach($props as $prop => $param){
92 -
93 - //echo $tab.' - '.$section.' - '.$prop.'<br>';
94 -
95 - // No value set
96 - if(empty($el['atts'][$prop]) && empty($el['atts'][$prop.'_tablet']) && empty($el['atts'][$prop.'_mobile'])){
97 - continue;
98 - }
99 -
100 - // Clean the not required atts
101 - if(!empty($param['req'])){
102 -
103 - $set = true;
104 -
105 - foreach($param['req'] as $rk => $reqval){
106 - $except = $rk{0} == '!' ? true : false;
107 - $rk = $except ? substr($rk, 1) : $rk;
108 - $val = @$el['atts'][$rk];
109 -
110 - //echo $prop.' - '.$rk.' : '.$reqval.' == '.$val.'<br>';
111 -
112 - // The value should not be there
113 - if($except){
114 -
115 - if(!is_array($reqval) && $reqval == $val){
116 - $set = false;
117 - break;
118 - }
119 -
120 - // Its an array and a value is found, then dont show
121 - if(is_array($reqval) && in_array($val, $reqval)){
122 - $set = false;
123 - break;
124 - }
125 -
126 - // The value must be equal
127 - }else{
128 -
129 - if(!is_array($reqval) && $reqval != $val){
130 - $set = false;
131 - break;
132 - }
133 -
134 - // Its an array and no value is found, then dont show
135 - if(is_array($reqval) && !in_array($val, $reqval)){
136 - $set = false;
137 - break;
138 - }
139 - }
140 -
141 - }
142 -
143 - // Unset as we dont need
144 - if(empty($set)){
145 - unset($el['atts'][$prop]);
146 - unset($el['atts'][$prop.'_tablet']);
147 - unset($el['atts'][$prop.'_mobile']);
148 - }
149 -
150 - }
151 -
152 - // We could have unset the value above, so we need to check again if the value is there
153 - if(empty($el['atts'][$prop]) && empty($el['atts'][$prop.'_tablet']) && empty($el['atts'][$prop.'_mobile'])){
154 - continue;
155 - }
156 -
157 - // Handle the edit fields
158 - if(!empty($param['edit'])){
159 - $el['edit'][$prop] = $param['edit'];
160 - }
161 -
162 - // Backward compatibility of Icons
163 - if($param['type'] == 'icon' && !empty($el['atts'][$prop]) && !preg_match('/\s/', $el['atts'][$prop])){
164 - $el['atts'][$prop] = $el['oAtts'][$prop] = 'fa fa-'.$el['atts'][$prop];
165 - }
166 -
167 - // Backward compatibility of Box Shadow
168 - if($param['type'] == 'box_shadow' && !empty($el['atts'][$prop]) && substr_count($el['atts'][$prop], ',') == 3){
169 - $el['atts'][$prop] = $el['oAtts'][$prop] = $el['atts'][$prop].',0,';
170 - }
171 -
172 - // Load any attachment values
173 - if(in_array($param['type'], ['image', 'video', 'audio', 'media'])){
174 -
175 - $attachment = ($param['type'] == 'image') ? pagelayer_image($el['atts'][$prop]) : pagelayer_attachment($el['atts'][$prop]);
176 -
177 - if(!empty($attachment)){
178 - foreach($attachment as $k => $v){
179 - $el['tmp'][$prop.'-'.$k] = $v;
180 - }
181 - }
182 -
183 - }
184 -
185 - // Handle the AddClasses
186 - if(!empty($param['addClass']) && !empty($el['atts'][$prop])){
187 -
188 - // Convert to an array
189 - if(!is_array($param['addClass'])){
190 - $param['addClass'] = array($param['addClass']);
191 - }
192 -
193 - // Loop through
194 - foreach($param['addClass'] as $k => $v){
195 - $k = str_replace('{{element}}', '', $k);
196 - $el['classes'][] = [trim($k) => str_replace('{{val}}', $el['atts'][$prop], $v)];
197 - }
198 -
199 - }
200 -
201 - // Handle the AddClasses
202 - if(!empty($param['addAttr']) && !empty($el['atts'][$prop])){
203 -
204 - // Convert to an array
205 - if(!is_array($param['addAttr'])){
206 - $param['addAttr'] = array($param['addAttr']);
207 - }
208 -
209 - // Loop through
210 - foreach($param['addAttr'] as $k => $v){
211 - $k = str_replace('{{element}}', '', $k);
212 - $el['attr'][] = [trim($k) => $v];
213 - }
214 -
215 - }
216 -
217 - // Handle the CSS
218 - if(!empty($param['css'])){
219 - //echo $prop.'<br>';
220 - // Convert to an array
221 - if(!is_array($param['css'])){
222 - $param['css'] = array($param['css']);
223 - }
224 -
225 - $modes = [
226 - 'desktop' => '',
227 - 'tablet' => '_tablet',
228 - 'mobile' => '_mobile'
229 - ];
230 -
231 - // Loop the modes and check for values
232 - foreach($modes as $mk => $mv){
233 -
234 - $M_prop = $prop.$mv;
235 -
236 - // Any value ?
237 - if(empty($el['atts'][$M_prop])){
238 - continue;
239 - }
240 -
241 - // Loop through
242 - foreach($param['css'] as $k => $v){
243 -
244 - // Make the selector
245 - $selector = (!is_numeric($k) ? $k : $el['selector']);
246 - $selector = pagelayer_parse_el_vars($selector, $el);
247 -
248 - $ender = '';
249 -
250 - if($mk == 'tablet'){
251 - $selector = '@media (max-width: 768px) and (min-width: 361px){'.$selector;
252 - $ender = '}';
253 - }
254 -
255 - if($mk == 'mobile'){
256 - $selector = '@media (max-width: 360px){'.$selector;
257 - $ender = '}';
258 - }
259 -
260 - if(!empty($selector)){
261 - // Make the CSS
262 - $el['css'][] = $selector.'{'.pagelayer_css_render($v, $el['atts'][$M_prop], @$param['sep']).'}'.$ender;
263 - }else{
264 - $el['css'][] = pagelayer_parse_el_vars($el['atts'][$M_prop],$el);
265 - }
266 - }
267 -
268 - }
269 -
270 - }
271 -
272 - if($param['type'] == 'typography'){
273 - $val = explode(',', $el['atts'][$prop]);
274 -
275 - if(!empty($val[0]) && !in_array($val[0], $pagelayer->runtime_fonts)){
276 - $pagelayer->runtime_fonts[] = $val[0];
277 - //pagelayer_print($pagelayer->runtime_fonts);
278 - }
279 - }
280 -
281 - }
282 -
283 - }
284 -
285 - }
286 -
287 - //@pagelayer_print($el['css']);
288 -
289 - // Is there a function of the tag ?
290 - if(function_exists($func)){
291 - call_user_func_array($func, array(&$el));
292 - }
293 -
294 - // Create the default atts and tmp atts
295 - if(pagelayer_is_live()){
296 - pagelayer_create_sc($el);
297 - }
298 -
299 - $div = '<div pagelayer-id="'.$el['id'].'">
300 - <style pagelayer-style-id="'.$el['id'].'"></style>';
301 -
302 - $is_group = !empty($pagelayer->shortcodes[$tag]['params']['elements']) ? true : false;
303 -
304 - // If there is an HTML AND you are not a GROUP, then make use of it, or append the real content
305 - if(!empty($pagelayer->shortcodes[$tag]['html'])){
306 -
307 - // Create the HTML object
308 - $node = pQuery::parseStr($pagelayer->shortcodes[$tag]['html']);
309 -
310 - // Remove the if-ext
311 - foreach($node('[if-ext]') as $v){
312 - $reqvar = pagelayer_var($v->attr('if-ext'));
313 - $v->removeAttr('if-ext');
314 -
315 - // Is the element there ?
316 - if(empty($el['atts'][$reqvar])){
317 - $v->after($v->html());
318 - $v->remove();
319 - }
320 - }
321 -
322 - // Remove the if
323 - foreach($node('[if]') as $v){
324 - $reqvar = pagelayer_var($v->attr('if'));
325 - $v->removeAttr('if');
326 -
327 - // Is the element there ?
328 - if(empty($el['atts'][$reqvar])){
329 - $v->remove();
330 - }
331 - }
332 -
333 - //die($node->html());
334 -
335 - // Do we have a holder ? Mainly for groups
336 - if(!empty($pagelayer->shortcodes[$tag]['holder'])){
337 - $node->query($pagelayer->shortcodes[$tag]['holder'])->html('{{pagelayer_do_shortcode}}');
338 - $do_shortcode = 1;
339 - }
340 -
341 - $html = pagelayer_parse_vars($node->html(), $el);
342 -
343 - // Append to the DIV
344 - $div .= $html;
345 -
346 - // Is it a widget ?
347 - }elseif(!empty($pagelayer->shortcodes[$tag]['widget'])){
348 -
349 - $class = $pagelayer->shortcodes[$tag]['widget'];
350 - $instance = [];
351 -
352 - // Is there any existing data ?
353 - if(!empty($el['atts']['widget_data'])){
354 - $json = trim($el['atts']['widget_data']);
355 - $json = json_decode($json, true);
356 - //pagelayer_print($json);die();
357 - if(!empty($json)){
358 - $instance = $json;
359 - }
360 - }
361 -
362 - ob_start();
363 - the_widget($class, $instance, array('widget_id'=>'arbitrary-instance-'.$el['id'],
364 - 'before_widget' => '',
365 - 'after_widget' => '',
366 - 'before_title' => '',
367 - 'after_title' => ''
368 - ));
369 -
370 - $div .= ob_get_contents();
371 - ob_end_clean();
372 -
373 - }else{
374 - $div .= '{{pagelayer_do_shortcode}}';
375 - $do_shortcode = 1;
376 - }
377 -
378 - // End the tag
379 - $div .= '</div>';
380 -
381 - // Add classes and attributes
382 - if(!empty($el['classes']) || !empty($el['attr'])){
383 -
384 - // Create the HTML object
385 - $node = pQuery::parseStr($div);
386 -
387 - // Add the editable values
388 - if(!empty($el['edit'])){
389 -
390 - foreach($el['edit'] as $k => $v){
391 - $node->query($v)->attr('pagelayer-editable', $k);
392 - }
393 -
394 - }
395 -
396 - // Add the classes
397 - if(!empty($el['classes'])){
398 -
399 - //pagelayer_print($el['classes']);
400 -
401 - foreach($el['classes'] as $k => $v){
402 -
403 - if(!is_array($v)){
404 - $v = [$v];
405 - }
406 -
407 - foreach($v as $kk => $vv){
408 - //echo $kk.' - '.$vv."\n";
409 - if(is_numeric($kk)){
410 - $node->query($el['selector'])->addClass($vv);
411 - }else{
412 - $node->query($kk)->addClass($vv);
413 - }
414 -
415 - }
416 -
417 - }
418 -
419 - //echo $node->html();
420 - //die();
421 -
422 - }
423 -
424 - // Add the attributes
425 - if(!empty($el['attr'])){
426 -
427 - //pagelayer_print($el['attr']);
428 -
429 - foreach($el['attr'] as $k => $v){
430 -
431 - if(!is_array($v)){
432 - $v = [$v];
433 - }
434 -
435 - foreach($v as $kk => $vv){
436 -
437 - $att = explode('=', $vv, 2);
438 - $att[1] = pagelayer_parse_vars($att[1], $el);
439 - $att[1] = trim($att[1], '"');
440 -
441 - if(is_numeric($kk)){
442 - $node->query($el['selector'])->attr($att[0], $att[1]);
443 - }else{
444 - $node->query($kk)->attr($att[0], $att[1]);
445 - }
446 -
447 - }
448 -
449 - }
450 -
451 - }
452 -
453 - $div = $node->html();
454 - //die($div);
455 -
456 - }
457 -
458 - // Add the CSS if any or remove it
459 - $style = '';
460 - if(!empty($el['css'])){
461 -
462 - $style = '<style pagelayer-style-id="'.$el['id'].'">
463 -'.implode("\n", pagelayer_parse_vars($el['css'], $el)).'
464 -</style>';
465 -
466 - if(!empty($pagelayer->shortcodes[$tag]['overide_css_selector'])){
467 - $style = str_replace($el['selector'], $pagelayer->shortcodes[$tag]['overide_css_selector'], $style);
468 - $style = str_replace($el['wrap'], $pagelayer->shortcodes[$tag]['overide_css_selector'], $style);
469 - }
470 -
471 - }
472 -
473 - $div = str_replace('<style pagelayer-style-id="'.$el['id'].'"></style>', $style, $div);
474 -
475 - // Is there an inner content which requires a SHORTCODE ?
476 - if(!empty($do_shortcode)){
477 - $div = str_replace('{{pagelayer_do_shortcode}}', do_shortcode($el['content']), $div);
478 - }
479 -
480 - return $div;
481 -
482 -}
483 -
484 -// Creates the shortcode and returns a base64 encoded files
485 -function pagelayer_create_sc(&$el){
486 -
487 - $a = $tmp = array();
488 -
489 - if(!empty($el['oAtts'])){
490 -
491 - foreach($el['oAtts'] as $k => $v){
492 - $el['attr'][] = 'pagelayer-a-'.$k.'="'.$v.'"';
493 - }
494 -
495 - }
496 -
497 - // Tmp atts
498 - if(!empty($el['tmp'])){
499 -
500 - foreach($el['tmp'] as $k => $v){
501 - $el['attr'][] = 'pagelayer-tmp-'.$k.'="'.$v.'"';
502 - }
503 -
504 - }
505 -
506 - // Add the tag
507 - $el['attr'][] = 'pagelayer-tag="'.$el['tag'].'"';
508 -
509 - // Make it a PageLayer element for editing
510 - $el['classes'][] = 'pagelayer-ele';
511 -
512 -}
513 -
514 -// Converts {{val}} to val
515 -function pagelayer_var($var){
516 - return substr($var, 2, -2);
517 -}
518 -
519 -// Replace the variables
520 -function pagelayer_parse_el_vars($str, &$el){
521 -
522 - $str = str_replace('{{element}}', $el['selector'], $str);
523 - $is_live = pagelayer_is_live();
524 - if(!empty($is_live)){
525 - $str = str_replace('{{wrap}}', $el['wrap'], $str);
526 - }else{
527 - $str = str_replace('{{wrap}}', $el['selector'], $str);
528 - }
529 - $str = str_replace('{{ele_id}}', $el['id'], $str);
530 -
531 - return $str;
532 -
533 -}
534 -
535 -// Parse the variables
536 -function pagelayer_parse_vars($str, &$el){
537 -
538 - //pagelayer_print($el);
539 - if(is_array($el['tmp'])){
540 - foreach($el['tmp'] as $k => $v){
541 - $str = str_replace('{{{'.$k.'}}}', $el['tmp'][$k], $str);
542 - }
543 - }
544 -
545 - if(is_array($el['atts'])){
546 - foreach($el['atts'] as $k => $v){
547 - $str = str_replace('{{'.$k.'}}', $el['atts'][$k], $str);
548 - }
549 - }
550 -
551 - return $str;
552 -}
553 -
554 -// Make the rule
555 -function pagelayer_css_render($rule, $val, $sep = ','){
556 -
557 - // Seperator
558 - $sep = empty($sep) ? ',' : $sep;
559 -
560 - // Replace the val
561 - $rule = str_replace('{{val}}', $val, $rule);
562 -
563 - // If there is an array
564 - if(preg_match('/\{val\[\d/is', $rule)){
565 - $val = explode($sep, $val);
566 - foreach($val as $k => $v){
567 - $rule = str_replace('{{val['.$k.']}}', $v, $rule);
568 - }
569 - }
570 -
571 - return $rule;
572 -
573 -}
574 -
575 -// Post Property Handler
576 -function pagelayer_sc_body(&$el){
577 -
578 - global $post;
579 -
580 - $el['oAtts']['post_title'] = $post->post_title;
581 - $el['oAtts']['post_name'] = $post->post_name;
582 - $el['oAtts']['post_excerpt'] = $post->post_excerpt;
583 - $el['oAtts']['post_status'] = $post->post_status;
584 - $el['oAtts']['featured_image'] = get_post_thumbnail_id($post);
585 -
586 - // Load featured image details
587 - if(!empty($el['oAtts']['featured_image'])){
588 -
589 - $attachment = pagelayer_image($el['oAtts']['featured_image']);
590 -
591 - if(!empty($attachment)){
592 - foreach($attachment as $k => $v){
593 - $el['tmp']['featured_image-'.$k] = $v;
594 - }
595 - }
596 -
597 - }
598 -
599 -}
600 -
601 -// ROW Handler
602 -function pagelayer_sc_row(&$el){
603 -
604 - pagelayer_bg_video($el);
605 -
606 - if(!empty($el['atts']['row_shape_type_top'])){
607 - $path_top = PAGELAYER_DIR.'/images/shapes/'.$el['atts']['row_shape_type_top'].'-top.svg';
608 - $el['atts']['svg_top'] = file_get_contents($path_top);
609 - }
610 -
611 - if(!empty($el['atts']['row_shape_type_bottom'])){
612 - $path_bottom = PAGELAYER_DIR.'/images/shapes/'.$el['atts']['row_shape_type_bottom'].'-bottom.svg';
613 - $el['atts']['svg_bottom'] = file_get_contents($path_bottom);
614 - }
615 -
616 - // Row background slider
617 - if(!empty($el['atts']['bg_slider'])){
618 - $ids = explode(',', $el['atts']['bg_slider']);
619 - $urls = [];
620 - $el['atts']['slider'] = '';
621 -
622 - // Make the image URL
623 - foreach($ids as $k => $v){
624 -
625 - $image = pagelayer_image($v);
626 - $urls['i'.$v] = @$image['full-url'];
627 -
628 - $el['atts']['slider'] .= '<div class="pagelayer-bgimg-slide" style="background-image:url(\''.$image['full-url'].'\')"></div>';
629 -
630 - }
631 -
632 - if(!empty($urls)){
633 - $el['tmp']['bg_slider-urls'] = json_encode($urls);
634 - }
635 -
636 - }
637 -}
638 -
639 -// Column Handler
640 -function pagelayer_sc_col(&$el){
641 -
642 - // Add the default col class
643 - $el['classes'][] = 'pagelayer-col';
644 -
645 - //return do_shortcode($el['content']);
646 -
647 - pagelayer_bg_video($el);
648 -
649 -}
650 -
651 -// Just for BG handling
652 -function pagelayer_bg_video(&$el){
653 -
654 - if(empty($el['tmp']['bg_video_src-url'])){
655 - return false;
656 - }
657 -
658 - // Get the video URL for the iframe
659 - $iframe_src = pagelayer_video_url($el['tmp']['bg_video_src-url']);
660 -
661 - $source = filter_var($el['tmp']['bg_video_src-url'], FILTER_SANITIZE_URL);
662 - $source = str_replace('&amp;', '&', $source);
663 - $url = parse_url($source);
664 -
665 - $youtubeRegExp = '/youtube\.com|youtu\.be/is';
666 - $vimeoRegExp = '/vimeo\.com/is';
667 -
668 - if (!empty($source)) {
669 -
670 - if (preg_match($youtubeRegExp, $source)) {
671 - if (preg_match('/youtube\.com/is', $source)) {
672 -
673 - if (preg_match('/watch/is', $source)) {
674 - parse_str($url['query'], $parameters);
675 -
676 - if (isset($parameters['v']) && !empty($parameters['v'])) {
677 - $videoId = $parameters['v'];
678 - }
679 -
680 - } else if (preg_match('/embed/is', $url['path'])) {
681 - $path = explode('/', $url['path']);
682 - if (isset($path[2]) && !empty($path[2])) {
683 - $videoId = $path[2];
684 - }
685 - }
686 -
687 - } else if (preg_match('/youtu\.be/is', $url['host'])) {
688 - $path = explode('/', $url['path']);
689 -
690 - if (isset($path[1]) && !empty($path[1])) {
691 - $videoId = $path[1];
692 - }
693 -
694 - }
695 -
696 - $el['atts']['vid_src'] = '<iframe src="'.$iframe_src.'?autoplay=1&controls=0&showinfo=0&rel=0&loop=1&autohide=1&playlist='.$videoId.'" allowfullscreen="1" webkitallowfullscreen="1" mozallowfullscreen="1" frameborder="0"></iframe>';
697 -
698 - } else if (preg_match($vimeoRegExp, $source)) {
699 -
700 - $el['atts']['vid_src'] = '<iframe src="'.$iframe_src.'?background=1&autoplay=1&loop=1&byline=0&title=0" allowfullscreen="1" webkitallowfullscreen="1" mozallowfullscreen="1" frameborder="0"></iframe>';
701 -
702 - }else{
703 -
704 - $el['atts']['vid_src'] = '<video autoplay loop>'.
705 - '<source src="'.$iframe_src.'" type="video/mp4">'.
706 - '</video>';
707 -
708 - }
709 - }
710 -}
711 -
712 -// Image Handler
713 -function pagelayer_sc_social(&$el){
714 - $icon = explode(' fa-', $el['atts']['icon']);
715 - $el['classes'][] = ['.pagelayer-icon-holder' => 'pagelayer-'.$icon[1]];
716 -}
717 -
718 -// Image Handler
719 -function pagelayer_sc_image(&$el){
720 -
721 - // Decide the image URL
722 - $el['atts']['func_id'] = @$el['tmp']['id-'.$el['atts']['id-size'].'-url'];
723 - $el['atts']['func_id'] = empty($el['atts']['func_id']) ? @$el['tmp']['id-full-url'] : $el['atts']['func_id'];
724 -
725 - // What is the link ?
726 - if(!empty($el['atts']['link_type'])){
727 -
728 - // Custom url
729 - if($el['atts']['link_type'] == 'custom_url'){
730 - $el['atts']['func_link'] = $el['atts']['link'];
731 - }
732 -
733 - // Link to the media file itself
734 - if($el['atts']['link_type'] == 'media_file'){
735 - $el['atts']['func_link'] = $el['atts']['func_id'];
736 - }
737 -
738 - // Lightbox
739 - if($el['atts']['link_type'] == 'lightbox'){
740 - $el['atts']['func_link'] = $el['atts']['func_id'];
741 - }
742 -
743 - }
744 -
745 - //pagelayer_print($el);
746 -
747 -}
748 -
749 -// Image Slider Handler
750 -function pagelayer_sc_image_slider(&$el){
751 -
752 - $ids = explode(',', $el['atts']['ids']);
753 - $urls = [];
754 - $all_urls = [];
755 - $final_urls = [];
756 - $ul = [];
757 - $size = $el['atts']['size'];
758 -
759 - // Make the image URL
760 - foreach($ids as $k => $v){
761 -
762 - $image = pagelayer_image($v);
763 -
764 - $final_urls[$v] = empty($image[$size.'-url']) ? @$image['full-url'] : $image[$size.'-url'];
765 -
766 - $urls['i'.$v] = @$image['full-url'];
767 -
768 - foreach($image as $kk => $vv){
769 - $si = strstr($kk, '-url', true);
770 - if(!empty($si)){
771 - $all_urls['i'.$v][$si] = $vv;
772 - }
773 - }
774 -
775 - $li = '<li class="pagelayer-slider-item">';
776 -
777 - // Any Link ?
778 - if(!empty($el['atts']['link_type'])){
779 - $link = ($el['atts']['link_type'] == 'media_file' ? $final_urls[$v] : @$el['atts']['link']);
780 - $li .= '<a href="'.$link.'">';
781 - }
782 -
783 - // The Image
784 - $li .= '<img class="pagelayer-img" src="'.$final_urls[$v].'">';
785 -
786 - if(!empty($el['atts']['link_type'])){
787 - $li .= '</a>';
788 - }
789 -
790 - $li .= '</li>';
791 -
792 - $ul[] = $li;
793 -
794 - }
795 -
796 - //pagelayer_print($urls);
797 - //pagelayer_print($final_urls);
798 - //pagelayer_print($all_urls);
799 -
800 - // Make the TMP vars
801 - if(!empty($urls)){
802 - $el['tmp']['ids-urls'] = json_encode($urls);
803 - $el['tmp']['ids-all-urls'] = json_encode($all_urls);
804 - $el['atts']['ul'] = implode('', $ul);
805 -
806 - // Which arrows to show
807 - if(in_array(@$el['atts']['controls'], ['arrows', 'none'])){
808 - $el['attr'][] = ['.pagelayer-image-slider-ul' => 'data-pager="false"'];
809 - }
810 -
811 - if(in_array(@$el['atts']['controls'], ['pager', 'none'])){
812 - $el['attr'][] = ['.pagelayer-image-slider-ul' => 'data-controls="false"'];
813 - }
814 - }
815 -
816 -};
817 -
818 -//Grid Gallery Handler
819 -function pagelayer_sc_grid_gallery(&$el){
820 -
821 - $ids = explode(',', $el['atts']['ids']);
822 - $urls = [];
823 - $all_urls = [];
824 - $final_urls = [];
825 - $ul = [];
826 - $size = $el['atts']['size'];
827 - $i = 0;
828 - $col = $el['atts']['columns'];
829 - $gallery_rand = 'gallery-id-'.floor((rand() * 100) + 1);
830 -
831 - $ul[] = '<ul class="pagelayer-grid-gallery-ul">';
832 - // Make the image URL
833 - foreach($ids as $k => $v){
834 -
835 - $image = pagelayer_image($v);
836 -
837 - $final_urls[$v] = empty($image[$size.'-url']) ? @$image['full-url'] : $image[$size.'-url'];
838 -
839 - $urls['i'.$v] = @$image['full-url'];
840 - $links['i'.$v] = @$image['link'];
841 - $titles['i'.$v] = @$image['title'];
842 - $captions['i'.$v] = @$image['caption'];
843 -
844 - foreach($image as $kk => $vv){
845 - $si = strstr($kk, '-url', true);
846 - if(!empty($si)){
847 - $all_urls['i'.$v][$si] = $vv;
848 - }
849 - }
850 -
851 - /* if(($i % $col) == 0 && $i != 0 ){
852 - $ul[] = '</ul><ul class="pagelayer-grid-gallery-ul">';
853 - } */
854 -
855 - $li = '<li class="pagelayer-gallery-item" >';
856 -
857 - if(empty($el['atts']['link_to'])){
858 - $li .= '<div>';
859 - }
860 -
861 - // Any Link ?
862 - if(!empty($el['atts']['link_to']) && $el['atts']['link_to'] == 'media_file'){
863 - $link = ($el['atts']['link_to'] == 'media_file' ? $final_urls[$v] : @$el['atts']['link']);
864 - $li .= '<a href="'.$link.'" class="pagelayer-ele-link">';
865 - }
866 -
867 - // Any Link ?
868 - if(!empty($el['atts']['link_to']) && $el['atts']['link_to'] == 'attachment' ){
869 - $link = $image['link'];
870 - $li .= '<a href="'.$link.'" class="pagelayer-ele-link">';
871 - }
872 -
873 - if(!empty($el['atts']['link_to']) && $el['atts']['link_to'] == 'lightbox'){
874 - $li .= '<a href="'.$image['full-url'].'" data-lightbox-gallery="'.$gallery_rand.'" alt="'.$image['alt'].'" class="pagelayer-ele-link" pagelayer-grid-gallery-type="'.$el['atts']['link_to'].'">';
875 - }
876 - // The Image
877 - $li .= '<img class="pagelayer-img" src="'.$final_urls[$v].'" title="'.$image['title'].'" alt="'.$image['alt'].'">';
878 -
879 - if(!empty($el['atts']['caption'])){
880 - $li .= '<span class="pagelayer-grid-gallery-caption">'.$image['caption'].'</span>';
881 - }
882 -
883 - if(!empty($el['atts']['link_to'])){
884 - $li .= '</a>';
885 - }
886 -
887 - if(empty($el['atts']['link_to'])){
888 - $li .= '</div>';
889 - }
890 -
891 - $li .= '</li>';
892 -
893 - $ul[] = $li;
894 - $i++;
895 - }
896 -
897 - $ul[] = '</ul>';
898 -
899 - //pagelayer_print($urls);
900 - //pagelayer_print($final_urls);
901 - //pagelayer_print($all_urls);
902 -
903 - // Make the TMP vars
904 - if(!empty($urls)){
905 - $el['tmp']['ids-urls'] = json_encode($urls);
906 - $el['tmp']['ids-all-urls'] = json_encode($all_urls);
907 - $el['tmp']['ids-all-links'] = json_encode($links);
908 - $el['tmp']['ids-all-titles'] = json_encode($titles);
909 - $el['tmp']['ids-all-captions'] = json_encode($captions);
910 - $el['atts']['ul'] = implode('', $ul);
911 - $el['tmp']['gallery-random-id'] = $gallery_rand;
912 -
913 - }
914 -}
915 -
916 -// Testimonial Handler
917 -function pagelayer_sc_testimonial(&$el){
918 -
919 - $el['atts']['func_image'] = @$el['tmp']['avatar-'.$el['atts']['custom_size'].'-url'];
920 - $el['atts']['func_image'] = empty($el['atts']['func_image']) ? @$el['tmp']['avatar-full-url'] : $el['atts']['func_image'];
921 -
922 - if(!empty($image)){
923 - foreach($image as $k => $v){
924 - $el['tmp']['avatar-'.$k] = $v;
925 - }
926 - }
927 -
928 -}
929 -
930 -// Video Handler
931 -function pagelayer_sc_video(&$el){
932 -
933 - $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'];
934 - $el['atts']['video_overlay_image-url'] = empty($el['atts']['video_overlay_image-url']) ? $el['atts']['video_overlay_image'] : $el['atts']['video_overlay_image-url'];
935 -
936 - // Get the video URL for the iframe
937 - $el['atts']['vid_src'] = pagelayer_video_url($el['tmp']['src-url']);
938 -
939 - if($el['atts']['autoplay'] == "true"){
940 - $el['atts']['vid_src'] .="?&autoplay=1";
941 - }else{
942 - $el['atts']['vid_src'] .="?&autoplay=0";
943 - }
944 -
945 - if($el['atts']['mute'] == "true"){
946 - $el['atts']['vid_src'] .="&mute=1";
947 - }else{
948 - $el['atts']['vid_src'] .="&mute=0";
949 - }
950 -
951 - if($el['atts']['loop'] == "true"){
952 - $el['atts']['vid_src'] .="&loop=1";
953 - }else{
954 - $el['atts']['vid_src'] .="&loop=0";
955 - }
956 -
957 - $el['tmp']['ele_id'] = $el['id'];
958 -
959 -}
960 -
961 -
962 -// Shortcodes Handler
963 -function pagelayer_sc_shortcodes(&$el){
964 - $el['tmp']['shortcode'] = do_shortcode($el['atts']['data']);
965 -}
966 -
967 -// Shortcodes Handler
968 -function pagelayer_sc_wp_widgets(&$el){
969 -
970 - global $wp_registered_sidebars;
971 -
972 - $data = '';
973 - foreach($wp_registered_sidebars as $v){
974 - if($el['atts']['sidebar'] == $v['id']){
975 - ob_start();
976 - dynamic_sidebar($v['id']);
977 - $data = ob_get_clean();
978 - }
979 - }
980 -
981 - $el['tmp']['data'] = $data;
982 -}
983 -
984 -
985 -// Service Handler
986 -function pagelayer_sc_service(&$el){
987 -
988 - if(!empty($el['atts']['service_image'])){
989 - $el['atts']['func_image'] = @$el['tmp']['service_image-'.$el['atts']['service_image_size'].'-url'];
990 - $el['atts']['func_image'] = empty($el['atts']['func_image']) ? @$el['tmp']['service_image-full-url'] : $el['atts']['func_image'];
991 - }
992 -}
993 -
994 -
995 -/*pagelayer_print($atts);
996 -pagelayer_print($content);
997 -die();*/
998 -
999 -/////////////////////////////////////
1000 -// Miscellaneous Shortcode Functions
1001 -/////////////////////////////////////
1002 -
1003 -// The font family list
1004 -function pagelayer_font_family(){
1005 - return array(
1006 - 'arial' => 'Arial',
1007 - 'terminal' => 'Terminal'
1008 - );
1009 -}
1010 -
1011 -// Supported Icons
1012 -function pagelayer_icon_class_list(){
1013 - return array();
1014 -}
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 +}