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

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

4,095 lines 101.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 //////////////////////////////////////////////////////////////
4 //===========================================================
5 // class.php
6 //===========================================================
7 // PAGELAYER
8 // Inspired by the DESIRE to be the BEST OF ALL
9 // ----------------------------------------------------------
10 // Started by: Pulkit Gupta
11 // Date: 23rd Jan 2017
12 // Time: 23:00 hrs
13 // Site: http://pagelayer.com/wordpress (PAGELAYER)
14 // ----------------------------------------------------------
15 // Please Read the Terms of use at http://pagelayer.com/tos
16 // ----------------------------------------------------------
17 //===========================================================
18 // (c)Pagelayer Team
19 //===========================================================
20 //////////////////////////////////////////////////////////////
21
22 // Are we being accessed directly ?
23 if(!defined('PAGELAYER_VERSION')) {
24 exit('Hacking Attempt !');
25 }
26
27 // Get the client IP
28 function _pagelayer_getip(){
29 if(isset($_SERVER["REMOTE_ADDR"])){
30 return $_SERVER["REMOTE_ADDR"];
31 }elseif(isset($_SERVER["HTTP_X_FORWARDED_FOR"])){
32 return $_SERVER["HTTP_X_FORWARDED_FOR"];
33 }elseif(isset($_SERVER["HTTP_CLIENT_IP"])){
34 return $_SERVER["HTTP_CLIENT_IP"];
35 }
36 }
37
38 // Get the client IP
39 function pagelayer_getip(){
40
41 global $pagelayer;
42
43 // Just so that we have something
44 $ip = _pagelayer_getip();
45 $method = @$pagelayer->ip_method;
46
47 $pagelayer->ip_method = (int) $method;
48
49 if(isset($_SERVER["REMOTE_ADDR"])){
50 $ip = $_SERVER["REMOTE_ADDR"];
51 }
52
53 if(isset($_SERVER["HTTP_X_FORWARDED_FOR"]) && $method == 1){
54 $ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
55 }
56
57 if(isset($_SERVER["HTTP_CLIENT_IP"]) && $method == 2){
58 $ip = $_SERVER["HTTP_CLIENT_IP"];
59 }
60
61 // Hacking fix for X-Forwarded-For
62 if(!pagelayer_valid_ip($ip)){
63 return '';
64 }
65
66 return $ip;
67
68 }
69
70 // Execute a select query and return an array
71 function pagelayer_selectquery($query, $array = 0){
72 global $wpdb;
73
74 $result = $wpdb->get_results($query, 'ARRAY_A');
75
76 if(empty($array)){
77 return current($result);
78 }else{
79 return $result;
80 }
81 }
82
83 // Check if an IP is valid
84 function pagelayer_valid_ip($ip){
85
86 // IPv6
87 if(pagelayer_valid_ipv6($ip)){
88 return true;
89 }
90
91 // IPv4
92 if(!ip2long($ip)){
93 return false;
94 }
95
96 return true;
97 }
98
99 function pagelayer_valid_ipv6($ip){
100
101 $pattern = '/^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))$/';
102
103 if(!preg_match($pattern, $ip)){
104 return false;
105 }
106
107 return true;
108
109 }
110
111 // Check if a field is posted via POST else return default value
112 function pagelayer_optpost($name, $default = ''){
113
114 if(!empty($_POST[$name])){
115 return pagelayer_inputsec(pagelayer_htmlizer(trim($_POST[$name])));
116 }
117
118 return $default;
119 }
120
121 // Check if a field is posted via GET else return default value
122 function pagelayer_optget($name, $default = ''){
123
124 if(!empty($_GET[$name])){
125 return pagelayer_inputsec(pagelayer_htmlizer(trim($_GET[$name])));
126 }
127
128 return $default;
129 }
130
131 // Check if a field is posted via GET or POST else return default value
132 function pagelayer_optreq($name, $default = ''){
133
134 if(!empty($_REQUEST[$name])){
135 return pagelayer_inputsec(pagelayer_htmlizer(trim($_REQUEST[$name])));
136 }
137
138 return $default;
139 }
140
141 // For filling in posted values
142 function pagelayer_POSTval($name, $default = ''){
143
144 return (!empty($_POST) ? (!isset($_POST[$name]) ? '' : esc_html($_POST[$name])) : $default);
145
146 }
147
148 function pagelayer_POSTchecked($name, $default = false){
149
150 return (!empty($_POST) ? (isset($_POST[$name]) ? 'checked="checked"' : '') : (!empty($default) ? 'checked="checked"' : ''));
151
152 }
153
154 // For check isset value
155 function pagelayer_isset($var, $name, $default = ''){
156
157 return isset($var[$name]) ? $var[$name] : $default;
158
159 }
160
161 function pagelayer_POSTselect($name, $value, $default = false){
162
163 if(empty($_POST)){
164 if(!empty($default)){
165 return 'selected="selected"';
166 }
167 }else{
168 if(isset($_POST[$name])){
169 if(trim($_POST[$name]) == $value){
170 return 'selected="selected"';
171 }
172 }
173 }
174
175 }
176
177 function pagelayer_inputsec($string){
178
179 $string = addslashes($string);
180
181 // This is to replace ` which can cause the command to be executed in exec()
182 $string = str_replace('`', '\`', $string);
183
184 return $string;
185
186 }
187
188 function pagelayer_htmlizer($string){
189
190 $string = htmlentities($string, ENT_QUOTES, 'UTF-8');
191
192 preg_match_all('/(&amp;#(\d{1,7}|x[0-9a-fA-F]{1,6});)/', $string, $matches);//r_print($matches);
193
194 foreach($matches[1] as $mk => $mv){
195 $tmp_m = pagelayer_entity_check($matches[2][$mk]);
196 $string = str_replace($matches[1][$mk], $tmp_m, $string);
197 }
198
199 return $string;
200
201 }
202
203 function pagelayer_entity_check($string){
204
205 //Convert Hexadecimal to Decimal
206 $num = ((substr($string, 0, 1) === 'x') ? hexdec(substr($string, 1)) : (int) $string);
207
208 //Squares and Spaces - return nothing
209 $string = (($num > 0x10FFFF || ($num >= 0xD800 && $num <= 0xDFFF) || $num < 0x20) ? '' : '&#'.$num.';');
210
211 return $string;
212
213 }
214
215 // Check if a checkbox is selected
216 function pagelayer_is_checked($post){
217
218 if(!empty($_POST[$post])){
219 return true;
220 }
221 return false;
222 }
223
224 // Report an error
225 function pagelayer_report_error($error = array()){
226
227 if(empty($error)){
228 return true;
229 }
230
231 $error_string = '<b>Please fix the below error(s) :</b> <br />';
232
233 foreach($error as $ek => $ev){
234 $error_string .= '* '.$ev.'<br />';
235 }
236
237 echo '<div id="message" class="error"><p>'
238 . __pl($error_string)
239 . '</p></div>';
240 }
241
242 // Report a notice
243 function pagelayer_report_notice($notice = array()){
244
245 global $wp_version;
246
247 if(empty($notice)){
248 return true;
249 }
250
251 // Which class do we have to use ?
252 if(version_compare($wp_version, '3.8', '<')){
253 $notice_class = 'updated';
254 }else{
255 $notice_class = 'updated';
256 }
257
258 $notice_string = '<b>Please check the below notice(s) :</b> <br />';
259
260 foreach($notice as $ek => $ev){
261 $notice_string .= '* '.$ev.'<br />';
262 }
263
264 echo '<div id="message" class="'.$notice_class.'"><p>'
265 . __pl($notice_string)
266 . '</p></div>';
267 }
268
269 // Convert an objext to array
270 function pagelayer_objectToArray($d){
271
272 if(is_object($d)){
273 $d = get_object_vars($d);
274 }
275
276 if(is_array($d)){
277 return array_map(__FUNCTION__, $d); // recursive
278 }elseif(is_object($d)){
279 return pagelayer_objectToArray($d);
280 }else{
281 return $d;
282 }
283 }
284
285 // Sanitize variables
286 function pagelayer_sanitize_variables($variables = array()){
287
288 if(is_array($variables)){
289 foreach($variables as $k => $v){
290 $variables[$k] = trim($v);
291 $variables[$k] = escapeshellcmd($v);
292 }
293 }else{
294 $variables = escapeshellcmd(trim($variables));
295 }
296
297 return $variables;
298 }
299
300 // Is multisite ?
301 function pagelayer_is_multisite() {
302
303 if(function_exists('get_site_option') && function_exists('is_multisite') && is_multisite()){
304 return true;
305 }
306
307 return false;
308 }
309
310 // Generate a random string
311 function pagelayer_RandomString($length = 10){
312 $characters = '0123456789abcdefghijklmnopqrstuvwxyz';
313 $charactersLength = strlen($characters);
314 $randomString = '';
315 for($i = 0; $i < $length; $i++){
316 $randomString .= $characters[rand(0, $charactersLength - 1)];
317 }
318 return $randomString;
319 }
320
321 function pagelayer_print($array){
322
323 echo '<pre>';
324 print_r($array);
325 echo '</pre>';
326
327 }
328
329 function pagelayer_cleanpath($path){
330 $path = str_replace('\\\\', '/', $path);
331 $path = str_replace('\\', '/', $path);
332 $path = str_replace('//', '/', $path);
333 return rtrim($path, '/');
334 }
335
336 // Returns the Numeric Value of results Per Page
337 function pagelayer_get_page($get = 'page', $resperpage = 50){
338
339 $resperpage = (!empty($_REQUEST['reslen']) && is_numeric($_REQUEST['reslen']) ? (int) pagelayer_optreq('reslen') : $resperpage);
340
341 if(pagelayer_optget($get)){
342 $pg = (int) pagelayer_optget($get);
343 $pg = $pg - 1;
344 $page = ($pg * $resperpage);
345 $page = ($page <= 0 ? 0 : $page);
346 }else{
347 $page = 0;
348 }
349 return $page;
350 }
351
352 // Are we editing from the Admin panel ?
353 function pagelayer_is_editing($force = false){
354
355 global $post, $pagelayer;
356
357 if(!empty($force)){
358 return true;
359 }
360
361 if(!is_admin()){
362 return false;
363 }
364
365 $current_file = basename($_SERVER['PHP_SELF']);
366
367 $type = get_post_type();
368 //echo $type;return false;
369 //$page = pagelayer_optreq('page');
370
371 // Are we in the live editor mode OR is this a post which is supported
372 if((pagelayer_supported_type($type) && in_array($current_file, array('post.php', 'post-new.php'))) || pagelayer_is_live()){
373 return true;
374 }else{
375 return false;
376 }
377
378 }
379
380 // Is the given post type editable by us ?
381 function pagelayer_supported_type($type){
382
383 global $pagelayer;
384
385 $type = trim($type);
386
387 if(in_array($type, $pagelayer->settings['post_types'])){
388 return true;
389 }
390
391 if($type == $pagelayer->builder['name']){
392 return true;
393 }
394
395 return false;
396
397 }
398
399 function pagelayer_shortlink($id){
400
401 $post = get_post( $id );
402 if ( ! empty( $post->ID ) ) {
403 $post_id = $post->ID;
404 }
405
406 $post_type = get_post_type_object( $post->post_type );
407
408 if ( 'page' === $post->post_type && get_option( 'page_on_front' ) == $post->ID && 'page' === get_option( 'show_on_front' ) ) {
409 $link = home_url( '/' );
410 } elseif ( $post_type->public ) {
411 $link = home_url( '?p=' . $post_id );
412 }
413
414 if(function_exists('is_post_status_viewable') && !is_post_status_viewable($post_id)){
415 $link = get_permalink( $post->ID );
416 }
417
418 $link .= substr_count($link, '?') > 0 ? '' : '?';
419 return $link;
420 }
421
422 // Pagelayer live link
423 function pagelayer_livelink($id){
424 return pagelayer_shortlink($id).'&pagelayer-live=1';
425 }
426
427 // Are we in live mode ?
428 function pagelayer_is_live(&$error = array()){
429
430 global $post;
431
432 // Are we seeing the post ?
433 if(!isset($post) || !isset($post->ID) || empty($post->ID)){
434 $error[] = 'Post ID is missing or blank - '.@$post->ID;
435 return false;
436 }
437
438 $parID = $post->ID;
439
440 // Is revision?
441 if(wp_is_post_revision($post->ID) ){
442 $parID = wp_get_post_parent_id($post->ID);
443 }
444
445 // Are you allowed to edit ?
446 if(!pagelayer_user_can_edit($parID)){
447 $error[] = 'You dont have editing rights for this page - '.$parID;
448 return false;
449 }
450
451 // Is it the live mode ?
452 if(pagelayer_optreq('pagelayer-live')){
453 $error[] = 'pagelayer-live is missing';
454 return true;
455 }
456
457 return false;
458
459 }
460
461 // Are we in live IFRAME mode ?
462 function pagelayer_is_live_iframe(&$error = array()){
463
464 // Are we seeing the post ?
465 if(!pagelayer_is_live($error)){
466 return false;
467 }
468
469 // Is it the live mode ?
470 if(pagelayer_optreq('pagelayer-iframe')){
471 return true;
472 }
473
474 $error[] = 'pagelayer-iframe missing in GET';
475
476 return false;
477
478 }
479
480 // Are we editing a live template
481 function pagelayer_is_live_template($post = []){
482
483 // Are we seeing the post ?
484 if(!pagelayer_is_live()){
485 return false;
486 }
487
488 if(!$post){
489 $post = $GLOBALS['post'];
490 }
491
492 if($post->post_type == 'pagelayer-template'){
493 return true;
494 }
495
496 return false;
497
498 }
499
500 function pagelayer_has_blocks($post = null) {
501 if ( ! has_blocks( $post ) ) {
502 return false;
503 }
504
505 if ( ! is_string( $post ) ) {
506 $wp_post = get_post( $post );
507 if ( $wp_post instanceof WP_Post ) {
508 $post = $wp_post->post_content;
509 }
510 }
511
512 return false !== strpos( $post, '<!-- wp:pagelayer/' );
513 }
514
515 // Can the current user edit the post ?
516 function pagelayer_user_can_edit($post = NULL){
517
518 global $wp_the_query, $current_user, $pagelayer;
519
520 $post = get_post($post);
521
522 if(empty($post)){
523 return false;
524 }
525
526 // No trash editing
527 if(get_post_status($post->ID) === 'trash'){
528 return false;
529 }
530
531 // Is pagelayer supposed to edit this ?
532 if(!pagelayer_supported_type($post->post_type)){
533 return false;
534 }
535
536 // Get the post type object
537 $object = get_post_type_object($post->post_type);
538
539 // Is this type editable by the user ?
540 if(!current_user_can($object->cap->edit_posts)){
541 return false;
542 }
543
544 // Is this type editable ?
545 if(!isset($object->cap->edit_post)){
546 return false;
547 }
548
549 // Can this user edit the post type ?
550 if(!current_user_can($object->cap->edit_post, $post->ID)){
551 return false;
552 }
553
554 // Page for blogs not allowed
555 if(get_option('page_for_posts') === $post->ID){
556 return false;
557 }
558
559 return true;
560
561 }
562
563 // Language sting function
564 function __pl($key){
565
566 global $pagelayer;
567
568 if(!empty($pagelayer->l[$key])){
569 return $pagelayer->l[$key];
570 }
571
572 return $key;
573
574 }
575
576 // Give the list of icon sources
577 function pagelayer_icon_sources(){
578 return array();
579 }
580
581 // Sets the memory limit
582 function pagelayer_memory_limit($mb){
583
584 $bytes = ($mb * 1024 * 1024);
585 $mb_str = (string) $mb.'M';
586
587 // Some servers might have ini_get disabled
588 if(function_exists('ini_get')){
589 $memory_limit = @ini_get('memory_limit');
590 }
591
592 if(empty($memory_limit)){
593 return;
594 }
595
596 $memory_limit_bytes = (strpos($memory_limit, 'M') ? (intval($memory_limit) * 1024 * 1024) : intval($memory_limit));
597
598 //$memory_limit_bytes > 0 is for memory limit = -1
599 if($memory_limit_bytes <= $bytes && $memory_limit_bytes > 0){
600
601 // Some servers might have ini_set disabled
602 if(function_exists('ini_set')){
603 @ini_set('memory_limit', $mb_str);
604 }
605 }
606
607 }
608
609 // Pagelayer the content
610 function pagelayer_the_content($content, $dump = false){
611 global $pagelayer;
612
613 $content = pagelayer_sanitize_content( $content );
614 $content = do_blocks( $content );
615 $content = do_shortcode( $content );
616
617 if($dump){
618 preg_match_all('/<div ([^>]*)pagelayer-id="([^"]*)"([^>]*)>/', $content, $matches);
619
620 foreach($matches[0] as $k => $div){
621 $id = $matches[2][$k];
622
623 if(empty($pagelayer->data_attr[$id])){
624 continue;
625 }
626
627 $data_attr = '<!-- '.pagelayer_serialize_attributes($pagelayer->data_attr[$id]).' -->';
628 $content = str_replace($div, $div.$data_attr, $content);
629 }
630 }
631
632 return $content;
633 }
634
635 function pagelayer_create_id(){
636 return pagelayer_RandomString(3).rand(1000, 9999);
637 }
638
639 // Loads the shortcodes
640 function pagelayer_load_shortcodes(){
641 global $pagelayer, $post;
642
643 if(!empty($pagelayer->shortcode_loaded)){
644 return;
645 }
646
647 pagelayer_memory_limit(128);
648
649 // We have loaded
650 $pagelayer->shortcode_loaded = 1;
651
652 do_action('pagelayer_before_load_shortcodes');
653
654 // pQuery
655 include_once(PAGELAYER_DIR.'/lib/pquery/IQuery.php');
656 include_once(PAGELAYER_DIR.'/lib/pquery/gan_formatter.php');
657 include_once(PAGELAYER_DIR.'/lib/pquery/gan_node_html.php');
658 include_once(PAGELAYER_DIR.'/lib/pquery/gan_tokenizer.php');
659 include_once(PAGELAYER_DIR.'/lib/pquery/gan_parser_html.php');
660 include_once(PAGELAYER_DIR.'/lib/pquery/gan_selector_html.php');
661 include_once(PAGELAYER_DIR.'/lib/pquery/gan_xml2array.php');
662 include_once(PAGELAYER_DIR.'/lib/pquery/pQuery.php');
663
664 include_once(PAGELAYER_DIR.'/main/shortcode_functions.php');
665
666 // Apply filter to load custom widgets functions
667 do_action('pagelayer_load_shortcode_functions');
668
669 include_once(PAGELAYER_DIR.'/main/shortcodes.php');
670
671 // Apply filter to load custom widgets
672 do_action('pagelayer_load_custom_widgets');
673
674 // Render Pagelayer element by blocks
675 add_action('pre_render_block', 'pagelayer_render_blocks', 10, 2);
676
677 // Add global widget data
678 if(defined('PAGELAYER_PREMIUM') && !pagelayer_is_gutenberg_editor()){
679
680 // Get global widget templates id by type
681 $args = [
682 'post_type' => $pagelayer->builder['name'],
683 'status' => 'publish',
684 'meta_key' => 'pagelayer_template_type',
685 'meta_value' => array('global_widget', 'section', 'global_section'),
686 'posts_per_page' => -1
687 ];
688
689 $query = new WP_Query($args);
690
691 $tmp_list = [];
692 $global_widgets = array();
693 $global_widgets['global_widget'] = array();
694 $global_widgets['section'] = array();
695 $global_widgets['global_section'] = array();
696
697 foreach($query->posts as $template){
698
699 // The type
700 $pagelayer_template_type = get_post_meta($template->ID, 'pagelayer_template_type', true);
701
702 $global_data = [];
703 $global_data['post_id'] = $template->ID;
704 $global_data['title'] = $template->post_title;
705 $global_data['$'] = pagelayer_the_content($template->post_content, true);
706 $global_widgets[$pagelayer_template_type][$template->ID] = $global_data;
707
708 }
709
710 $pagelayer->global_widgets = $global_widgets['global_widget'];
711 $pagelayer->saved_sections = $global_widgets['section'];
712 $pagelayer->global_sections = $global_widgets['global_section'];
713 }
714
715 do_action('pagelayer_after_load_shortcodes');
716 }
717
718 // Add the shortcodes to the pagelayer list
719 function pagelayer_add_shortcode($tag, $params = array()){
720
721 global $pagelayer, $post;
722
723 if($tag == 'pl_row'){
724 $inner_tag = 'pl_inner_row';
725 add_shortcode($inner_tag, 'pagelayer_render_shortcode');
726 }
727
728 if($tag == 'pl_col'){
729 $inner_tag = 'pl_inner_col';
730 add_shortcode($inner_tag, 'pagelayer_render_shortcode');
731 }
732
733 add_shortcode($tag, 'pagelayer_render_shortcode');//$params['func']);
734 //unset($params['func']);
735
736 // Is there a group ?
737 if(empty($params['group'])){
738 $params['group'] = 'misc';
739 }
740
741 // Add the advanced styling group
742 $params['options'] = [
743 'ele_bg_styles' => __pl('ele_bg_styles'),
744 'ele_styles' => __pl('ele_styles'),
745 'border_styles' => __pl('border_styles'),
746 'font_style' => __pl('font_style'),
747 'position_styles' => __pl('position_styles'),
748 'animation_styles' => __pl('animation_styles'),
749 'motion_effects' => __pl('Motion Effects'),
750 'responsive_styles' => __pl('responsive_styles'),
751 'attributes' => __pl('attributes'),
752 'custom_styles' => __pl('custom_styles'),
753 ];
754
755 if(!empty($params['skip_props_cat'])){
756 foreach($params['skip_props_cat'] as $k => $v){
757 unset($params['options'][$v]);
758 }
759 }
760
761 // Are the settings there which hold the params ?
762 if(empty($params['settings'])){
763 $params['settings'] = [
764 'params' => $params['name'],
765 ];
766 }
767
768 // Disable the style options
769 if(!empty($params['styles'])){
770 $params['settings'] = array_merge($params['settings'], $params['styles']);
771 unset($params['styles']);
772 }
773
774 /*// The following is for testing only
775 $r = [];
776 foreach($pagelayer->styles as $k => $v){
777 foreach($v as $kk => $vv){
778 $r[$kk] = $kk;
779 }
780 }
781 //print_r($r);die();
782
783 foreach($params['settings'] as $k => $v){
784 if(empty($params[$k])) continue;
785 foreach($params[$k] as $kk => $vv){
786 if(!empty($r[$kk])){
787 echo 'Duplicate KEY '.$kk.' in Shortcode '.$tag."<br>";
788 }
789 }
790 }
791 //die();*/
792
793 $params = apply_filters( 'pagelayer_shortcode_params', $params, $tag );
794
795 // Insert the shortcode
796 $pagelayer->shortcodes[$tag] = $params;
797 $pagelayer->groups[$params['group']][] = $tag;
798
799 // Export the default values
800 foreach($pagelayer->tabs as $tab){
801
802 if(empty($pagelayer->shortcodes[$tag][$tab])){
803 continue;
804 }
805
806 foreach($pagelayer->shortcodes[$tag][$tab] as $section => $Lsection){
807
808 $props = empty($pagelayer->shortcodes[$tag][$section]) ? @$pagelayer->styles[$section] : @$pagelayer->shortcodes[$tag][$section];
809
810 //echo $tab.' - '.$section.' - <br>';
811
812 if(empty($props)){
813 continue;
814 }
815
816 // Save customizer params
817 if( $tag == 'pl_customizer' ){
818 $pagelayer->customizer_params = array_merge($pagelayer->customizer_params, $props);
819 }
820
821 foreach($props as $prop => $param){
822
823 // Set default values to export for JS
824 if(isset($param['export-def']) && isset($param['default']) && $param['export-def'] == 1){
825 $pagelayer->default_params[$tag][$prop] = $param['default'];
826 }
827
828 }
829 }
830 }
831 }
832
833 // Add a freemium shortcode i.e. available for render, but not to drag or edit
834 function pagelayer_freemium_shortcode($tag, $params = array()){
835
836 // If we are the free version, we just allow render and some edits
837 if(!defined('PAGELAYER_PREMIUM')){
838
839 $params['not_visible'] = 1;
840 $params['freemium'] = 1;
841
842 $cats = empty($params['styles']) ? array() : $params['styles'];
843
844 if(!empty($params['settings'])){
845 $cats = array_merge($cats, $params['settings']);
846 }
847
848 $cats['params'] = $params['name'];
849 //pagelayer_print($cats);
850
851 foreach($cats as $k => $v){
852 if(empty($params[$k])) continue;
853
854 foreach($params[$k] as $kk => $vv){
855
856 if(empty($params[$k][$kk]['np'])){
857 $params[$k][$kk]['pro'] = 1;
858 }
859
860 }
861
862 }
863
864 }
865
866 return pagelayer_add_shortcode($tag, $params);
867 }
868
869 // Returns the permalink values
870 function pagelayer_permalink($id){
871
872 if(is_numeric($id)){
873 $id = (int) @$id;
874 $perma = get_permalink($id);
875
876 if(!empty($perma)){
877 $id = $perma;
878 }
879 }
880
881 $id = apply_filters('pagelayer_permalink', $id);
882
883 return $id;
884 }
885
886 // Returns the Image values
887 function pagelayer_image($id = 0){
888
889 global $pagelayer;
890
891 $ret = [];
892
893 if(!empty($id) && is_array($id)){
894
895 foreach($id as $key => $image){
896 $attachment = pagelayer_image(@$image);
897 if(!empty($attachment)){
898 foreach($attachment as $k => $v){
899 if($key == 'retina'){
900 $ret['retina-'.$k] = $v;
901 }else if($key == 'retina_mobile'){
902 $ret['retina-mobile-'.$k] = $v;
903 }else{
904 $ret[$k] = $v;
905 }
906 }
907 }
908 }
909
910 return $ret;
911 }
912
913 // External image ?
914 if(pagelayer_is_external_img($id)){
915
916 $ret['url'] = $id;
917
918 // Attachment
919 }elseif(!empty($id)){
920
921 $id = (int) @$id;
922
923 $image = get_post($id);
924
925 // Is there an attachment which is an image ?
926 if(!empty($image) && $image->post_type == 'attachment' && wp_attachment_is_image($id)){
927
928 // Need to export necessary media
929 if(!empty($pagelayer->export_mode)){
930 $pagelayer->media_to_export[] = $id;
931 }
932
933 $sizes = get_intermediate_image_sizes();
934 array_unshift($sizes, 'full');
935
936 foreach($sizes as $size){
937 $src = wp_get_attachment_image_src($id, $size);
938 $ret[$size.'-url'] = $src[0];
939 }
940
941 // Title and Alt
942 $title = esc_attr($image->post_title);
943 $alt = get_post_meta($id, '_wp_attachment_image_alt', true);
944 $alt = empty($alt) ? $image->post_excerpt : $alt;
945 $alt = empty($alt) ? $image->post_title : $alt;
946 $alt = empty($alt) ? '' : esc_attr(trim(strip_tags($alt)));
947 $link = get_attachment_link($id);
948 $caption = wp_get_attachment_caption($id);
949 $caption = !empty($caption) ? esc_attr($caption) : '';
950
951 }
952
953 }
954
955 // First preference to full url
956 if(!empty($ret['full-url'])){
957 $ret['url'] = $ret['full-url'];
958 }
959
960 // No image
961 if(empty($ret['url'])){
962 $ret['url'] = PAGELAYER_URL.'/images/default-image.png';
963 }
964
965 // Extract filename without extension
966 $filename = pathinfo($ret['url'], PATHINFO_FILENAME);
967
968 // Skip title if same as filename
969 $title = (!empty($title) && $title != $filename) ? $title : '';
970
971 $ret['alt'] = @$alt;
972 $ret['title'] = @$title;
973 $ret['link'] = @$link;
974 $ret['caption'] = @$caption;
975
976 $ret = apply_filters('pagelayer_image', $ret);
977
978 if(pagelayer_is_default_img($ret['url'])){
979 $ret['no-image-set'] = 1;
980 }
981
982 return $ret;
983
984 }
985
986 // Checks if the given parameter is an external link or a wp attachment id
987 function pagelayer_is_external_img($img = ''){
988
989 if(empty($img)){
990 return false;
991 }
992
993 if(preg_match('#http://#is', $img) || preg_match('#https://#is', $img) || preg_match('#^{{#is', $img)){
994 return true;
995 }
996
997 return false;
998
999 }
1000
1001 // Checks if the given parameter is the default image
1002 function pagelayer_is_default_img($img){
1003
1004 if($img == PAGELAYER_URL.'/images/default-image.png'){
1005 return true;
1006 }
1007
1008 return false;
1009
1010 }
1011
1012 // Returns the attachment url
1013 function pagelayer_attachment($id){
1014
1015 $ret = [];
1016
1017 // External url ?
1018 if(pagelayer_is_external_img($id)){
1019
1020 $ret['url'] = $id;
1021
1022 // Attachment
1023 }elseif(!empty($id)){
1024
1025 // Need to export necessary media
1026 if(!empty($pagelayer->export_mode)){
1027 $pagelayer->media_to_export[] = $id;
1028 }
1029
1030 $ret['url'] = wp_get_attachment_url($id);
1031
1032 }
1033
1034 $ret = apply_filters('pagelayer_attachment', $ret);
1035
1036 return $ret;
1037
1038 }
1039
1040 // Convert the regular URL of a Video to a Embed URL
1041 // Todo : Check
1042 function pagelayer_video_url($source, $no_url = false){
1043
1044 global $pagelayer;
1045
1046 if (!empty($source)) {
1047
1048 $source = esc_url( $source );
1049 $source = str_replace('&amp;', '&', $source);
1050 $url = parse_url($source);
1051 $videoSite ='';
1052 $videoId ='';
1053 $vid_atts = [];
1054
1055 $youtubeRegExp = '/youtube\.com|youtu\.be/is';
1056 $vimeoRegExp = '/vimeo\.com/is';
1057
1058 if (preg_match($youtubeRegExp, $source)) {
1059 $videoSite = 'youtube';
1060 } else if (preg_match($vimeoRegExp, $source)) {
1061 $videoSite = 'vimeo';
1062 }
1063
1064 switch ($videoSite) {
1065 case 'youtube':
1066
1067 $pagelayer->append_yt_api = true;
1068
1069 if (preg_match('/youtube\.com/is', $source)) {
1070
1071 if (preg_match('/watch/is', $source)) {
1072 parse_str($url['query'], $parameters);
1073
1074 if (isset($parameters['v']) && !empty($parameters['v'])) {
1075 $videoId = $parameters['v'];
1076 }
1077
1078 } else if (preg_match('/embed/is', $url['path'])) {
1079 $path = explode('/', $url['path']);
1080 if (isset($path[2]) && !empty($path[2])) {
1081 $videoId = $path[2];
1082 }
1083 }
1084
1085 } else if (preg_match('/youtu\.be/is', $url['host'])) {
1086 $path = explode('/', $url['path']);
1087
1088 if (isset($path[1]) && !empty($path[1])) {
1089 $videoId = $path[1];
1090 }
1091
1092 }
1093
1094 $vid_atts['type'] = 'youtube';
1095 $vid_atts['src'] = '//www.youtube.com/embed/'.$videoId;
1096 $vid_atts['id'] = $videoId;
1097
1098 break;
1099 case 'vimeo':
1100
1101 if (preg_match('/player\.vimeo\.com/is', $url['host']) && preg_match('/video/is', $url['path'])) {
1102 $path = explode('video/', $source);
1103 } else if (preg_match('/vimeo\.com/is', $url['host'])) {
1104 $path = explode('.com/', $source);
1105 }
1106
1107 if(isset($path[1]) && !empty($path[1])) {
1108 $videoId = $path[1];
1109 }
1110
1111 $vid_atts['type'] = 'vimeo';
1112 $vid_atts['src'] = '//player.vimeo.com/video/'.$videoId;
1113 $vid_atts['id'] = $videoId;
1114
1115 break;
1116 default:
1117
1118 $vid_atts['type'] = 'local';
1119 $vid_atts['src'] = $source;
1120 $vid_atts['id'] = $videoId;
1121
1122 }
1123
1124 if(!$no_url){
1125 return $vid_atts['src'];
1126 }
1127
1128 return $vid_atts;
1129
1130 }
1131 }
1132
1133
1134 // As per the JS specification
1135 function pagelayer_escapeHTML($str){
1136
1137 if(is_null($str)){
1138 return '';
1139 }
1140
1141 $replace = [
1142 ']' => '&#93;',
1143 '[' => '&#91;',
1144 //'=' => '&#61;',
1145 '<' => '&lt;',
1146 '>' => '&gt;',
1147 '"' => '&quot;',
1148 //'&' => '&amp;',
1149 '\'' => '&#39;',
1150 '\\' => '&#92;'
1151 ];
1152
1153 $str = str_replace(array_keys($replace), array_values($replace), $str);
1154
1155 return $str;
1156 }
1157
1158 // As per the JS specification
1159 function pagelayer_unescapeHTML($str){
1160
1161 if(is_null($str)){
1162 return '';
1163 }
1164
1165 $replace = [
1166 '#93' => ']',
1167 '#91' => '[',
1168 //'#61' => '=',
1169 'lt' => '<',
1170 'gt' => '>',
1171 'quot' => '"',
1172 //'amp' => '&',
1173 '#39' => '\'',
1174 '#92' => '\\'
1175 ];
1176
1177 foreach($replace as $k => $v){
1178 $str = str_replace('&'.$k.';', $v, $str);
1179 }
1180 return $str;
1181 }
1182
1183 // Converts a Unicode code point to its UTF-8 encoded string.
1184 function pagelayer_codepoint_to_utf8($num) {
1185 if ($num < 0x80) {
1186 return chr($num);
1187 } elseif ($num < 0x800) {
1188 return chr(0xC0 | ($num >> 6))
1189 . chr(0x80 | ($num & 0x3F));
1190 } elseif ($num < 0x10000) {
1191 return chr(0xE0 | ($num >> 12))
1192 . chr(0x80 | (($num >> 6) & 0x3F))
1193 . chr(0x80 | ($num & 0x3F));
1194 } elseif ($num < 0x110000) {
1195 return chr(0xF0 | ($num >> 18))
1196 . chr(0x80 | (($num >> 12) & 0x3F))
1197 . chr(0x80 | (($num >> 6) & 0x3F))
1198 . chr(0x80 | ($num & 0x3F));
1199 }
1200 return '';
1201 }
1202
1203 // To make decode entities faster
1204 function pagelayer_optimized_decode_entities($string, $req = true) {
1205
1206 // Fast replace common HTML entities
1207 $common_entities_map = [
1208 '&#93;' => ']', '&#91;' => '[', '&lt;' => '<', '&gt;' => '>', '&amp;' => '&', '&quot;' => '"', '&#39;' => "'",
1209 '&copy;' => '©', '&reg;' => '®', '&ndash;' => '', '&mdash;' => '', '&bull;' => '',
1210 '&hellip;' => '', '&lsquo;' => '', '&rsquo;' => '', '&ldquo;' => '', '&rdquo;' => ''
1211 ];
1212
1213 // Replace common entities first for performance
1214 $string = str_replace(array_keys($common_entities_map), array_values($common_entities_map), $string);
1215
1216 // Return early if no encoded entities exist
1217 if(!preg_match('/\\\\u[0-9a-fA-F]{4}|&#x[0-9a-fA-F]+;|&#\d+;/', $string)) {
1218 return $string;
1219 }
1220
1221 $string = preg_replace_callback(
1222 '/\\\\u([0-9a-fA-F]{4})|&#x([0-9a-fA-F]+);|&#([0-9]+);/',
1223 function ($matches) {
1224 if (!empty($matches[1])) {
1225 // Decode \uXXXX Unicode sequences
1226 return pagelayer_codepoint_to_utf8( hexdec($matches[1]) );
1227 }elseif (!empty($matches[2])) {
1228 // Decode hexadecimal HTML entities (&#x6A; → j)
1229 return pagelayer_codepoint_to_utf8( hexdec($matches[2]) );
1230 } elseif (!empty($matches[3])) {
1231 // Decode decimal HTML entities (&#106; → j)
1232 return pagelayer_codepoint_to_utf8( (int)$matches[3] );
1233 }
1234 return $matches[0];
1235 },
1236 $string
1237 );
1238
1239 // Additional decoding to cover remaining cases
1240 if($req){
1241 $string = pagelayer_optimized_decode_entities($string, false);
1242 }
1243
1244 return $string;
1245 }
1246
1247 // Return true if user can add js content
1248 function pagelayer_user_can_add_js_content(){
1249
1250 // Unfiltered_html cap needs to be checked for multisite
1251 if(current_user_can('unfiltered_html')){
1252 return true;
1253 }
1254
1255 $pagelayer_js_permission = get_option('pagelayer_js_permission');
1256 $current_user = wp_get_current_user();
1257
1258 // If not allowed any role by admin
1259 if(empty($pagelayer_js_permission) || empty($current_user->roles)){
1260 return false;
1261 }
1262
1263 foreach($current_user->roles as $role){
1264 if(in_array($role, $pagelayer_js_permission)){
1265 return true;
1266 }
1267 }
1268
1269 return false;
1270 }
1271
1272 // Check for XSS codes in our shortcodes submitted
1273 function pagelayer_xss_content($data){
1274
1275 $data = pagelayer_optimized_decode_entities($data);
1276
1277 // Collapse all whitespace for pattern matching
1278 $data = preg_split('/\s/', $data);
1279 $data = implode('', $data);
1280 //echo $data;
1281
1282 if(preg_match('/["\']javascript\:/is', $data)){
1283 return 'javascript';
1284 }
1285
1286 if(preg_match('/["\']vbscript\:/is', $data)){
1287 return 'vbscript';
1288 }
1289
1290 if(preg_match('/\-moz\-binding\:/is', $data)){
1291 return '-moz-binding';
1292 }
1293
1294 if(preg_match('/expression\(/is', $data)){
1295 return 'expression';
1296 }
1297
1298 if(preg_match('/\<(iframe|frame|script|style|link|applet|embed|xml|svg|object|layer|ilayer|meta)/is', $data, $matches)){
1299 return $matches[1];
1300 }
1301
1302 // Reject ANY on* event handler attribute. Per the HTML spec every attribute
1303 // name beginning with "on" (optionally followed by a letter and word chars)
1304 if(preg_match('/(on[a-z0-9]{1,60})=/i', $data, $matches)){
1305 return $matches[0];
1306 }
1307
1308 return;
1309
1310 }
1311
1312 // Check for XSS codes in our blocks array
1313 function pagelayer_sanitize_blocks_save_pre($block){
1314
1315 foreach($block as $k => $v){
1316
1317 // Recurse on arrays
1318 if(is_array($v)){
1319 $block[$k] = pagelayer_sanitize_blocks_save_pre($v);
1320
1321 // We dont support objects !
1322 }elseif(is_object($v)){
1323 $block[$k] = null;
1324 // Strings
1325 }else{
1326
1327 if(is_string($v)){
1328
1329 $v = wp_filter_post_kses($v);
1330
1331 while(true){
1332 $str = '"'.($v);
1333 $found = pagelayer_xss_content($str);
1334 //echo (string)$v.'--'.$found."\n";
1335
1336 if(strlen($found) > 0){
1337 // There is htmlentities?
1338 if(strpos($v, $found) === false){
1339 $v = '';
1340 break;
1341 }
1342 $v = str_replace($found, '', $v);
1343 }else{
1344 break;
1345 }
1346
1347 }
1348
1349 }
1350
1351 $block[$k] = $v;
1352 }
1353
1354 }
1355
1356 return $block;
1357 }
1358
1359 // Check for XSS codes in our shortcode attributes
1360 function pagelayer_sanitize_shortcode_atts($content){
1361
1362 // Do we have something suspicious ?
1363 $tmp_check = pagelayer_xss_content($content);
1364 if(empty($tmp_check)){
1365 return $content;
1366 }
1367
1368 pagelayer_load_shortcodes();
1369
1370 preg_match_all( '/' . get_shortcode_regex() . '/', $content, $matches, PREG_SET_ORDER );
1371
1372 $prefixes = ['pl_'];
1373
1374 $prefixes = apply_filters( 'pagelayer_valid_shortcode_tag', $prefixes);
1375
1376 foreach ($matches as $shortcode) {
1377
1378 $shortcode_name = $shortcode[2];
1379
1380 $vailid = false;
1381
1382 foreach($prefixes as $prefix) {
1383 if (strpos($shortcode_name, $prefix) === 0) {
1384 $vailid = true;
1385 break;
1386 }
1387 }
1388
1389 if(!$vailid){
1390 continue;
1391 }
1392
1393 $attrs = shortcode_parse_atts( $shortcode[3] );
1394 $atts = ' ';
1395
1396 foreach($attrs as $key => $value){
1397
1398 // Skip if key contains XSS
1399 if (!is_numeric($key) && strlen(pagelayer_xss_content($key . '=')) > 0) continue;
1400
1401 $value = wp_filter_post_kses($value);
1402
1403 // Skip if value contains XSS
1404 if (strlen(pagelayer_xss_content('"' . $value)) > 0) continue;
1405
1406 $atts .= is_numeric($key) ? $value . ' ' : $key . '="' . $value . '" ';
1407
1408 }
1409
1410 $new_shortcode = '[' . $shortcode_name . $atts . ']';
1411
1412 if(!empty($shortcode[5])){
1413 $new_shortcode .= $shortcode[5].'[/' . $shortcode_name .']';
1414 }
1415
1416 // Replace the original shortcode with sanitized attributes
1417 $content = str_replace($shortcode[0], $new_shortcode, $content);
1418 }
1419
1420 return $content;
1421 }
1422
1423 function pagelayer_getting_started_notice(){
1424
1425 // Is Sitepad setup done?
1426 $setup_done = get_option('sp_setup_done');
1427
1428 if(defined('SITEPAD') && empty($setup_done)){
1429 return;
1430 }
1431
1432 // If SitePad used custom BRAND SM
1433 if(defined('BRAND_SM_CUSTOM')){
1434 return;
1435 }
1436
1437 echo '
1438 <script type="application/javascript">
1439 jQuery(document).ready(function(){
1440 jQuery("#pagelayer-getting-started-notice").click(function(e){
1441
1442 if(jQuery(e.target).hasClass("notice-dismiss")){
1443 var data;
1444 jQuery("#pagelayer-getting-started-notice").hide();
1445 // Save this preference
1446 jQuery.post("'.admin_url('?pagelayer-getting-started=0&pagelayer_nonce='.wp_create_nonce("pagelayer_getting_started_nonce") ).'", data, function(response) {
1447 //alert(response);
1448 });
1449 return false;
1450 }
1451
1452 });
1453 });
1454 </script>
1455
1456 <div id="pagelayer-getting-started-notice" class="notice notice-success is-dismissible">
1457 <p style="font-size: 14px; font-weight: 600">';
1458 if(defined('SITEPAD')){
1459
1460 echo '<a href="'.BRAND_SM_URL.'"><img src="'.BRAND_SM_LOGO .'" style="vertical-align: middle; margin:0px 10px" width="24" /></a>'.__('Thanks for choosing '.BRAND_SM .'. We recommend that you see the short and sweet <a href="'.admin_url('admin.php?page=pagelayer_getting_started').'">Getting Started Video</a> to know the basics of '.BRAND_SM.'.');
1461
1462 }else{
1463
1464 echo '<a href="'.PAGELAYER_WWW_URL.'"><img src="'.PAGELAYER_URL.'/images/pagelayer-logo-256.png" style="vertical-align: middle; margin:0px 10px" width="24" /></a>'.__('Thanks for choosing Pagelayer. We recommend that you see the short and sweet <a href="'.admin_url('admin.php?page=pagelayer_getting_started').'">Getting Started Video</a> to know the basics of Pagelayer.', 'pagelayer');
1465
1466 }
1467
1468 echo '</p>
1469 </div>';
1470
1471 }
1472
1473 // Show Changelog promo
1474 function pagelayer_show_changelog_notice(){
1475
1476 // Is Sitepad setup done?
1477 if(defined('SITEPAD')){
1478 return;
1479 }
1480
1481 echo '
1482 <script type="application/javascript">
1483 jQuery(document).ready(function(){
1484 jQuery("#pagelayer-changelog-notice").click(function(e){
1485
1486 if(jQuery(e.target).hasClass("notice-dismiss")){
1487 var data;
1488 jQuery("#pagelayer-changelog-notice").hide();
1489 // Save this preference
1490 jQuery.post("'.admin_url('?pagelayer-changelog-notice=0&pagelayer_nonce='.wp_create_nonce("pagelayer_changelog_nonce") ).'", data, function(response) {
1491 //alert(response);
1492 });
1493 return false;
1494 }
1495
1496 });
1497 });
1498 </script>
1499
1500 <div id="pagelayer-changelog-notice" class="notice notice-info is-dismissible">
1501 <p style="font-size: 14px; font-weight: 600">
1502 <a href="'.PAGELAYER_WWW_URL.'"><img src="'.PAGELAYER_URL.'/images/pagelayer-logo-256.png" style="vertical-align: middle; margin:0px 10px" width="24" /></a>'.__('Empower Your Designs: Pagelayer 1.8.1 - Unleashing Seamless Integration with Gutenberg for Enhanced Website Creation! <a href="'.PAGELAYER_WWW_URL.'/blog/reinventing-pagelayer-for-gutenberg-a-seamless-fusion-of-powerful-page-building-and-wordpress-editor/">Read More</a>.', 'pagelayer') .'
1503 </p>
1504 </div>';
1505
1506 }
1507
1508 // Show promo notice on dashboard
1509 function pagelayer_show_promo(){
1510
1511 global $pagelayer_promo_opts;
1512 $opts = $pagelayer_promo_opts;
1513
1514 echo '<style>
1515 #pagelayer_promo a.pagelayer_promo_button {
1516 background-color: #4CAF50 !important;
1517 border: none !important;
1518 color: white !important;
1519 padding: 6px 10px !important;
1520 text-align: center !important;
1521 text-decoration: none !important;
1522 display: inline-block !important;
1523 font-size: 13px !important;
1524 margin: 4px 2px !important;
1525 -webkit-transition-duration: 0.4s;
1526 transition-duration: 0.4s;
1527 cursor: pointer !important;
1528 }
1529 #pagelayer_promo a.pagelayer_promo_button:focus,
1530 #pagelayer_promo a.pagelayer_promo_button:hover{
1531 border: none !important;
1532 color: white !important;
1533 box-shadow: 0 6px 8px 0 rgba(0,0,0,0.24), 0 9px 25px 0 rgba(0,0,0,0.19) !important;
1534 }
1535 #pagelayer_promo a.pagelayer_promo_buy {
1536 color: white !important;
1537 padding: 8px 12px !important;
1538 font-size: 14px !important;
1539 background-color: #4CAF50 !important;
1540 }
1541 #pagelayer_promo a.pagelayer_promo_button1 {
1542 color: white !important;
1543 background-color: #4CAF50 !important;
1544 border:3px solid #4CAF50 !important;
1545 }
1546 #pagelayer_promo a.pagelayer_promo_button1:hover {
1547 border:3px solid #4CAF50 !important;
1548 }
1549 #pagelayer_promo a.pagelayer_promo_button2 {
1550 color: white !important;
1551 background-color: #0085ba !important;
1552 }
1553 #pagelayer_promo a.pagelayer_promo_button3 {
1554 color: white !important;
1555 background-color: #365899 !important;
1556 }
1557 #pagelayer_promo a.pagelayer_promo_button4 {
1558 color: white !important;
1559 background-color: rgb(66, 184, 221) !important;
1560 }
1561 #pagelayer_promo a.pagelayer_promo-close{
1562 float:right !important;
1563 text-decoration:none !important;
1564 margin: 5px 10px 0px 0px !important;
1565 color: #666 !important;
1566 }
1567 #pagelayer_promo a.pagelayer_promo-close:hover{
1568 color: red !important;
1569 }
1570 #pagelayer_promo a:not(.pagelayer_promo_button):not(.pagelayer_promo-close) {
1571 color: #4CAF50 !important;
1572 text-decoration: underline !important;
1573 }
1574 #pagelayer_promo a:not(.pagelayer_promo_button):not(.pagelayer_promo-close):hover {
1575 color: #3e8e41 !important;
1576 }
1577 </style>
1578 <script type="application/javascript">
1579 jQuery(document).ready(function(){
1580 jQuery("#pagelayer_promo .pagelayer_promo-close").click(function(){
1581 var data;
1582 jQuery("#pagelayer_promo").hide();
1583 // Save this preference
1584 jQuery.post("'.admin_url('?pagelayer_promo=0').'", data, function(response) {
1585 //alert(response);
1586 });
1587 });
1588 });
1589 </script>
1590
1591 <div class="notice notice-success" id="pagelayer_promo" style="min-height:90px">
1592 <a class="pagelayer_promo-close" href="javascript:" aria-label="Dismiss this Notice">
1593 <span class="dashicons dashicons-dismiss"></span> Dismiss
1594 </a>';
1595
1596 if(!empty($opts['image'])){
1597 echo '<a href="'.$opts['website'].'"><img src="'.$opts['image'].'" style="float:left; margin:10px 20px 10px 10px" width="67" /></a>';
1598 }
1599
1600 echo '
1601 <p style="font-size:13px">We are glad you like <a href="'.$opts['website'].'"><b>Pagelayer</b></a> and have been using it since the past few days. It is time to take the next step !</p>
1602 <p>
1603 '.(empty($opts['pro_url']) ? '' : '<a class="pagelayer_promo_button pagelayer_promo_buy" target="_blank" href="'.$opts['pro_url'].'">Buy Pagelayer Pro</a>').'
1604 '.(empty($opts['rating']) ? '' : '<a class="pagelayer_promo_button pagelayer_promo_button2" target="_blank" href="'.$opts['rating'].'">Rate it 5�
1605 \'s</a>').'
1606 '.(empty($opts['facebook']) ? '' : '<a class="pagelayer_promo_button pagelayer_promo_button3" target="_blank" href="'.$opts['facebook'].'"><span class="dashicons dashicons-thumbs-up"></span> Facebook</a>').'
1607 '.(empty($opts['twitter']) ? '' : '<a class="pagelayer_promo_button pagelayer_promo_button4" target="_blank" href="'.$opts['twitter'].'"><span class="dashicons dashicons-twitter"></span> Tweet</a>').'
1608 '.(empty($opts['website']) ? '' : '<a class="pagelayer_promo_button pagelayer_promo_button4" target="_blank" href="'.$opts['website'].'">Visit our website</a>').'
1609 </p>
1610 <p style="font-size:13px"><a href="'.$opts['pro_url'].'"><b>Pagelayer Pro</b></a> has many more features like 60+ widgets, 400+ sections, Theme Builder, WooCommerce Builder, Theme Creator and Exporter, Form Builder, Popup Builder, etc.';
1611
1612 if(date('Ymd') <= 20200331){
1613 echo '<br><span style="font-size: 14px"><b>Promotional Offer</b></span> : If you buy <a href="'.$opts['pro_url'].'"><b>Pagelayer Pro</b></a> before <b>31st March, 2020</b> then you will get an additional year free and your license will expire on <b>31st March, 2022</b>.';
1614 }
1615
1616 echo '</p></div>';
1617
1618 }
1619
1620 // Are we to show a promo ?
1621 function pagelayer_maybe_promo($opts){
1622
1623 global $pagelayer_promo_opts;
1624
1625 // There must be an interval
1626 if(!current_user_can('activate_plugins')){
1627 return false;
1628 }
1629
1630 // There must be an interval
1631 if(empty($opts['interval'])){
1632 return false;
1633 }
1634
1635 // Are we to show a promo
1636 $opt_name = 'pagelayer_promo_time';
1637 $promo_time = get_option($opt_name);
1638
1639 // First time access
1640 if(empty($promo_time)){
1641 update_option($opt_name, time() + (!empty($opts['after']) ? $opts['after'] * 86400 : 0));
1642 $promo_time = get_option($opt_name);
1643 }
1644
1645 // Is there interval elapsed
1646 if(time() > $promo_time){
1647 $pagelayer_promo_opts = $opts;
1648 add_action('admin_notices', 'pagelayer_show_promo');
1649 }
1650
1651 // Are we to disable the promo
1652 if(isset($_GET['pagelayer_promo']) && (int)$_GET['pagelayer_promo'] == 0){
1653 update_option($opt_name, time() + ($opts['interval'] * 86400));
1654 die('DONE');
1655 }
1656
1657 }
1658
1659 // Show the Pro notice
1660 function pagelayer_show_pro_notice(){
1661
1662 if(defined('PAGELAYER_PREMIUM')){
1663 return;
1664 }
1665
1666 echo '<div class="pagelayer-notice pagelayer-notice-info">'.__('This feature is a part of <a href="'.PAGELAYER_PRO_PRICE_URL.'" target="_blank">Pagelayer Pro</a>. You will need to purchase <a href="'.PAGELAYER_PRO_PRICE_URL.'" target="_blank">Pagelayer Pro</a> to use this feature.').'</div>';
1667
1668 }
1669
1670 // Show the Pro Div
1671 function pagelayer_show_pro_div($head = '', $message = '', $admin_css = 1){
1672
1673 if(defined('PAGELAYER_PREMIUM')){
1674 return;
1675 }
1676
1677 if(basename(get_template_directory()) == 'popularfx'){
1678 $pro_url = 'https://popularfx.com/pricing?from=pagelayer-plugin';
1679 $pro_txt = 'PopularFX Pro';
1680 }else{
1681 $pro_url = PAGELAYER_PRO_PRICE_URL;
1682 $pro_txt = 'Pagelayer Pro';
1683 }
1684
1685 if(!empty($admin_css)){
1686 wp_enqueue_style( 'pagelayer-admin', PAGELAYER_CSS.'/pagelayer-admin.css', array(), PAGELAYER_VERSION);
1687 }
1688
1689 echo '<div class="pagelayer-pro-div">';
1690
1691 if(!empty($head)){
1692 echo '<h1 class="pagelayer-pro-head">'.$head.'</h1>';
1693 }
1694
1695 echo '<div class="pagelayer-pro-message">';
1696
1697 if(empty($message)){
1698
1699 echo __('This feature is a part of <a href="'.$pro_url.'" target="_blank">'.$pro_txt.'</a>. You will need to purchase <a href="'.$pro_url.'" target="_blank">'.$pro_txt.'</a> to use this feature.');
1700
1701 }else{
1702
1703 echo $message;
1704 echo ' '.__('This feature is a part of <a href="'.$pro_url.'" target="_blank">'.$pro_txt.'</a>.');
1705
1706 }
1707
1708 echo '</div>
1709 <center><a class="button-pagelayer" href="'.$pro_url.'" target="_blank" style="text-decoration: none;">'.sprintf(__('Upgrade to %s', 'pagelayer'), $pro_txt).'</a></center>
1710 </div>';
1711
1712 }
1713
1714 // Bread Crumbs with links
1715 function pagelayer_get_breadcrumb(){
1716 global $post;
1717
1718 // Home page
1719 $ret = '<a href="'.home_url().'" rel="nofollow">{{home}}</a>';
1720
1721 // Is Front page
1722 if(is_front_page()){
1723 return $ret;
1724
1725 // Is search query
1726 }elseif(is_search()){
1727 $ret .= '<b class="pagelayer-breadcrumb-sep" if="{{separator}}">{{separator}}</b><b class="pagelayer-breadcrumb-prefix" if="{{search_prefix}}">{{search_prefix}}</b>';
1728 $ret .= '<em>';
1729 $ret .= '<span>'.get_search_query().'</span>';
1730 $ret .= '</em>';
1731
1732 //Is category or single post
1733 }elseif(is_category() || is_single()){
1734
1735 $ret .= '<b class="pagelayer-breadcrumb-sep" if="{{separator}}">{{separator}}</b>';
1736 $categories = get_the_category();
1737 $separator = ' ';
1738 $output = '';
1739 if(!empty($categories)){
1740 $ret .= get_category_parents($categories[0], true, ' <b class="pagelayer-breadcrumb-sep" if="{{separator}}">{{separator}}</b> ');
1741 }
1742 if(is_single()) {
1743 /* if (empty($categories)){
1744 $ret .= ' <b class="pagelayer-breadcrumb-sep" if="{{separator}}">{{separator}}</b> ';
1745 } */
1746 $ret .= '<span>'.get_the_title().'</span>';
1747 }
1748
1749 // Is page
1750 }elseif(is_page() ){
1751 if(!empty($post->post_parent)){
1752 $ancestors = array_reverse(get_post_ancestors( $post->ID ));
1753 $page_on_front = get_option('page_on_front');
1754
1755 foreach( $ancestors as $ancestor ){
1756
1757 if($page_on_front == $ancestor){
1758 continue;
1759 }
1760
1761 $ret .= '<b class="pagelayer-breadcrumb-sep" if="{{separator}}">{{separator}}</b><a href="'.get_permalink($ancestor).'">'.get_the_title($ancestor).'</a>';
1762 }
1763
1764 $ret .=' <b class="pagelayer-breadcrumb-sep" if="{{separator}}">{{separator}}</b><span>'.get_the_title().'</span>';
1765
1766 }else{
1767 $ret .= '<b class="pagelayer-breadcrumb-sep" if="{{separator}}">{{separator}}</b>';
1768 $ret .= '<span>'.get_the_title().'</span>';
1769 }
1770 }else{
1771 $ret .= '<b class="pagelayer-breadcrumb-sep" if="{{separator}}">{{separator}}</b>';
1772 $ret .= '<span>'.wp_title('', false ).'</span>';
1773 }
1774
1775 // wooCommerce Integration left
1776
1777 return $ret;
1778 }
1779
1780 // Portfolio Posts
1781 function pagelayer_widget_posts($args){
1782
1783 $r = new \WP_Query($args);
1784
1785 $ret = '';
1786 if ( $r->have_posts() ){
1787
1788 if($args['filter_by'] != 'none' && $args['post_type'] == 'post'){
1789 $ret .= '<div class="pagelayer-postfolio-filter">';
1790
1791 $data_filter = ( $args['filter_by'] == 'category' ? get_categories() : get_tags() );
1792
1793 if(!empty($data_filter)){
1794
1795 $ret .= '<div class="pagelayer-postfolio-btn" data-filter="all">'.__pl('All').'</div>';
1796
1797 foreach($data_filter as $filter) {
1798 $ret .= '<div class="pagelayer-postfolio-btn" data-filter="'.$filter->name.'">' . $filter->name . '</div>';
1799 }
1800
1801 }
1802
1803 $ret .= '</div>';
1804 }
1805
1806 $ret .= '<div class="pagelayer-postfolio-container">';
1807
1808 while ( $r->have_posts() ) : $r->the_post();
1809 $post_meta = ( $args['filter_by'] == 'category' ? get_the_category() : get_the_tags() );
1810 $meta_attr = '';
1811 if($post_meta){
1812
1813 $meta_array = array();
1814 foreach( $post_meta as $meta ){
1815 $meta_array[] = $meta->name;
1816 }
1817 $meta_attr .= ' data-category="'.implode(' ', $meta_array).'"';
1818 }
1819
1820 $ret .= '<div class="pagelayer-postfolio-thumb"'.(has_post_thumbnail() ? ' style="background:url('.get_the_post_thumbnail_url().')"' : ''). $meta_attr .'>';
1821 $ret .= '<a href="'.esc_url( get_permalink() ).'" rel="bookmark">';
1822 $ret .= '<div class="pagelayer-postfolio-content">';
1823 $ret .= '<h4 class="pagelayer-entry-title">'.get_the_title().'</h4>';
1824 $ret .= '</div></a></div>';
1825
1826 endwhile;
1827
1828 $ret .= '</div>';
1829
1830 }
1831
1832 return $ret;
1833 }
1834
1835 // List all available sizes of images registered on WordPress
1836 function pagelayer_image_sizes(){
1837
1838 $sizes = array();
1839 $sizes = get_intermediate_image_sizes();
1840 $ret = array();
1841 foreach($sizes as $size){
1842 $ret[$size] = __pl($size);
1843 }
1844
1845 return $ret;
1846 }
1847
1848 function pagelayer_remove_excerpt_more($more){
1849 return '';
1850 }
1851
1852 function pagelayer_posts($params, $args = []){
1853 global $post, $wp_query;
1854
1855 if(isset($params['exc_length'])){
1856 $exc_length = (int) $params['exc_length'];
1857 add_filter( 'excerpt_length', function($length) use($exc_length){
1858 return $exc_length;
1859 }, 999 );
1860 }
1861
1862 // add_filter('excerpt_more', 'pagelayer_remove_excerpt_more', 999);
1863
1864 // If args is empty
1865 if(empty($args)){
1866 $args = array(
1867 'post_type' => $params['post_type'],
1868 'posts_per_page' => $params['posts_per_page'],
1869 'order' => $params['order']
1870 );
1871
1872 if(!empty($params['paged'])){
1873 $args['paged'] = $params['paged'];
1874 }
1875
1876 if (!empty($params['term']) || !empty($params['exc_term'])) {
1877 $tax_query = [];
1878
1879 if (!empty($params['term'])) {
1880 $terms = explode(',', $params['term']);
1881 $include = array_reduce($terms, function ($carry, $term) {
1882 list($taxonomy, $slug, $id) = explode(':', $term);
1883 $carry[$taxonomy][] = $slug;
1884 return $carry;
1885 }, []);
1886
1887 $filters = array_filter([
1888 isset($include['category']) ? [
1889 'taxonomy' => 'category',
1890 'field' => 'slug',
1891 'terms' => $include['category'],
1892 'include_children' => false,
1893 ] : null,
1894 isset($include['post_tag']) ? [
1895 'taxonomy' => 'post_tag',
1896 'field' => 'slug',
1897 'terms' => $include['post_tag'],
1898 'include_children' => false,
1899 ] : null,
1900 ]);
1901
1902 if(!empty($filters)){
1903 $tax_query[] = array_merge(['relation' => 'OR'], $filters);
1904 }
1905 }
1906
1907 // Handle exclusions
1908 if (!empty($params['exc_term'])) {
1909 $terms = explode(',', $params['exc_term']);
1910 $include = array_reduce($terms, function ($carry, $term) {
1911 list($taxonomy, $slug, $id) = explode(':', $term);
1912 $carry[$taxonomy][] = $slug;
1913 return $carry;
1914 }, []);
1915
1916 $filters = array_filter([
1917 isset($include['category']) ? [
1918 'taxonomy' => 'category',
1919 'field' => 'slug',
1920 'terms' => $include['category'],
1921 'operator' => 'NOT IN',
1922 'include_children' => false,
1923 ] : null,
1924 isset($include['post_tag']) ? [
1925 'taxonomy' => 'post_tag',
1926 'field' => 'slug',
1927 'terms' => $include['post_tag'],
1928 'operator' => 'NOT IN',
1929 'include_children' => false,
1930 ] : null,
1931 ]);
1932
1933 if(!empty($filters)){
1934 $tax_query[] = array_merge(['relation' => 'AND'], $filters);
1935 }
1936 }
1937
1938 // Apply the combined tax_query
1939 if(!empty($tax_query)){
1940 $args['tax_query'] = array_merge(['relation' => 'AND'], $tax_query);
1941 }
1942 }
1943
1944 if(!empty($params['author_name'])){
1945 $author_name = explode(':', $params['author_name']);
1946 $args['author_name'] = $author_name[0];
1947 }
1948
1949 if(!empty($params['exc_author'])){
1950 $exc_author = explode(':', $params['exc_author']);
1951 $args['author'] = '-'.$exc_author[1];
1952 }
1953
1954 if (!empty($params['offset'])) {
1955 $args['offset'] = (int) $params['offset'];
1956
1957 // Make Compatible for Infinite load
1958 if(!empty($params['infinite_types']) && !empty($params['paged']) && $params['paged'] > 1 ){
1959 $args['offset'] = $args['offset'] + (($params['paged'] - 1) * $params['posts_per_page']);
1960 }
1961 }
1962
1963 if(!empty($params['ignore_sticky'])){
1964 $args['ignore_sticky_posts'] = $params['ignore_sticky'];
1965 }
1966
1967 if(!empty($params['orderby'])){
1968 $args['orderby'] = $params['orderby'];
1969 }
1970
1971 if(!empty($params['by_period'])){
1972 $date_arg = array();
1973 switch($params['by_period']){
1974 case 'last_day':
1975 $date_arg['day'] = date('j')-1;
1976 break;
1977 case 'last_week':
1978 $date_arg['week'] = date('W')-1;
1979 break;
1980 case 'last_month':
1981 $date_arg['month'] = date('n')-1;
1982 break;
1983 case 'last_year':
1984 $date_arg['year'] = date('Y')-1;
1985 break;
1986 case 'custom':
1987 $date_arg['before'] = $params['before_date'];
1988 $date_arg['after'] = $params['after_date'];
1989 break;
1990 }
1991 $args['date_query'] = array(
1992 $date_arg
1993 );
1994 }
1995 }
1996 //pagelayer_print($args);
1997
1998 // Only see published posts
1999 $args['post_status'] = 'publish';
2000
2001 $postsquery = new WP_Query($args);
2002 $data = '';
2003
2004 if(!wp_doing_ajax() && !empty($params['infinite_types'])){
2005 $data.='<div class="pagelayer-post-max" data-max="'.$postsquery->max_num_pages.'"></div>';
2006 }
2007
2008 if(!$postsquery->have_posts()){
2009 return '<h3>No posts found!</h3>';
2010 }
2011
2012 // To reset the post when the $wp_query->post is empty
2013 $orig_post = $post;
2014
2015 while($postsquery->have_posts()) : $postsquery->the_post();
2016 $data .= '<div class="pagelayer-wposts-col">
2017 <div class="pagelayer-wposts-post">
2018 <div class="pagelayer-wposts-featured">';
2019 $data .= '<a href="'. get_the_permalink() .'">';
2020
2021 if(!empty($params['show_thumb'])){
2022 $data .= '<div class="pagelayer-wposts-thumb" style="background:url('.(has_post_thumbnail($postsquery->ID) ? get_the_post_thumbnail_url($postsquery->ID, $params['thumb_size']) : ( empty($params['thumb_img_type']) || empty($params['def_thumb_img']) ? PAGELAYER_URL.'/images/no_screenshot.png' : $params['def_thumb_img']) ).')"></div>';
2023 }
2024 /* if($params['show_thumb'] && has_post_thumbnail( $postsquery->ID )){
2025 $data .= get_the_post_thumbnail_url($postsquery->ID,$params['thumb_size']);
2026 } */
2027 $data .= '</a></div>
2028 <div class="pagelayer-wposts-content">';
2029
2030 if(!empty($params['show_title'])){
2031 $data .= '<a href="'.esc_url( get_permalink() ).'" rel="bookmark"><div class="pagelayer-wposts-title">'. get_the_title().'</div></a>';
2032 }
2033
2034 $data .= '<div class="pagelayer-wposts-meta">';
2035 $sep = '';
2036 if(!empty($params['meta_sep'])){
2037 $sep = ' <b class="pagelayer-wposts-sep">'.$params['meta_sep'].'</b> ';
2038 }
2039 if(!empty($params['author'])){
2040 $data .= '<span class="pagelayer-wposts-author">By <a class="pagelayer-wposts-author-url" href="'.esc_url(get_author_posts_url(get_the_author_meta('ID'))).'">'.esc_html(get_the_author()).'</a></span>'.$sep;
2041 }
2042 if(!empty($params['date'])){
2043 $data .= '<span class="pagelayer-wposts-date"><time class="pagelayer-wposts-entry-date published updated" datetime="'.get_the_date('c').'"><span class="date-d">'.get_the_date('j').'</span> <span class="date-my">'.get_the_date('M, y').'</span></time></span>'.$sep;
2044 }
2045
2046 if(!empty($params['category'])){
2047 $category = get_the_category();
2048 $singlecategory = '';
2049 foreach( $category as $cat ){
2050 $singlecategory .= '<a href="' . get_tag_link( $cat->term_id ) . '">'. $cat->name .'</a>';
2051 }
2052
2053 if(!empty($singlecategory)){
2054 $data .= '<span class="pagelayer-wposts-category">' . $singlecategory . '</span>'.$sep;
2055 }
2056
2057 }
2058
2059 if(!empty($params['tags'])){
2060 $tags = get_the_tags();
2061 $singletag = '';
2062 if(!empty($tags)){
2063 foreach( $tags as $tag ){
2064 $singletag .= '<a href="' . get_tag_link( $tag->term_id ) . '">'. $tag->name .'</a>';
2065 }
2066 if(!empty($singletag)){
2067 $data .= '<span class="pagelayer-wposts-tags">'.$singletag.'</span>'.$sep;
2068 }
2069 }
2070
2071 }
2072
2073 if(!empty($params['comments']) && comments_open($postsquery->ID)){
2074 $data .= '<span class="pagelayer-wposts-comments"><a href="' . esc_url( get_permalink() ) . '">' . esc_html(get_comments_number()).' '.__pl('comments').'</a></span>'.$sep;
2075 }
2076
2077 $data .= '</div>';
2078
2079 if(!empty($params['show_content'])){
2080 $data .= '<div class="pagelayer-wposts-excerpt">';
2081
2082 if($params['show_content'] == 'excerpt'){
2083 $post_excerpt = get_the_excerpt();
2084 $trimmed_excerpt = !empty($params['exc_length']) ? wp_trim_words($post_excerpt, (int) $params['exc_length']) : $post_excerpt;
2085 $data .= pagelayer_the_content($trimmed_excerpt);
2086 } elseif ($params['show_content'] == 'full') {
2087 $data .= pagelayer_the_content(get_the_content());
2088 }
2089 $data .= '</div>';
2090 }
2091
2092 if(!empty($params['show_more'])){
2093 $data .= '<div class="pagelayer-wposts-mdiv"><a class="pagelayer-wposts-more pagelayer-btn-holder pagelayer-ele-link '.$params['btn_type'].' '.$params['size'].' '.$params['icon_position'].'" href="'. get_the_permalink().'">';
2094
2095 if($params['icon']){
2096 $data .= '<i class="'.$params['icon'].' pagelayer-btn-icon"></i>';
2097 }
2098
2099 if($params['more']){
2100 $data .= '<span class="pagelayer-btn-text">'.$params['more'].'</span>';
2101 }
2102
2103 if($params['icon']){
2104 $data .= '<i class="'.$params['icon'].' pagelayer-btn-icon"></i>';
2105 }
2106
2107 $data .= '</a></div>';
2108
2109 //$data .= '<a class="pagelayer-wposts-more" href="'. get_the_permalink().'">'.$params['more'].'</a>';
2110 }
2111
2112 //$data .= '<div class="pagelayer-wposts-date"><p>'.get_the_date().'</p></div>';
2113 $data .= '</div></div></div>';
2114 endwhile;
2115
2116 // In the Gutenberg while adding new page the $wp_query->post was empty
2117 if ( !isset( $wp_query ) || empty($wp_query->post) ) {
2118 $GLOBALS['post'] = $orig_post;
2119 }else{
2120 wp_reset_postdata();
2121 }
2122
2123 return $data;
2124 }
2125
2126 // Get Post Revision
2127 function pagelayer_get_post_revision_by_id($postID){
2128
2129 // Insert the post revision into the database
2130 $post_revisions = array();
2131 $reviews = wp_get_post_revisions($postID);
2132
2133 foreach($reviews as $values){
2134
2135 $date_format = date_i18n('j-M @ H:i', strtotime( $values->post_modified ) );
2136 $user_meta = get_userdata($values->post_author);
2137
2138 if ( false !== strpos( $values->post_name, 'autosave' ) ) {
2139 $type = 'autosave';
2140 } else {
2141 $type = 'revision';
2142 }
2143
2144 $post_tmp_data = array(
2145 'ID' => $values->ID,
2146 'post_author_name' => $user_meta->data->display_name,
2147 'post_author_url' => get_avatar_url($values->post_author),
2148 'post_date' => $date_format,
2149 'post_date_ago' => human_time_diff(strtotime($values->post_modified), current_time( 'timestamp' )) . ' ago ',
2150 'post_type' => $type,
2151 );
2152
2153 $post_revisions[] = $post_tmp_data;
2154 }
2155
2156 return $post_revisions;
2157 }
2158
2159 // Gets author data
2160 function pagelayer_author_data($postID){
2161
2162 $authorID = get_post_field('post_author', $postID);
2163 $data['display_name'] = get_the_author_meta( 'display_name' , $authorID );
2164 $data['description'] = get_the_author_meta( 'description' , $authorID );
2165 $data['user_url'] = get_author_posts_url( $authorID , '' );
2166 $data['avatar'] = get_avatar_url( $authorID );
2167
2168 return $data;
2169 }
2170
2171 // Posts Slider
2172 function pagelayer_posts_slider($params){
2173
2174 $args = array();
2175
2176 if(isset($params['post']['post_type'])){
2177 $args['post_type'] = $params['post']['post_type'];
2178 }
2179
2180 if(isset($params['post']['category'])){
2181 $args['category_name'] = $params['post']['category'];
2182 }
2183
2184 if(isset($params['post']['tags'])){
2185 $args['tag'] = $params['post']['tags'];
2186 }
2187
2188 if(isset($params['post']['order_by'])){
2189 $args['orderby'] = $params['post']['order_by'];
2190 }
2191
2192 if(isset($params['post']['sort_order'])){
2193 $args['order'] = $params['post']['sort_order'];
2194 }
2195
2196 if(isset($params['post']['post_count'])){
2197 $args['posts_per_page'] = $params['post']['post_count'];
2198 }
2199
2200 $data = '';
2201 $postsquery = new WP_Query($args);
2202 if ( $postsquery->have_posts() ){
2203 while ( $postsquery->have_posts() ) : $postsquery->the_post();
2204 $data .= '<li class="pagelayer-posts-slider-col">
2205 <div class="pagelayer-posts-slider-post">
2206 <div class="pagelayer-posts-slider-featured-img">';
2207 $data .= '<a href="'. get_the_permalink() .'">';
2208 if(has_post_thumbnail( $postsquery->ID ) ){
2209 if($params['post']['image_size'] == "full" || $params['post']['image_size'] == "custom" ){
2210 $image = wp_get_attachment_image_src( get_post_thumbnail_id( $postsquery->ID ), 'single-post-thumbnail' );
2211 $data .= '<img class="pagelayer-img" src="'.$image[0].'" class="pagelayer-posts-slider-img">';
2212 }else if($params['post']['image_size'] == "thumbnail"){
2213 $data .= get_the_post_thumbnail();
2214 }
2215 }
2216 $data .= '</a></div>
2217 <div class="pagelayer-posts-slider-content">';
2218 $data .= '<p class="pagelayer-posts-slider-title">'. get_the_title().'</p>';
2219 $data .= '<div class="pagelayer-posts-slider-excerpt">';
2220 if($params['post']['show_excerpt'] == "true"){
2221 if(has_excerpt()){
2222 $excerpt = get_the_excerpt();
2223 $data .= pagelayer_the_content($excerpt);
2224 }
2225 }
2226 $data .= '</div>';
2227 $data .= '<a class="pagelayer-posts-slider-link" href="'. get_the_permalink().'">Read More</a>';
2228 $data .= '<div class="pagelayer-post-slider-date"><p>'.get_the_date().'</p></div>';
2229 $data .= '</div></div></li>';
2230 endwhile;
2231 }
2232 return $data;
2233 }
2234
2235 // Gets the site logo URLs
2236 function pagelayer_site_logo(){
2237
2238 if(get_theme_mod('custom_logo')){
2239 $logo_id = get_theme_mod('custom_logo');
2240 return pagelayer_image($logo_id);
2241 }
2242
2243 return NULL;
2244 }
2245
2246 // Create select options
2247 function pagelayer_create_sel_options( $opt_array , $selected = ''){
2248 $options = '';
2249 foreach($opt_array as $x => $val){
2250
2251 // Single item
2252 if(is_string($opt_array[$x])){
2253 $options .= pagelayer_sel_option($x, $val, $selected);
2254
2255 // Groups
2256 }else{
2257
2258 if(array_key_exists('hide_drop', $opt_array[$x]) && !empty($opt_array[$x]['hide_drop'])){
2259 continue;
2260 }
2261
2262 // If Label is there, then its a normal option
2263 if(array_key_exists('label', $opt_array[$x])){
2264 $options .= pagelayer_sel_option($x, $opt_array[$x]['label'], $selected);
2265
2266 // Optgroups
2267 } else{
2268 $options .= '<optgroup label="'. $x .'">';
2269 $options .= pagelayer_create_sel_options($opt_array[$x], $selected);
2270 $options .= '</optgroup>';
2271 }
2272 }
2273 }
2274
2275 return $options;
2276 }
2277
2278 // Create option HTML
2279 function pagelayer_sel_option($val, $lang, $selected){
2280 return '<option value="'. $val .'" '. (($val != $selected) ? '' : 'selected="selected"') .' >'. $lang .'</option>';
2281 }
2282
2283 // Get values from multi-dimensional array by key
2284 function pagelayer_multi_array_search(&$array, $key){
2285
2286 if(!is_array($array)){
2287 return false;
2288 }
2289
2290 foreach ($array as $k => $v) {
2291
2292 if($k == $key){
2293 return $v;
2294 }
2295
2296 if (is_array($v)) {
2297 $found = pagelayer_multi_array_search($v, $key);
2298 if(!empty($found)){
2299 return $found;
2300 }
2301 }
2302 }
2303
2304 return false;
2305 }
2306
2307 function pagelayer_get_post_term(){
2308
2309 $args = [
2310 'taxonomy' => array('category','post_tag'),
2311 'hide_empty' => false,
2312 ];
2313
2314 $terms = get_terms( $args );
2315
2316 $ret = array();
2317 foreach ( $terms as $term ) {
2318 $ret[$term->taxonomy.':'.$term->slug.':'.$term->term_taxonomy_id] = $term->taxonomy .': '. $term->name;
2319 }
2320 //pagelayer_print($terms);die();
2321 return $ret;
2322 }
2323
2324 function pagelayer_get_post_author(){
2325
2326 $args = [
2327 'capability' => array( 'edit_posts' ),
2328 'fields' => [
2329 'ID',
2330 'display_name',
2331 'user_nicename',
2332 ]
2333 ];
2334
2335 // Capability queries were only introduced in WP 5.9.
2336 if( version_compare( $GLOBALS['wp_version'], '5.9-alpha', '<' ) ){
2337 $args['who'] = 'authors';
2338 unset( $args['capability'] );
2339 }
2340
2341 $authors = new \WP_User_Query( $args );
2342
2343 $ret = array();
2344 foreach ( $authors->get_results() as $author ) {
2345 $ret[$author->user_nicename.':'.$author->ID] = $author->display_name;
2346 }
2347 //pagelayer_print($authors->get_results());die();
2348 return $ret;
2349 }
2350
2351 // Gets the registered post types
2352 function pagelayer_get_public_post_types( $args = [] ) {
2353
2354 global $pagelayer;
2355
2356 $post_type_args = [
2357 'public' => true,
2358 ];
2359
2360 $post_type_args = wp_parse_args( $post_type_args, $args );
2361
2362 $_post_types = get_post_types( $post_type_args, 'objects' );
2363
2364 $post_types = array();
2365
2366 foreach ( $_post_types as $post_type => $object ) {
2367
2368 if($post_type == $pagelayer->builder['name']){
2369 continue;
2370 }
2371
2372 $post_types[ $post_type ] = $object->label;
2373 }
2374 //print_r($post_types);
2375
2376 return $post_types;
2377 }
2378
2379 // Simply echo and dir
2380 function pagelayer_json_output(&$done){
2381
2382 echo json_encode($done);
2383 wp_die();
2384
2385 }
2386
2387 // Get the current query for render the product
2388 function pagelayer_shortcode_current_query($query_args, $atts, $type){
2389 global $wp_query;
2390
2391 if($type == 'pagelayer_current_query'){
2392
2393 if ( ! is_page( wc_get_page_id( 'shop' ) ) ) {
2394 $query_args = $wp_query->query_vars;
2395 }
2396
2397 add_action( "woocommerce_shortcode_before_{$type}_loop", function () {
2398 wc_set_loop_prop( 'is_shortcode', false );
2399 } );
2400
2401 if(!empty($atts['paginate'])){
2402 $page = get_query_var( 'paged', 1 );
2403
2404 if( 1 < $page ) {
2405 $query_args['paged'] = $page;
2406 }
2407 }
2408
2409 // Always query only IDs
2410 $query_args['fields'] = 'ids';
2411
2412 }
2413
2414 return $query_args;
2415 }
2416
2417 // Loads the tags which have parameters of a particular type
2418 function pagelayer_get_prop_type($types){
2419
2420 global $pagelayer;
2421
2422 if(!is_array($types)){
2423 $types = [$types];
2424 }
2425
2426 $ret = [];
2427
2428 // Loop thru all shortcodes
2429 foreach($pagelayer->shortcodes as $tag => $vvv){
2430
2431 // Lets create the CSS, Classes, Attr. Also clean the dependent atts
2432 foreach($pagelayer->tabs as $tab){
2433
2434 if(empty($pagelayer->shortcodes[$tag][$tab])){
2435 continue;
2436 }
2437
2438 foreach($pagelayer->shortcodes[$tag][$tab] as $section => $Lsection){
2439
2440 $props = empty($pagelayer->shortcodes[$tag][$section]) ? @$pagelayer->styles[$section] : @$pagelayer->shortcodes[$tag][$section];
2441
2442 //echo $tab.' - '.$section.' - <br>';
2443
2444 if(empty($props)){
2445 continue;
2446 }
2447
2448 // Loop all props
2449 foreach($props as $prop => $param){
2450
2451 // Load any attachment values
2452 if(!in_array($param['type'], $types)){
2453 continue;
2454 }
2455
2456 $ret[$tag][$prop] = $param['type'];
2457
2458 }
2459
2460 }
2461
2462 }
2463
2464 }
2465
2466 //r_print($ret);die();
2467
2468 return $ret;
2469
2470 }
2471
2472 function pagelayer_export_content($content){
2473
2474 global $pagelayer;
2475
2476 // Just call do_shortcode so we can get list of media files to export
2477 //do_shortcode($content);
2478
2479 $theme_url = preg_replace('/http(s?):\/\//is', '', get_stylesheet_directory_uri());
2480
2481 $content = preg_replace('/http(s?):\/\/'.preg_quote($theme_url, '/').'/is', '{{theme_url}}', $content);
2482
2483 // Remove unnecessary spaces
2484 $content = preg_replace('/--\>\s*(?!<!--)/is', '-->', $content);
2485
2486 // Replace links of the theme for images
2487 $content = pagelayer_export_theme_links($content, get_stylesheet_directory_uri());
2488
2489 ////////////////////
2490 // Handle Link IDs
2491 ////////////////////
2492
2493 if(empty($pagelayer->e['link_tags'])){
2494 $pagelayer->e['link_tags'] = pagelayer_get_prop_type('link');
2495 //r_print($pagelayer->e['link_tags']);die();
2496 }
2497
2498 if(empty($pagelayer->e['media_tags'])){
2499 $pagelayer->e['media_tags'] = pagelayer_get_prop_type(['image', 'video', 'audio', 'media', 'multi_image']);
2500 //r_print($pagelayer->e['media_tags']);die();
2501 }
2502
2503 $parsed = parse_blocks($content);
2504 //r_print($parsed);//die();
2505
2506 $parsed = pagelayer_export_link_ids($parsed);
2507
2508 // Export the media as well
2509 $parsed = pagelayer_export_media($parsed);
2510
2511 // Reserialize
2512 $content = serialize_blocks($parsed);
2513
2514 // We store in SP format
2515 $content = str_replace('<!-- wp:pagelayer', '<!-- sp:pagelayer', $content);
2516 $content = str_replace('<!-- /wp:pagelayer', '<!-- /sp:pagelayer', $content);
2517
2518 // Just pass the content to
2519 $content = pagelayer_export_extract_menu_ids($content);
2520
2521 // Apply a filter
2522 $content = apply_filters('pagelayer_export_content', $content);
2523
2524 return $content;
2525
2526 }
2527
2528 // Export the menu IDs
2529 function pagelayer_export_extract_menu_ids($content){
2530
2531 global $pagelayer;
2532
2533 // Any Menu ?
2534 preg_match_all('/\[pl_wp_menu ([^\]]*)nav_list="(\d*)"([^\]]*)\]/is', $content, $matches);
2535 //r_print($matches);
2536
2537 if(!empty($matches[2])){
2538
2539 foreach($matches[2] as $k => $v){
2540 $v = (int)$v;
2541 $pagelayer->export_menus[$v] = $v;
2542 }
2543 //r_print($pagelayer->export_menus);
2544
2545 }
2546
2547 // Also for block format
2548 preg_match_all('/<!--\s+(?P<closer>\/)?sp:pagelayer\/pl_wp_menu\s+(?P<attrs>{(?:(?:[^}]+|}+(?=})|(?!}\s+\/?-->).)*+)?}\s+)?(?P<void>\/)?-->/s', $content, $matches);
2549
2550 if(!empty($matches['attrs'])){
2551
2552 foreach($matches['attrs'] as $k => $v){
2553 preg_match('/nav_list"\s*:\s*"(\d*)"/is', $v, $vmatch);
2554
2555 if(!empty($vmatch[1])){
2556 $vmatch[1] = (int)$vmatch[1];
2557 $pagelayer->export_menus[$vmatch[1]] = $vmatch[1];
2558 //r_print($pagelayer->export_menus);
2559 }
2560 }
2561 }
2562
2563 return $content;
2564
2565 }
2566
2567 function pagelayer_export_link_ids($parsed){
2568
2569 global $pagelayer;
2570
2571 foreach($parsed as $k => $v){
2572
2573 if(!empty($v['innerBlocks'])){
2574 $parsed[$k]['innerBlocks'] = pagelayer_export_link_ids($v['innerBlocks']);
2575 }
2576
2577 if(!preg_match('/pagelayer/is', $v['blockName'])){
2578 continue;
2579 }
2580
2581 $tag = str_replace('pagelayer/', '', $v['blockName']);
2582 //echo $tag;//die();
2583
2584 // Is there a tag having a link prop
2585 if(empty($pagelayer->e['link_tags'][$tag])){
2586 continue;
2587 }
2588 //echo $tag;die();
2589
2590 foreach($pagelayer->e['link_tags'][$tag] as $kk => $vv){
2591 if(!empty($v['attrs'][$kk]) && is_numeric($v['attrs'][$kk])){
2592 $linked = get_post($v['attrs'][$kk]);
2593 if(!empty($linked->post_name)){
2594 $parsed[$k]['attrs'][$kk] = '||link_id|'.$linked->post_type.'|'.$linked->post_name.'||';
2595 }
2596 //echo $tag;echo '-'.$kk;r_print($parsed[$k]['attrs']);die();
2597 }
2598 }
2599
2600 }
2601
2602 return $parsed;
2603
2604 }
2605
2606 // Replace theme links with theme_url
2607 function pagelayer_export_theme_links($content, $link){
2608
2609 global $sitepad;
2610
2611 // Theme URL correction code
2612 $theme_url = preg_replace('/http(s?):\/\//is', '', $link);
2613
2614 $theme_urls[0] = 'http://'.$theme_url;
2615 $theme_urls[1] = 'https://'.$theme_url;
2616 $theme_urls[2] = $theme_url;
2617 $theme_urls[3] = str_replace('/', '\\/', $theme_urls[0]);
2618 $theme_urls[4] = str_replace('/', '\\/', $theme_urls[1]);
2619 $theme_urls[5] = str_replace('/', '\\/', $theme_url);
2620
2621 foreach($theme_urls as $k => $v){
2622 $content = preg_replace_callback('/'.preg_quote($v, '/').'([^"]*)/is', 'pagelayer_export_theme_links_replacer', $content);
2623 }
2624
2625 $content = str_ireplace($theme_urls, '{{theme_url}}', $content);
2626
2627 return $content;
2628 }
2629
2630 // This function is a part of pagelayer_export_theme_links
2631 function pagelayer_export_theme_links_replacer($matches){
2632 return '{{theme_url}}'.str_replace('\\/', '/', $matches[1]);
2633 }
2634
2635 // Export media
2636 function pagelayer_export_media($parsed){
2637
2638 global $pagelayer;
2639
2640 foreach($parsed as $k => $v){
2641
2642 if(!empty($v['innerBlocks'])){
2643 $parsed[$k]['innerBlocks'] = pagelayer_export_media($v['innerBlocks']);
2644 }
2645
2646 if(!preg_match('/pagelayer/is', $v['blockName'])){
2647 continue;
2648 }
2649
2650 $tag = str_replace('pagelayer/', '', $v['blockName']);
2651 //echo $tag;//die();
2652
2653 // Is there a tag having a link prop
2654 if(empty($pagelayer->e['media_tags'][$tag])){
2655 continue;
2656 }
2657 //echo $tag;die();
2658
2659 foreach($pagelayer->e['media_tags'][$tag] as $kk => $vv){
2660
2661 if(empty($v['attrs'][$kk])){
2662 continue;
2663 }
2664
2665 $is_array = 0;
2666
2667 // Is it an array
2668 if(is_array($v['attrs'][$kk])){
2669
2670 $ids = $v['attrs'][$kk];
2671 $is_array = 1;
2672
2673 // Is it of the format 1,2,3
2674 }elseif(preg_match('/^((\d*)(,?))*$/is', $v['attrs'][$kk])){
2675
2676 $ids = pagelayer_maybe_explode(',', $v['attrs'][$kk]);
2677
2678 // Its a number or string
2679 }else{
2680
2681 // Is it our default image ?
2682 if(preg_match('/pagelayer-pro\/images\/default-image.png$/is', $v['attrs'][$kk])){
2683 $parsed[$k]['attrs'][$kk] = '';
2684 continue;
2685 }
2686
2687 // It should be a number
2688 if(!is_numeric($v['attrs'][$kk])){
2689 continue;
2690 }
2691
2692 $ids = [$v['attrs'][$kk]];
2693 }
2694
2695 $ret = [];
2696
2697 foreach($ids as $id){
2698
2699 $file = pagelayer_export_media_files($id, $exp_img_url);
2700
2701 // Did it export ?
2702 if(empty($file) || !file_exists($file)){
2703 continue;
2704 }
2705
2706 $ret[] = $exp_img_url;
2707
2708 }
2709
2710 $parsed[$k]['attrs'][$kk] = $is_array ? $ret : implode(',', $ret);
2711 //echo $tag;echo '-'.$kk;r_print($parsed[$k]['attrs']);die();
2712 }
2713
2714 }
2715
2716 return $parsed;
2717
2718 }
2719
2720 // Exports the media to the images folder of the current theme
2721 function pagelayer_export_media_files($id, &$url = ''){
2722
2723 $theme_dir = get_stylesheet_directory();
2724 $image_dir = $theme_dir.'/images/';
2725 @mkdir($image_dir);
2726
2727 // Get the file path
2728 $file = get_attached_file($id);
2729
2730 if(empty($file) || !file_exists($file)){
2731 return false;
2732 }
2733
2734 $dest_file = $image_dir.basename($file);
2735
2736 // Copy the file
2737 copy($file, $dest_file);
2738
2739 // Replace the text
2740 $url = '{{theme_url}}/images/'.basename($file);
2741
2742 return $dest_file;
2743
2744 //echo $content;
2745 }
2746
2747 // Insert a post which is a Pagelayer Post
2748 function pagelayer_sanitize_content($content){
2749
2750 if(empty($content)){
2751 return $content;
2752 }
2753
2754 // Replace Vars
2755 $template_vars = pagelayer_template_vars();
2756
2757 foreach($template_vars as $key => $val){
2758 $content = str_replace($key, $val, $content);
2759 }
2760
2761 if(defined('PAGELAYER_BLOCK_PREFIX') && PAGELAYER_BLOCK_PREFIX == 'wp'){
2762 $content = str_replace('<!-- sp:pagelayer', '<!-- wp:pagelayer', $content);
2763 $content = str_replace('<!-- /sp:pagelayer', '<!-- /wp:pagelayer', $content);
2764 }
2765
2766 return $content;
2767 }
2768
2769 // Insert a post which is a Pagelayer Post
2770 function pagelayer_insert_content($post, &$ret){
2771
2772 $post = apply_filters('pagelayer_start_insert_content', $post);
2773
2774 $post['post_content'] = pagelayer_sanitize_content($post['post_content']);
2775 //pagelayer_print($post);die();
2776
2777 // Add slashes for safe insert
2778 $post['post_content'] = wp_slash($post['post_content']);
2779
2780 $post = apply_filters('pagelayer_pre_insert_content', $post);
2781
2782 // Now insert / update the post
2783 $ret = wp_insert_post($post);
2784
2785 // Did we save the post ?
2786 if(empty($ret) || is_wp_error($ret)){
2787 return false;
2788 }
2789
2790 // Convert to pagelayer accessed post
2791 if(!add_post_meta($ret, 'pagelayer-data', time(), true)){
2792 update_post_meta($ret, 'pagelayer-data', time());
2793 }
2794
2795 return $ret;
2796
2797 }
2798
2799 // Gets the list of enabled fonts
2800 function pagelayer_enabled_icons(){
2801
2802 $stored_icons = get_option('pagelayer_icons_set');
2803 if(empty($stored_icons)){
2804 update_option('pagelayer_icons_set', ['font-awesome5']);
2805 $stored_icons = get_option('pagelayer_icons_set');
2806 }
2807
2808 return $stored_icons;
2809
2810 }
2811
2812 // Prevent pro activate text for installer
2813 function pagelayer_install_plugin_complete_actions($install_actions, $api, $plugin_file){
2814
2815 if($plugin_file == PAGELAYER_PREMIUM_BASE){
2816 return array();
2817 }
2818
2819 return $install_actions;
2820 }
2821
2822 // Handle hexa to rgba and also remove alpha which is ff
2823 function pagelayer_hex8_to_rgba($val){
2824
2825 // If opacity is ff then discard ff
2826 if(preg_match('/^#([a-f0-9]{6})ff$/is', $val)){
2827 return substr($val, 0, 7);
2828 }
2829
2830 // Lets handle the RGB+opacity
2831 if(preg_match('/#([a-f0-9]{8})$/is', $val)){
2832 $val = pagelayer_hex2rgba($val);
2833 }
2834
2835 return $val;
2836
2837 }
2838
2839 // Convert to RGBA from HEX
2840 function pagelayer_hex2rgba($color){
2841
2842 //Return if no color provided
2843 if(empty($color)){
2844 return;
2845 }
2846
2847 //Sanitize $color if "#" is provided
2848 if ($color[0] == '#'){
2849 $color = substr( $color, 1 );
2850 }
2851
2852 //Check if color has 6 or 3 characters and get values
2853 if (strlen($color) == 8) {
2854 $hex = array( $color[0] . $color[1], $color[2] . $color[3], $color[4] . $color[5] );
2855 $alpha = $color[6] . $color[7];
2856 //$alpha = '';
2857 } elseif (strlen($color) == 6) {
2858 $hex = array( $color[0] . $color[1], $color[2] . $color[3], $color[4] . $color[5] );
2859 } elseif ( strlen( $color ) == 3 ) {
2860 $hex = array( $color[0] . $color[0], $color[1] . $color[1], $color[2] . $color[2] );
2861 } else {
2862 return;
2863 }
2864
2865 //Convert hexadec to rgb
2866 $rgb = array_map('hexdec', $hex);
2867
2868 //Check if opacity is set(rgba or rgb)
2869 if($alpha){
2870
2871 $alpha = number_format((float)hexdec($alpha) / 255, 2, '.', '');
2872 //print_r($alpha);
2873 if(abs($alpha) > 1){
2874 $alpha = 1.0;
2875 }
2876 $output = 'rgba('.implode(",",$rgb).','.$alpha.')';
2877 } else {
2878 $output = 'rgb('.implode(",",$rgb).')';
2879 }
2880
2881 //Return rgb(a) color string
2882 return $output;
2883 }
2884
2885 // Get social URLs
2886 function pagelayer_get_social_urls(){
2887
2888 $urls = array();
2889
2890 $urls['facebook'] = get_option('pagelayer-facebook-url');
2891 $urls['twitter'] = get_option('pagelayer-twitter-url');
2892 $urls['instagram'] = get_option('pagelayer-instagram-url');
2893 $urls['linkedin'] = get_option('pagelayer-linkedin-url');
2894 $urls['youtube'] = get_option('pagelayer-youtube-url');
2895 $urls['google'] = get_option('pagelayer-gplus-url');
2896
2897 foreach($urls as $k => $v){
2898
2899 if(empty($v)){
2900 unset($urls[$k]);
2901 continue;
2902 }
2903
2904 $urls[$k] = esc_url($v);
2905 }
2906
2907 return $urls;
2908 }
2909
2910 function pagelayer_get_option($opt){
2911 $ret = get_option($opt);
2912
2913 $opts = array(
2914 'pagelayer-address' => '1, My Address, My Street, New York City, NY, USA',
2915 'pagelayer-phone' => '+1234567890',
2916 'pagelayer-copyright' => '© '.date('Y').' '.get_option('blogname'),
2917 'pagelayer_cf_to_email' => 'contact@domain.com',
2918 'pagelayer_cf_success' => __pl('cf_success'),
2919 'pagelayer_cf_failed' => __pl('cf_failed'),
2920 );
2921
2922 if(empty($ret)){
2923 return $opts[$opt];
2924 }
2925
2926 return wp_kses_post($ret);
2927 }
2928
2929 // Uploads an image / media
2930 function pagelayer_upload_media($filename, $blob){
2931
2932 if(empty($blob)){
2933 return false;
2934 }
2935
2936 $md5 = md5($blob);
2937
2938 // Do we have this image
2939 $args = array(
2940 'post_type' => 'attachment',
2941 'post_status' => 'inherit',
2942 'meta_query' => array(
2943 array(
2944 'key' => 'pagelayer_image_md5',
2945 'value' => $md5,
2946 )
2947 )
2948 );
2949
2950 $query = new WP_Query($args);
2951
2952 // If we found the image, return
2953 foreach($query->posts as $ck => $cv){
2954 return $cv->ID;
2955 }
2956
2957 $upload = wp_upload_bits($filename, null, $blob);
2958
2959 if( !empty( $upload['error'] ) ) {
2960 return false;
2961 }
2962
2963 $file_path = $upload['file'];
2964 $file_name = basename( $file_path );
2965 $file_type = wp_check_filetype( $file_name, null );
2966 $attachment_title = sanitize_file_name( pathinfo( $file_name, PATHINFO_FILENAME ) );
2967 $wp_upload_dir = wp_upload_dir();
2968
2969 $post_info = array(
2970 'guid' => $wp_upload_dir['url'] . '/' . $file_name,
2971 'post_mime_type'=> $file_type['type'],
2972 'post_title' => $attachment_title,
2973 'post_content' => '',
2974 'post_status' => 'inherit',
2975 );
2976
2977 $attach_id = wp_insert_attachment( $post_info, $file_path, $parent_post_id );
2978 update_post_meta($attach_id, 'pagelayer_image_md5', $md5);
2979
2980 $lib = ABSPATH . 'site-admin/includes/image.php';
2981 $media = ABSPATH . 'site-admin/includes/media.php';
2982 $media = file_exists($media) ? $media : ABSPATH . 'wp-admin/includes/media.php';
2983 $lib = file_exists($lib) ? $lib : ABSPATH . 'wp-admin/includes/image.php';
2984
2985 require_once($media);
2986 require_once($lib);
2987
2988 $attach_data = wp_generate_attachment_metadata( $attach_id, $file_path );
2989 wp_update_attachment_metadata( $attach_id, $attach_data );
2990
2991 return $attach_id;
2992
2993 }
2994
2995 // Show the notice of importing the active themes content
2996 function pagelayer_theme_import_notices($return = false){
2997
2998 $theme = wp_get_theme();
2999
3000 $imported = get_option('pagelayer_theme_'.get_template().'_imported');
3001 $show = 0;
3002
3003 // We need to import the content
3004 if(empty($imported) && is_admin() && current_user_can('switch_themes')){
3005 $show = 1;
3006 }
3007
3008 $dismissed = get_option('pagelayer_theme_'.get_template().'_dismissed');
3009
3010 // Is this dismissed
3011 if($dismissed){
3012 $show = 0;
3013 }
3014
3015 //$show = 1;
3016
3017 // Is it the importer page ?
3018 if(!empty($_REQUEST['page']) && $_REQUEST['page'] == 'pagelayer_import'){
3019 $show = 0;
3020 }
3021
3022 // Show the message
3023 if(!empty($show)){
3024 $str = '
3025
3026 <style>
3027 .pagelayer_promo_button {
3028 background-color: #4CAF50; /* Green */
3029 border: none;
3030 color: white;
3031 padding: 6px 10px;
3032 text-align: center;
3033 text-decoration: none;
3034 display: inline-block;
3035 font-size: 13px;
3036 margin: 4px 2px;
3037 -webkit-transition-duration: 0.4s; /* Safari */
3038 transition-duration: 0.4s;
3039 cursor: pointer;
3040 }
3041 .pagelayer_promo_button:focus,
3042 .pagelayer_promo_button:hover{
3043 border: none;
3044 color: white;
3045 box-shadow: 0 6px 8px 0 rgba(0,0,0,0.24), 0 9px 25px 0 rgba(0,0,0,0.19);
3046 color: white;
3047 }
3048 .pagelayer_promo_buy {
3049 color: white;
3050 padding: 8px 12px;
3051 font-size: 14px;
3052 }
3053 .pagelayer_promo_button1 {
3054 color: white;
3055 background-color: #4CAF50;
3056 border:3px solid #4CAF50;
3057 }
3058 .pagelayer_promo_button1:hover {
3059 border:3px solid #4CAF50;
3060 }
3061 .pagelayer_promo_button2 {
3062 color: white;
3063 background-color: #0085ba;
3064 }
3065 .pagelayer_promo_button3 {
3066 color: white;
3067 background-color: #365899;
3068 }
3069 .pagelayer_promo_button4 {
3070 color: white;
3071 background-color: rgb(66, 184, 221);
3072 }
3073 .pagelayer_promo-close{
3074 float:right;
3075 text-decoration:none;
3076 margin: 5px 10px 0px 0px;
3077 }
3078 .pagelayer_promo-close:hover{
3079 color: red;
3080 }
3081 </style>
3082
3083 <script type="application/javascript">
3084 jQuery(document).ready(function(){
3085 jQuery("#pagelayer_promo .pagelayer_promo-close").click(function(){
3086 var data;
3087 jQuery("#pagelayer_promo").hide();
3088 // Save this preference
3089 jQuery.post("'.admin_url('?pagelayer_promo=0').'", data, function(response) {
3090 //alert(response);
3091 });
3092 });
3093 });
3094 </script>
3095
3096 <div class="notice notice-success" id="pagelayer_promo" style="min-height:30px">
3097 <a class="pagelayer_promo-close" href="javascript:" aria-label="Dismiss this Notice">
3098 <span class="dashicons dashicons-dismiss"></span> Dismiss
3099 </a>';
3100
3101 $str .= apply_filters('pagelayer_theme_import_notice_content', '<p>Please click <a href="'.admin_url('admin.php?page=pagelayer_import').'">here</a> to import your themes content</p>').'
3102
3103 </div>';
3104
3105 // Print it
3106 if(empty($return)){
3107 echo $str;
3108 }else{
3109 return $str;
3110 }
3111 }
3112
3113 }
3114
3115 // Parse the array variables
3116 function pagelayer_replace_vars( $string, $array, $pre = '', $suf = ''){
3117
3118 $array = (array) $array;
3119
3120 foreach($array as $kk => $vv){
3121
3122 if(is_array($vv)){
3123 $vv = pagelayer_flat_join($vv);
3124 }
3125
3126 $string = str_replace($pre.$kk.$suf, $vv, $string);
3127 }
3128 return $string;
3129 }
3130
3131 // Add Attachment to the contact the email
3132 function pagelayer_cf_email_attachment( &$phpmailer) {
3133
3134 if ( ! empty( $_FILES ) ) {
3135 foreach ( $_FILES as $attachment ) {
3136
3137 if(empty($attachment['name'])){
3138 continue;
3139 }
3140
3141 try {
3142 $phpmailer->addAttachment($attachment['tmp_name'], $attachment['name'], $encoding = 'base64', $attachment['type'], $disposition = 'attachment');
3143 } catch ( \Exception $e ) {
3144 continue;
3145 }
3146 }
3147 }
3148
3149 }
3150
3151 function pagelayer_array_flatten( $input ) {
3152 if ( ! is_array( $input ) ) {
3153 return array( $input );
3154 }
3155
3156 $output = array();
3157
3158 foreach ( $input as $value ) {
3159 $output = array_merge( $output, pagelayer_array_flatten( $value ) );
3160 }
3161
3162 return $output;
3163 }
3164
3165 function pagelayer_flat_join( $array ) {
3166 $array = pagelayer_array_flatten( $array );
3167 $output = array();
3168
3169 foreach ( (array) $array as $value ) {
3170 $output[] = trim( (string) $value );
3171 }
3172
3173 return implode( ', ', $output );
3174 }
3175
3176 // Verifies the Google Captcha
3177 function pagelayer_captcha_verify(){
3178
3179 // If secret key is not there, return
3180 $captcha_secret = get_option('pagelayer_google_captcha_secret');
3181
3182 if(empty($captcha_secret)){
3183 return true;
3184 }
3185
3186 $response = !empty($_POST['g-recaptcha-response']) ? sanitize_text_field($_POST['g-recaptcha-response']) : '';
3187
3188 $ip = pagelayer_getip();
3189
3190 // Is the IP or response not there ?
3191 if(empty($response) || empty($ip)){
3192 return false;
3193 }
3194
3195 $url = 'https://www.google.com/recaptcha/api/siteverify';
3196
3197 // Verify the post
3198 $req = wp_remote_post($url, array(
3199 'timeout' => 20,
3200 'body' => array(
3201 'secret' => $captcha_secret,
3202 'response' => $response,
3203 'remoteip' => $ip
3204 )
3205 )
3206 );
3207
3208 // Was there an error posting ?
3209 if(is_wp_error($req)){
3210 return false;
3211 }
3212
3213 // Process the post response
3214 $resp = wp_remote_retrieve_body($req);
3215
3216 // Is the body valid
3217 if(empty($resp)){
3218 return false;
3219 }
3220
3221 $json = json_decode($resp, true);
3222
3223 if(!empty($json['success']) && // for v2 and v3
3224 (!isset($json['score']) || $json['score'] >= 0.5 && $json['action'] === 'submit') // For v3
3225 ){
3226 return true;
3227 }
3228
3229 return false;
3230 }
3231
3232 // Pagelayer serialize attributes
3233 function pagelayer_serialize_attributes( $block_attributes ) {
3234 $encoded_attributes = json_encode( $block_attributes, JSON_FORCE_OBJECT);
3235 $encoded_attributes = preg_replace( '/--/', '\\u002d\\u002d', $encoded_attributes );
3236 $encoded_attributes = preg_replace( '/</', '\\u003c', $encoded_attributes );
3237 $encoded_attributes = preg_replace( '/>/', '\\u003e', $encoded_attributes );
3238 // Regex: /\\"/
3239 $encoded_attributes = preg_replace( '/\\\\"/', '\\u0022', $encoded_attributes );
3240
3241 return $encoded_attributes;
3242 }
3243
3244 function pagelayer_enable_giver(){
3245 global $pagelayer;
3246 return !empty($pagelayer->settings['enable_giver']) && $pagelayer->settings['enable_giver'] == 1;
3247 }
3248
3249 function pagelayer_load_font_options(){
3250 include_once(PAGELAYER_DIR.'/main/font-options.php');
3251 }
3252
3253 function pagelayer_is_utf8($str) {
3254 return (bool) preg_match('//u', $str);
3255 }
3256
3257 // Create blank images
3258 function pagelayer_create_blank_image($width, $height){
3259
3260 $im = @imagecreate($width, $height);
3261
3262 if(empty($im)){
3263 return false;
3264 }
3265
3266 $background_color = imagecolorallocate($im, 220, 220, 220);
3267 $text_color = imagecolorallocate($im, 110, 110, 110);
3268 $string = $width.' x '.$height;
3269 $font_size = 30;
3270 $sx = ($width / 2) - (strlen($string) * $font_size / 2);
3271 $sy = ($height / 2) - ($font_size / 2);
3272 $font = realpath(PAGELAYER_DIR.'/fonts/OpenSans-BoldItalic.ttf');
3273 imagettftext($im, $font_size, 0, $sx, $sy, $text_color, $font, $string);
3274 ob_start();
3275 imagepng($im);
3276 imagedestroy($im);
3277
3278 return ob_get_clean();
3279
3280 }
3281
3282 // Get category name by post type
3283 function pagelayer_post_type_category($post_type){
3284
3285 $taxonomies = get_object_taxonomies( $post_type, 'objects');
3286
3287 foreach( $taxonomies as $key => $tax){
3288 if(!empty($tax->hierarchical)){
3289 return $key;
3290 }
3291 }
3292
3293 return false;
3294
3295 }
3296
3297 // Get tag name by post type
3298 function pagelayer_post_type_tag($post_type){
3299
3300 $taxonomies = get_object_taxonomies( $post_type, 'objects');
3301
3302 foreach( $taxonomies as $key => $tax){
3303 if(!empty($tax->show_tagcloud) && empty($tax->hierarchical)){
3304 return $key;
3305 }
3306 }
3307 return false;
3308
3309 }
3310
3311 // Get checkboxes of post categories.
3312 function pagelayer_post_cats($post, &$cat_name = ''){
3313
3314 $ret = [];
3315
3316 $cat_name = pagelayer_post_type_category($post->post_type);
3317
3318 if(empty($cat_name)){
3319 return $ret;
3320 }
3321
3322 include_once(ABSPATH.PAGELAYER_CMS_DIR_PREFIX.'-admin/includes/template.php');
3323
3324 $args1 = array(
3325 'taxonomy' => $cat_name,
3326 'checked_ontop' => false,
3327 'echo' => false,
3328 );
3329
3330 $ret['with_checkbox'] = '<ul class="pagelayer-post-category" >'.wp_terms_checklist($post->ID, $args1 ).'</ul>';
3331
3332 $args2 = array(
3333 'taxonomy' => $cat_name,
3334 'hierarchical' => true,
3335 'echo' => 0,
3336 'class' => 'pagelayer-add-cat',
3337 'name' => 'pagelayer_cat_parent',
3338 'style' => 'list',
3339 'hide_empty' => 0,
3340 );
3341
3342 $ret['without_checkbox'] = wp_dropdown_categories( $args2 );
3343
3344 return $ret;
3345
3346 }
3347
3348 // Get checkboxes of post tags.
3349 function pagelayer_post_tags($post, &$tag_name = ''){
3350
3351 $ret = [];
3352
3353 $tag_name = pagelayer_post_type_tag($post->post_type);
3354
3355 if(empty($tag_name)){
3356 return $ret;
3357 }
3358
3359 $ret['postTags'] = wp_get_post_terms( $post->ID, $tag_name );
3360
3361 $ret['allTags'] = get_tags(array( 'hide_empty' => false, 'taxonomy' => $tag_name ));
3362
3363 return $ret;
3364
3365 }
3366
3367 // Get users who can edit a particular post type
3368 function pagelayer_post_authors_by_type($post_type){
3369
3370 global $wp_post_types;
3371
3372 if(empty($wp_post_types[$post_type])){
3373 $users = get_users( array( 'role__in' => array( 'administrator' ) ) );
3374 }else{
3375 $req_role = $wp_post_types[$post_type]->cap->edit_posts;
3376 $roles__in = [];
3377 foreach( wp_roles()->roles as $role_slug => $role ){
3378 if( ! empty( $role['capabilities'][$req_role] ) )
3379 $roles__in[] = $role_slug;
3380 }
3381 $users = get_users( array( 'role__in' => $roles__in ) );
3382 }
3383
3384 $user_array = [];
3385
3386 foreach ( $users as $user ) {
3387 $user_array[$user->ID] = $user->display_name;
3388 }
3389
3390 return $user_array;
3391 }
3392
3393 function pagelayer_parent_post_prop($post){
3394 global $wp_post_types;
3395
3396 if(!empty($wp_post_types[$post->post_type]->hierarchical)){
3397 return pagelayer_list_parents(0, 0, $post, []);
3398 }else{
3399 return [];
3400 }
3401 }
3402
3403 function pagelayer_list_parents( $parent = 0, $level = 0, $post = null, $values=array('')){
3404
3405 global $wpdb;
3406
3407 $post = get_post( $post );
3408
3409 $items = $wpdb->get_results( $wpdb->prepare( "SELECT ID, post_parent, post_title FROM $wpdb->posts
3410 WHERE post_parent = %d
3411 AND post_type = '".$post->post_type."'
3412 AND post_status = 'publish'
3413 ORDER BY menu_order", $parent ) );
3414
3415 if ( !empty($items) ) {
3416 foreach ( $items as $item ) {
3417
3418 // A page cannot be its own parent.
3419 if ( $post && $post->ID && (int) $item->ID === $post->ID ) {
3420 continue;
3421 }
3422
3423 $pad = str_repeat( '-', $level );
3424
3425 if(count($values)==0){
3426 $values[] = '';
3427 }
3428
3429 $values[' '.$item->ID] = $pad.esc_html( $item->post_title );
3430
3431 $values = pagelayer_list_parents($item->ID, $level + 1, $post, $values );
3432 }
3433 }
3434
3435 return $values;
3436 }
3437
3438 // Maybe explode
3439 function pagelayer_maybe_explode( $separator = ',', $string = '', $limit = PHP_INT_MAX ){
3440
3441 if(is_array($string)){
3442 return $string;
3443 }
3444
3445 return explode($separator, $string, $limit);
3446 }
3447
3448 // Maybe implode
3449 function pagelayer_maybe_implode($array, $separator = ','){
3450
3451 if(is_array($array)){
3452 return @implode($separator, $array);
3453 }
3454
3455 if(is_null($array)){
3456 return '';
3457 }
3458
3459 return $array;
3460
3461 }
3462
3463 // Sanitize text field or array
3464 function pagelayer_sanitize_text_field($str) {
3465
3466 if ( !is_object( $str ) && !is_array( $str ) ) {
3467 return sanitize_text_field($str);
3468 }
3469
3470 if( is_array($str) ){
3471 return array_map( 'pagelayer_sanitize_text_field', $str);
3472 }
3473
3474 return $str;
3475 }
3476
3477 // Sanitize posts data for WP_Query
3478 function pagelayer_sanitize_posts_data($data, $only_allowed = true) {
3479
3480 $allowed_keys = [
3481 'post_type', 'posts_per_page', 'order', 'orderby', 'paged',
3482 'filter_by', 'term', 'exc_term', 'cat', 'category_name',
3483 'tag', 'author', 'author_name', 'post__in', 'post__not_in',
3484 'include', 'exclude', 'search', 's', 'exact', 'sentence',
3485 'post_status', 'post_parent', 'offset',
3486 'posts_per_archive_page', 'page', 'ignore_sticky_posts'
3487 ];
3488
3489 $sanitized = [];
3490
3491 foreach($data as $key => $value){
3492 if($only_allowed && !in_array($key, $allowed_keys)) {
3493 continue;
3494 }
3495
3496 $sanitized[$key] = pagelayer_sanitize_text_field($value);
3497 }
3498
3499 // Security: Restrict post_status to prevent information disclosure
3500 // Only users who can read private posts or edit others' posts should be able to query non-public statuses
3501 if(isset($sanitized['post_status'])){
3502 $requested_status = $sanitized['post_status'];
3503
3504 // If requesting something other than publish, verify permissions
3505 if ($requested_status !== 'publish') {
3506 // Check if the user has permission to read private posts or edit others' posts
3507 // This prevents contributors from seeing titles of private posts they don't own.
3508 if (!current_user_can('read_private_posts') && !current_user_can('edit_others_posts')) {
3509 $sanitized['post_status'] = 'publish';
3510 }
3511 }
3512 }else{
3513 // Default to publish for safety if not specified
3514 $sanitized['post_status'] = 'publish';
3515 }
3516
3517 if(isset($sanitized['posts_per_page'])){
3518 $sanitized['posts_per_page'] = (int) $sanitized['posts_per_page'];
3519 if ($sanitized['posts_per_page'] > 100) {
3520 $sanitized['posts_per_page'] = 100;
3521 }
3522 }
3523
3524 if(isset($sanitized['paged'])){
3525 $sanitized['paged'] = (int) $sanitized['paged'];
3526 }
3527
3528 if(isset($sanitized['offset'])){
3529 $sanitized['offset'] = (int) $sanitized['offset'];
3530 }
3531
3532 if(isset($sanitized['post__in']) && is_string($sanitized['post__in'])){
3533 $sanitized['post__in'] = array_map('intval', explode(',', $sanitized['post__in']));
3534 }
3535
3536 if(isset($sanitized['post__not_in']) && is_string($sanitized['post__not_in'])){
3537 $sanitized['post__not_in'] = array_map('intval', explode(',', $sanitized['post__not_in']));
3538 }
3539
3540 if(isset($sanitized['post_parent'])){
3541 $sanitized['post_parent'] = (int) $sanitized['post_parent'];
3542 }
3543
3544 if(isset($sanitized['cat'])){
3545 $sanitized['cat'] = (int) $sanitized['cat'];
3546 }
3547
3548 if(isset($sanitized['author'])){
3549 $sanitized['author'] = (int) $sanitized['author'];
3550 }
3551
3552 return $sanitized;
3553 }
3554
3555 // Update nav menu item
3556 function pagelayer_save_nav_menu_items($items){
3557
3558 // Menu setting keys
3559 $allowed_post = array('title' => 'post_title');
3560 $allowed_meta = array('_pagelayer_content');
3561
3562 foreach($items as $id => $values){
3563
3564 $meta_input = array();
3565 $id = (int) $id;
3566 $post = get_post($id);
3567
3568 // Post found ?
3569 if(empty($post)){
3570 continue;
3571 }
3572
3573 foreach($values as $kk => $vv){
3574
3575 if(array_key_exists($kk, $allowed_post)){
3576 $name = $allowed_post[$kk];
3577 $post->$name = $vv;
3578 }
3579
3580 if(!in_array($kk, $allowed_meta)){
3581 continue;
3582 }
3583
3584 $meta_input[$kk] = stripslashes_deep($vv);
3585 }
3586
3587 if(isset($meta_input['_pagelayer_content'])){
3588 $meta_input['_pagelayer_content'] = base64_decode($meta_input['_pagelayer_content']);
3589 }
3590
3591 $post->meta_input = $meta_input;
3592 wp_update_post($post);
3593 }
3594 }
3595
3596 // Update customizer options
3597 function pagelayer_save_customizer_options($customizer_options){
3598 global $pagelayer;
3599
3600 // To load customizer params array
3601 if(empty($pagelayer->customizer_params)){
3602 pagelayer_load_shortcodes();
3603 }
3604
3605 $customizer_options = apply_filters( 'pagelayer_save_customizer_options', $customizer_options );
3606 $customizer_data = array();
3607 $customizer_option_data = array();
3608
3609 foreach($pagelayer->customizer_params as $ck => $cv){
3610 foreach($pagelayer->screens as $sk => $sv){
3611
3612 $screen = (!empty($sv) ? '_'.$sv : '');
3613 $screen_key = $ck.$screen;
3614
3615 // Save to pagelayer customizer mods
3616 if( empty($cv['option']) ){
3617 if( isset($customizer_options[$screen_key])){
3618 $customizer_data[$screen_key] = $customizer_options[$screen_key];
3619 }
3620 continue;
3621 }
3622
3623 $option_key = $cv['option'].$screen;
3624
3625 // Update option
3626 if( isset($customizer_options[$screen_key] ) ) {
3627 update_option( $option_key, $customizer_options[$screen_key]);
3628 continue;
3629 }
3630
3631 delete_option($option_key);
3632 }
3633 }
3634
3635 // Set Typography settings for global and current post type
3636 $posttype=array(
3637 '' => '', // Make this empty for global values
3638 'current' => $customizer_options['pagelayer_current_post_type']
3639 );
3640
3641 $typo = ['font-family', 'font-size', 'font-style', 'font-weight', 'font-variant', 'decoration-line', 'line-height', 'text-transform', 'text-spacing', 'word-spacing'];
3642
3643 foreach($posttype as $type => $tv){
3644
3645 foreach($pagelayer->css_settings as $set => $params){
3646
3647 foreach($pagelayer->screens as $sk => $sv){
3648
3649 $screen = (!empty($sv) ? '_'.$sv : '');
3650 $post_type = (!empty($tv) ? '_'.$tv : '');
3651 $post_key = (!empty($type) ? $type.'_' : '');
3652 $post_key_set = $post_key.$set;
3653
3654 // Create key as per customizer shortcode
3655 $key = $post_key_set.$screen;
3656
3657 // Create option keys for the global and current post type
3658 $option_setting = empty($params['key']) ? 'pagelayer_'.$set.'_css'.$post_type : $params['key'].$post_type;
3659
3660 $props = array(
3661 'color' => $post_key_set.'_color'.$screen,
3662 'padding' => $post_key_set.'_padding'.$screen,
3663 'margin' => $post_key_set.'_margin'.$screen,
3664 'background-color' => $post_key_set.'_background_color'.$screen,
3665 );
3666
3667 $globalsetting = array();
3668
3669 // Set Typography
3670 if(isset($customizer_options[$key])){
3671 foreach($customizer_options[$key] as $k => $v){
3672 if($v == 'Default' || empty($v)){
3673 unset($customizer_options[$key][$k]);
3674 }
3675
3676 // For sidebar, width default should not be saved
3677 if($set == 'sidebar' && $k == 'width' && $v == 20){
3678 unset($customizer_options[$key][$k]);
3679 }
3680
3681 $globalsetting[$key][$typo[$k]] = $customizer_options[$key][$k];
3682 unset($customizer_options[$key][$k]);
3683 }
3684 }
3685
3686 // Set other props with typography
3687 foreach($props as $pk => $pv){
3688
3689 if(!isset($customizer_options[$pv])){
3690 continue;
3691 }
3692
3693 $globalsetting[$key][$pk] = $customizer_options[$pv];
3694 unset($customizer_options[$pv]);
3695
3696 }
3697
3698 // Are we to save ?
3699 if(!empty($globalsetting[$key])){
3700 update_option($option_setting.$screen, $globalsetting[$key]);
3701 }else{
3702 delete_option($option_setting.$screen);
3703 }
3704
3705 }
3706
3707 }
3708 }
3709
3710 $customizer_data = apply_filters( 'pagelayer_customizer_options', $customizer_data, $customizer_options);
3711
3712 update_option('pagelayer_customizer_mods', $customizer_data);
3713 }
3714
3715 // Get customizer options values
3716 // return array to set customizer block attributes
3717 function pagelayer_get_customizer_options(){
3718 global $pagelayer, $post;
3719
3720 $options = array();
3721
3722 // To load customizer params array
3723 if(empty($pagelayer->customizer_params)){
3724 pagelayer_load_shortcodes();
3725 }
3726
3727 // Get values form options
3728 foreach($pagelayer->customizer_params as $ck => $cv){
3729
3730 if( empty($cv['option']) ){
3731 continue;
3732 }
3733
3734 $screens = array('desktop' => '');
3735
3736 if( !empty($cv['screen']) ){
3737 $screens = $pagelayer->screens;
3738 }
3739
3740 foreach($screens as $sk => $sv){
3741
3742 $screen = (!empty($sv) ? '_'.$sv : '');
3743 $screen_key = $cv['option'].$screen;
3744 $screen_ck = $ck.$screen;
3745
3746 // Get option value
3747 $c_option = get_option($screen_key);
3748
3749 if(empty($c_option)){
3750 continue;
3751 }
3752
3753 $options[$screen_ck] = $c_option;
3754 }
3755 }
3756
3757
3758 // Get values from pagelayer mods
3759 $mods = get_option('pagelayer_customizer_mods');
3760
3761 if(!empty($mods)){
3762 $options = array_merge($options, $mods);
3763 }
3764
3765 $posttype=array(
3766 '' => '',
3767 'current' => $post->post_type
3768 );
3769
3770 $typo = ['font-family', 'font-size', 'font-style', 'font-weight', 'font-variant', 'decoration-line', 'line-height', 'text-transform', 'text-spacing', 'word-spacing'];
3771
3772 foreach($posttype as $type => $tv){
3773
3774 foreach($pagelayer->css_settings as $set => $params){
3775
3776 foreach($pagelayer->screens as $sk => $sv){
3777
3778 $screen = (!empty($sv) ? '_'.$sv : '');
3779 $postprefix = (!empty($tv) ? '_'.$tv : '');
3780 $postk = (!empty($type) ? $type.'_' : '');
3781 $post_key_set = $postk.$set;
3782
3783 // Create key as per customizer shortcode
3784 $key = $post_key_set.$screen;
3785
3786 // Create option keys for the global and current post type
3787 $setting = empty($params['key']) ? 'pagelayer_'.$set.'_css'.$postprefix : $params['key'].$postprefix;
3788
3789 $props = array(
3790 'color' => $post_key_set.'_color'.$screen,
3791 'padding' => $post_key_set.'_padding'.$screen,
3792 'margin' => $post_key_set.'_margin'.$screen,
3793 'background-color' => $post_key_set.'_background_color'.$screen,
3794 );
3795
3796 $optarray = get_option($setting.$screen);
3797
3798 if(!empty($optarray)){
3799
3800 // Get Typography
3801 foreach($typo as $tk => $tv){
3802
3803 $tval = '';
3804
3805 if(isset($optarray[$tv])){
3806 $tval = $optarray[$tv];
3807 }
3808
3809 $options[$key][$tk] = $tval;
3810 }
3811
3812 foreach($props as $pk => $pv){
3813 if(empty( $optarray[$pk])){
3814 continue;
3815 }
3816
3817 $options[$pv] = $optarray[$pk];
3818 }
3819 }
3820 }
3821 }
3822 }
3823
3824 $options = apply_filters( 'pagelayer_get_customizer_options', $options);
3825
3826 return $options;
3827 }
3828
3829 // Sanitize style props for colors and fons
3830 function pagelayer_load_global_palette(){
3831 global $pagelayer;
3832
3833 // Default global colors
3834 $pagelayer->global_colors = array(
3835 'primary' => array(
3836 'title' => 'Primary',
3837 'value' => '#007bff',
3838 ),
3839 'secondary' => array(
3840 'title' => 'Secondary',
3841 'value' => '#6c757d',
3842 ),
3843 'text' => array(
3844 'title' => 'Text',
3845 'value' => '#1d1d1d',
3846 ),
3847 'accent' => array(
3848 'title' => 'Accent',
3849 'value' => '#61ce70',
3850 ),
3851 );
3852
3853 // Global color
3854 $global_color = get_option('pagelayer_global_colors');
3855
3856 if(!empty($global_color)){
3857 $pagelayer->global_colors = json_decode($global_color, true);
3858 }
3859
3860 // Default global fonts
3861 $pagelayer->global_fonts = array(
3862 'primary' => array(
3863 'title' => 'Primary',
3864 'value' => $pagelayer->default_font_styles(),
3865 ),
3866 'secondary' => array(
3867 'title' => 'Secondary',
3868 'value' => $pagelayer->default_font_styles(array('font-family' => 'Roboto')),
3869 ),
3870 'text' => array(
3871 'title' => 'Text',
3872 'value' => $pagelayer->default_font_styles(array('font-family' => 'Montserrat')),
3873 ),
3874 'accent' => array(
3875 'title' => 'Accent',
3876 'value' => $pagelayer->default_font_styles(array('font-family' => 'Poppins')),
3877 ),
3878 );
3879
3880 // Global font
3881 $global_font = get_option('pagelayer_global_fonts');
3882
3883 if(!empty($global_font)){
3884 $pagelayer->global_fonts = json_decode($global_font, true);
3885 }
3886 }
3887
3888 // Get global colors
3889 function pagelayer_sanitize_global_color($val){
3890 global $pagelayer;
3891
3892 if(!is_string($val) || $val[0] != '$'){
3893 return $val;
3894 }
3895
3896 $gkey = substr($val, 1);
3897 $gcolor = isset($pagelayer->global_colors[$gkey]) ? $gkey : 'primary';
3898 $val = 'var(--pagelayer-color-'.$gcolor.')';
3899
3900 return $val;
3901 }
3902
3903 // Sanitize style props for colors and fons
3904 function pagelayer_sanitize_global_style($val, $val_desk = '', $mode = 'desktop'){
3905 global $pagelayer;
3906
3907 // Sanitize Global background color
3908 if( !empty($val['background-color']) && $val['background-color'][0] == '$'){
3909 $val['background-color'] = pagelayer_sanitize_global_color($val['background-color']);
3910 }
3911
3912 // Sanitize Global color
3913 if( !empty($val['color']) && $val['color'][0] == '$'){
3914 $val['color'] = pagelayer_sanitize_global_color($val['color']);
3915 }
3916
3917 // Not set global for typo
3918 if(empty($val['global-font']) && empty($val_desk['global-font'])){
3919 return $val;
3920 }
3921
3922 $_desk_global = false;
3923
3924 if(empty($val['global-font'])){
3925 $font_key = @$val_desk['global-font'];
3926 $_desk_global = true;
3927 }else{
3928 $font_key = $val['global-font'];
3929 unset($val['global-font']);
3930 }
3931
3932 if(empty($font_key)){
3933 return $val;
3934 }
3935
3936 if(!isset($pagelayer->global_fonts[$font_key])){
3937 $font_key = 'primary';
3938 }
3939
3940 $_val = [];
3941
3942 // Apply global typo
3943 foreach($pagelayer->typo_props as $typo_key){
3944
3945 if(!empty($val[$typo_key])){
3946 continue;
3947 }
3948
3949 $global_val = $pagelayer->global_fonts[$font_key]['value'];
3950
3951 if( empty($global_val[$typo_key]) || (is_array($global_val[$typo_key]) && empty($global_val[$typo_key][$mode])) || (!is_array($global_val[$typo_key]) && !empty($_desk_global) && $mode != 'desktop') ){
3952 continue;
3953 }
3954
3955 $_val[$typo_key] = 'var(--pagelayer-font-'.$font_key.'-'.$typo_key.')';
3956 }
3957
3958 // This array contains other values like margin padding so we merge the array
3959 $val = empty($val) ? array() : $val;
3960 $val = array_merge($val, $_val);
3961 return $val;
3962 }
3963
3964 //Check an empty array
3965 function pagelayer_is_empty_array($arr){
3966
3967 foreach ($arr as $key => $value) {
3968 if (trim($value) !== '') return false;
3969 }
3970
3971 return true;
3972 }
3973
3974 // Pagelayer load font family
3975 function pagelayer_load_font_family($font, $font_weight='', $font_style=''){
3976 global $pagelayer;
3977
3978 // Load global fonts
3979 if(strripos($font, 'var(') !== false){
3980 $matches = [];
3981 preg_match('/(var\(--pagelayer-font-)(\w+)(-font-family\))/i', $font, $matches);
3982 $font_key = @$matches[2];
3983 $font = @$pagelayer->global_fonts[$font_key]['value']['font-family'];
3984 }
3985
3986 // Load global fonts weight
3987 if(!empty($font_weight) && strripos($font_weight, 'var(') !== false){
3988 $matches = [];
3989 preg_match('/(var\(--pagelayer-font-)(\w+)(-font-weight\))/i', $font_weight, $matches);
3990 $font_key = @$matches[2];
3991
3992 // Convert in string
3993 $font_weight = @$pagelayer->global_fonts[$font_key]['value']['font-weight'];
3994 }
3995
3996 // Load global fonts style
3997 if(!empty($font_style) && strripos($font_style, 'var(') !== false){
3998 $matches = [];
3999 preg_match('/(var\(--pagelayer-font-)(\w+)(-font-style\))/i', $font_style, $matches);
4000 $font_key = @$matches[2];
4001
4002 // Convert in string
4003 $font_style = @$pagelayer->global_fonts[$font_key]['value']['font-style'];
4004 }
4005
4006 if(empty($font)){
4007 return;
4008 }
4009
4010 $font_weights = array('400' =>'400');
4011 $font_style = empty($font_style) ? 'normal' : $font_style;
4012 $font_style = in_array($font_style, ['italic', 'oblique']) ? 'i' : '';
4013
4014 if(!empty($font_weight)){
4015
4016 if(!is_array($font_weight)){
4017 $font_weight = array($font_weight);
4018 }
4019
4020 foreach($font_weight as $weight){
4021 $font_weights[$weight.$font_style] = $weight.$font_style;
4022 }
4023 }
4024
4025 foreach($font_weights as $fkey => $fvalue){
4026 $pagelayer->runtime_fonts[$font][$fkey] = $fvalue;
4027 }
4028
4029 }
4030
4031 function pagelayer_update_plugin_notice(){
4032 if(defined('SOFTACULOUS_PLUGIN_UPDATE_NOTICE')){
4033 return;
4034 }
4035
4036 $to_update_plugins = apply_filters('softaculous_plugin_update_notice', []);
4037
4038 if(empty($to_update_plugins)){
4039 return;
4040 }
4041
4042 /* translators: %1$s is replaced with a "string" of name of plugins, and %2$s is replaced with "string" which can be "is" or "are" based on the count of the plugin */
4043 $msg = sprintf(__('New versions of %1$s %2$s available. Updating ensures better performance, security, and access to the latest features.', 'pagelayer'), '<b>'.esc_html(implode(', ', $to_update_plugins)).'</b>', (count($to_update_plugins) > 1 ? 'are' : 'is')) . ' <a class="button button-primary" href='.esc_url(admin_url('plugins.php?plugin_status=upgrade')).'>Update Now</a>';
4044
4045 define('SOFTACULOUS_PLUGIN_UPDATE_NOTICE', true); // To make sure other plugins don't return a Notice
4046 echo '<div class="notice notice-info is-dismissible" id="pagelayer-plugin-update-notice">
4047 <p>'.$msg. '</p>
4048 </div>';
4049
4050 wp_register_script('pagelayer-update-notice', '', ['jquery'], '', true);
4051 wp_enqueue_script('pagelayer-update-notice');
4052 wp_add_inline_script('pagelayer-update-notice', 'jQuery("#pagelayer-plugin-update-notice").on("click", function(e){
4053 let target = jQuery(e.target);
4054
4055 if(!target.hasClass("notice-dismiss")){
4056 return;
4057 }
4058
4059 var data;
4060
4061 // Hide it
4062 jQuery("#pagelayer-plugin-update-notice").hide();
4063
4064 // Save this preference
4065 jQuery.post("'.admin_url('admin-ajax.php?action=pagelayer_close_update_notice').'&pagelayer_nonce='.wp_create_nonce('pagelayer_promo_nonce').'", data, function(response) {
4066 //alert(response);
4067 });
4068 });');
4069 }
4070
4071 function pagelayer_update_plugin_notice_filter($plugins = []){
4072 $plugins['pagelayer/pagelayer.php'] = 'Pagelayer';
4073 return $plugins;
4074 }
4075
4076 function pagelayer_is_comment_mode(){
4077
4078 if(file_exists(PAGELAYER_DIR.'/comment_mode.php') && !empty($_REQUEST['cmode'])){
4079 include_once(PAGELAYER_DIR.'/comment_mode.php');
4080 return true;
4081 }
4082
4083 return false;
4084 }
4085
4086 function pagelayer_esc_crlf($value){
4087
4088 // Remove CRLF to prevent header injection
4089 $value = str_replace(array("\r", "\n", "%0a", "%0d"), '', $value);
4090
4091 // Trim spaces
4092 $value = trim($value);
4093
4094 return $value;
4095 }