PluginProbe
Page Builder: Pagelayer – Drag and Drop website builder / 2.2.1
Page Builder: Pagelayer – Drag and Drop website builder v2.2.1
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 / init.php

init.php in Page Builder: Pagelayer – Drag and Drop website builder 2.2.1, at init.php

1,733 lines 53.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 // We need the ABSPATH
4 if (!defined('ABSPATH')) exit;
5
6 define('PAGELAYER_BASE', plugin_basename(PAGELAYER_FILE));
7 define('PAGELAYER_PREMIUM_BASE', 'pagelayer-pro/pagelayer-pro.php');
8 define('PAGELAYER_VERSION', '2.2.1');
9 define('PAGELAYER_DIR', dirname(PAGELAYER_FILE));
10 define('PAGELAYER_SLUG', 'pagelayer');
11 define('PAGELAYER_URL', plugins_url('', PAGELAYER_FILE));
12 define('PAGELAYER_CSS', PAGELAYER_URL.'/css');
13 define('PAGELAYER_JS', PAGELAYER_URL.'/js');
14 define('PAGELAYER_PRO_PRICE_URL', 'https://pagelayer.com/pricing?from=plugin');
15 define('PAGELAYER_WWW_URL', 'https://pagelayer.com/');
16 define('PAGELAYER_DOCS', 'https://pagelayer.com/docs/');
17 define('PAGELAYER_API', 'https://api.pagelayer.com/');
18 define('PAGELAYER_AI_API', 'https://s2.softaculous.com/a/softai/ai.php');
19 define('PAGELAYER_SC_PREFIX', 'pl');
20 define('PAGELAYER_YOUTUBE_BG', 'https://www.youtube.com/watch?v=Csa6rvCWmLU');
21 define('PAGELAYER_CMS_NAME', defined('SITEPAD') ? 'SitePad' : 'WordPress');
22 define('PAGELAYER_BLOCK_PREFIX', defined('SITEPAD') ? 'sp' : 'wp');
23 define('PAGELAYER_CMS_DIR_PREFIX', defined('SITEPAD') ? 'site' : 'wp');
24 define('PAGELAYER_DEV', file_exists(dirname(__FILE__).'/dev.php') ? 1 : 0);
25 define('PAGELAYER_FONT_POST_TYPE', 'pagelayer-fonts');
26
27 include_once(PAGELAYER_DIR.'/main/functions.php');
28 include_once(PAGELAYER_DIR.'/main/class.php');
29 include_once(PAGELAYER_DIR.'/main/ai-controller.php');
30
31 function pagelayer_died(){
32 print_r(error_get_last());
33 }
34 //register_shutdown_function('pagelayer_died');
35
36 // Ok so we are now ready to go
37 register_activation_hook(PAGELAYER_FILE, 'pagelayer_activation');
38
39 // Is called when the ADMIN enables the plugin
40 function pagelayer_activation(){
41
42 global $wpdb;
43
44 $sql = array();
45
46 /*$sql[] = "DROP TABLE IF EXISTS `".$wpdb->prefix."pagelayer_logs`";
47
48 foreach($sql as $sk => $sv){
49 $wpdb->query($sv);
50 }*/
51
52 add_option('pagelayer_version', PAGELAYER_VERSION);
53 add_option('pagelayer_options', array());
54
55 }
56
57 // Checks if we are to update ?
58 function pagelayer_update_check(){
59
60 global $wpdb;
61
62 $sql = array();
63 $current_version = get_option('pagelayer_version');
64 $version = (int) str_replace('.', '', $current_version);
65
66 // No update required
67 if($current_version == PAGELAYER_VERSION){
68 return true;
69 }
70
71 // Is it first run ?
72 if(empty($current_version)){
73
74 // Reinstall
75 pagelayer_activation();
76
77 // Trick the following if conditions to not run
78 $version = (int) str_replace('.', '', PAGELAYER_VERSION);
79
80 }
81
82 // Backward compatibility of global typography
83 if(version_compare($current_version, '1.7.0', '<') && !defined('SITEPAD')){
84
85 // Set the array
86 $_pagelayer = new PageLayer();
87
88 $post_types = array('' => __('Global'));
89 $exclude = [ 'attachment', 'pagelayer-template' ];
90 $pt_objects = get_post_types(['public' => true,], 'objects');
91
92 foreach( $pt_objects as $pt_slug => $type ){
93
94 if ( in_array( $pt_slug, $exclude ) ) {
95 continue;
96 }
97
98 $post_types[$pt_slug] = $type->labels->name;
99 }
100
101 foreach($post_types as $sk => $sv){
102
103 $post_type = empty($sk) ? '' : '_'.$sk;
104
105 // Load CSS settings
106 foreach($_pagelayer->css_settings as $k => $params){
107
108 foreach($_pagelayer->screens as $sck => $scv){
109 $suffix = (!empty($scv) ? '_'.$scv : '');
110 $setting = empty($params['key']) ? 'pagelayer_'.$k.'_css'.$post_type : $params['key'].$post_type;
111
112 $tmp = get_option($setting.$suffix);
113
114 if(empty($tmp) || empty($tmp['global-font'])){
115 continue;
116 }
117
118 // Do empty typo if global set
119 foreach($tmp as $tk => $tv){
120
121 if(!in_array($tk, $_pagelayer->typo_props)){
122 continue;
123 }
124
125 $tmp[$tk] = '';
126 }
127
128 // Update settings
129 update_option($setting.$suffix, $tmp);
130 }
131 }
132 }
133 }
134
135 // Show changelog notice
136 if(version_compare($current_version, '1.8.1', '<') && !defined('SITEPAD')){
137 update_option('pagelayer_changelog_notice', 1);
138 }
139
140 // Save the new Version
141 update_option('pagelayer_version', PAGELAYER_VERSION);
142
143 }
144
145 // Add the action to load the plugin
146 add_action('plugins_loaded', 'pagelayer_load_plugin', 9);
147
148 // The function that will be called when the plugin is loaded
149 function pagelayer_load_plugin(){
150
151 // Init MCP Abilities
152 add_action('wp_abilities_api_categories_init', 'pagelayer_wp_abilities_api_categories_init');
153 add_action('wp_abilities_api_init', 'pagelayer_wp_abilities_api_init');
154
155 global $pagelayer;
156
157 // Check if the installed version is outdated
158 pagelayer_update_check();
159
160 // Set the array
161 $pagelayer = new PageLayer();
162
163 if(empty($pagelayer->BRAND_TEXT)){
164 $pagelayer->BRAND_TEXT = 'Pagelayer';
165 }
166
167 if(empty($pagelayer->LOGO)){
168 $pagelayer->LOGO = PAGELAYER_URL.'/images/pagelayer-logo-40.png';
169 }
170
171 // Is there any ACTION set ?
172 $pagelayer->action = pagelayer_optreq('pagelayer-action');
173
174 $tablet_breakpoint = get_option('pagelayer_tablet_breakpoint');
175 $mobile_breakpoint = get_option('pagelayer_mobile_breakpoint');
176
177 // Load settings
178 $pagelayer->settings['post_types'] = empty(get_option('pl_support_ept')) ? ['post', 'page'] : get_option('pl_support_ept');
179 $pagelayer->settings['enable_giver'] = get_option('pagelayer_enable_giver');
180 $pagelayer->settings['max_width'] = (int) (empty(get_option('pagelayer_content_width')) ? 1170 : get_option('pagelayer_content_width'));
181 $pagelayer->settings['tablet_breakpoint'] = (int) (empty($tablet_breakpoint) ? 780 : $tablet_breakpoint);
182 $pagelayer->settings['mobile_breakpoint'] = (int) (empty($mobile_breakpoint) ? 480 : $mobile_breakpoint);
183 $pagelayer->settings['sidebar'] = get_option('pagelayer_sidebar');
184 $pagelayer->settings['body_font'] = get_option('pagelayer_body_font');
185 $pagelayer->settings['color'] = get_option('pagelayer_color');
186
187 // Any custom types
188 $pagelayer->settings['post_types'] = apply_filters('pagelayer_supported_post_type', $pagelayer->settings['post_types']);
189
190 // Load the language
191 load_plugin_textdomain('pagelayer', false, PAGELAYER_SLUG.'/languages/');
192
193 // Load our array for builder
194 pagelayer_builder_array();
195
196 // Its premium
197 if(!defined('PAGELAYER_PREMIUM')){
198
199 // Show the promo
200 pagelayer_maybe_promo([
201 'after' => 1,// In days
202 'interval' => 30,// In days
203 'pro_url' => PAGELAYER_PRO_PRICE_URL,
204 'rating' => 'https://wordpress.org/plugins/pagelayer/#reviews',
205 'twitter' => 'https://twitter.com/pagelayer?status='.rawurlencode('I love #Pagelayer Site Builder by @pagelayer team for my #WordPress site - '.home_url()),
206 'facebook' => 'https://www.facebook.com/pagelayer',
207 'website' => PAGELAYER_WWW_URL,
208 'image' => PAGELAYER_URL.'/images/pagelayer-logo-256.png'
209 ]);
210
211 }
212
213 // Are we to disable the getting started promo
214 if(current_user_can('activate_plugins') && isset($_GET['pagelayer-getting-started']) && (int)$_GET['pagelayer-getting-started'] == 0){
215 check_ajax_referer('pagelayer_getting_started_nonce', 'pagelayer_nonce');
216 update_option('pagelayer_getting_started', time());
217 die('DONE');
218 }
219
220 // === Plugin Update Notice === //
221 if(is_admin() && current_user_can('manage_options')){
222 $plugin_update_notice = get_option('softaculous_plugin_update_notice', []);
223 $available_update_list = get_site_transient('update_plugins');
224 $plugin_path_slug = 'pagelayer/pagelayer.php';
225
226 if(
227 !empty($available_update_list) &&
228 is_object($available_update_list) &&
229 !empty($available_update_list->response) &&
230 !empty($available_update_list->response[$plugin_path_slug]) &&
231 (empty($plugin_update_notice) || empty($plugin_update_notice[$plugin_path_slug]) || (!empty($plugin_update_notice[$plugin_path_slug]) &&
232 version_compare($plugin_update_notice[$plugin_path_slug], $available_update_list->response[$plugin_path_slug]->new_version, '<')))
233 ){
234 add_action('admin_notices', 'pagelayer_update_plugin_notice');
235 add_filter('softaculous_plugin_update_notice', 'pagelayer_update_plugin_notice_filter');
236 }
237 }
238 // === Plugin Update Notice End === //
239
240 // Show the getting started video option
241 $seen = get_option('pagelayer_getting_started');
242 if(empty($seen) && !empty($_GET['page']) && $_GET['page'] != 'pagelayer_getting_started'){
243 add_action('admin_notices', 'pagelayer_getting_started_notice');
244 }
245
246 // Are we to disable the changelog notice
247 if(current_user_can('activate_plugins') && isset($_GET['pagelayer-changelog-notice']) && (int)$_GET['pagelayer-changelog-notice'] == 0){
248 check_ajax_referer('pagelayer_changelog_nonce', 'pagelayer_nonce');
249 update_option('pagelayer_changelog_notice', 0);
250 die('DONE');
251 }
252
253 // Show the changelog notice
254 $changelog = get_option('pagelayer_changelog_notice');
255 if(!empty($changelog)){
256 add_action('admin_notices', 'pagelayer_show_changelog_notice');
257 }
258
259 include_once(PAGELAYER_DIR.'/main/customizer.php');
260
261 if(class_exists('WooCommerce')){
262 include_once(PAGELAYER_DIR.'/main/woocommerce.php');
263 }
264
265 }
266
267 // This adds the left menu in WordPress Admin page
268 add_action('admin_menu', 'pagelayer_admin_menu', 5);
269
270 // Shows the admin menu of Pagelayer
271 add_action('admin_enqueue_scripts', 'pagelayer_admin_enqueue_scripts');
272 function pagelayer_admin_enqueue_scripts($hook){
273 global $typenow;
274
275 if(strpos($hook, "pagelayer") === false && $typenow !== 'pagelayer-template' && $typenow !== 'pagelayer-fonts'){
276 return;
277 }
278
279 wp_enqueue_script("pagelayer-admin", PAGELAYER_JS."/pagelayer-admin.js", array("jquery"), PAGELAYER_VERSION . '-' . time());
280 wp_enqueue_script("pagelayer-vanilla-picker", PAGELAYER_JS."/vanilla-picker.min.js", array(), PAGELAYER_VERSION);
281 wp_enqueue_style("pagelayer-admin", PAGELAYER_CSS."/pagelayer-admin.css", array(), PAGELAYER_VERSION);
282
283 wp_localize_script("pagelayer-admin", "pagelayer_admin_data", array(
284 'version' => PAGELAYER_VERSION,
285 'logo' => esc_url(PAGELAYER_URL . '/images/pagelayer-logo-40.png'),
286 'is_premium' => defined('PAGELAYER_PREMIUM') ? 1 : 0,
287 'pricing_url' => PAGELAYER_PRO_PRICE_URL,
288 'docs_url' => esc_url(PAGELAYER_DOCS),
289 'admin_url' => admin_url(),
290 'is_sitepad' => defined('SITEPAD') ? 1 : 0,
291 ));
292
293 if(strpos($hook, "pagelayer_ai_agents") !== false){
294 include_once(PAGELAYER_DIR.'/main/abilities.php');
295 wp_enqueue_style("pagelayer-abilities", PAGELAYER_CSS."/pagelayer-abilities.css", array(), PAGELAYER_VERSION);
296 wp_enqueue_script("pagelayer-abilities", PAGELAYER_JS."/pagelayer-abilities.js", array("jquery"), PAGELAYER_VERSION, true);
297
298 $site_url = trailingslashit(rtrim(home_url(), '/'));
299 $username = function_exists('wp_get_current_user') ? wp_get_current_user()->user_login : '';
300 $mcp_server_url = $site_url . ltrim(Pagelayer_Abilities::$MCP_SERVER_ENDPOINT, '/');
301
302 wp_localize_script("pagelayer-abilities", "pagelayer_abilities_data", array(
303 'siteUrl' => $site_url,
304 'mcpServerUrl' => $mcp_server_url,
305 'username' => $username,
306 'nonce' => wp_create_nonce('pagelayer_mcp_nonce')
307 ));
308 }
309 }
310
311 function pagelayer_admin_menu() {
312
313 global $wp_version, $pagelayer;
314
315 $capability = 'activate_plugins';// TODO : Capability for accessing this page
316
317 // Add the menu page
318 add_menu_page(__('Pagelayer Editor'), __('Pagelayer'), $capability, 'pagelayer', 'pagelayer_page_handler', PAGELAYER_URL.'/images/pagelayer-logo-19.png');
319
320 // Settings Page
321 add_submenu_page('pagelayer', __('Pagelayer Editor'), __('Settings'), $capability, 'pagelayer', 'pagelayer_page_handler');
322
323 // Meta Settings Page
324 add_submenu_page('admin.php', __('Meta Settings'), __('Meta Settings'), 'edit_posts', 'pagelayer_meta_setting', 'pagelayer_meta_handler');
325
326 // Add New Template Wizard Page
327 add_submenu_page('admin.php', __('Add New Template'), __('Add New Template'), $capability, 'pagelayer_template_wizard', 'pagelayer_builder_template_wizard');
328
329 // Export Template Page (accessed from buttons/links)
330 add_submenu_page('admin.php', __('Export Theme'), __('Export Theme'), $capability, 'pagelayer_template_export', 'pagelayer_builder_export');
331
332 // Import Template Page (accessed from buttons/links)
333 add_submenu_page('admin.php', __('Import Theme'), __('Import Theme'), $capability, 'pagelayer_import', 'pagelayer_import_page');
334
335 // UI Settings
336 add_submenu_page('pagelayer', __('Website Settings'), __('Website Settings'), $capability, 'pagelayer_website_settings', 'pagelayer_website_page');
337
338 // Add new template
339 add_submenu_page('pagelayer', __('Theme Templates'), __('Theme Templates'), $capability, 'edit.php?post_type=pagelayer-template');
340
341 // Add new template Link
342 //add_submenu_page('pagelayer', __('Add New Template'), __('Add New Template'), $capability, 'edit.php?post_type=pagelayer-template#new');
343
344 // Register Tools Submenu page under pagelayer
345 add_submenu_page('pagelayer', __('Tools'), __('Tools'), $capability, 'pagelayer_tools', 'pagelayer_tools_page_handler');
346
347 // AI Agents Connection
348 add_submenu_page('pagelayer', __('AI Agents', 'pagelayer'), __('AI Agents', 'pagelayer') . ' <span style="vertical-align:middle;background:#d63638;font-size:9px;padding:0 6px;border-radius:10px;line-height:18px;color:#fff;">New!</span>' , $capability, 'pagelayer_ai_agents', 'pagelayer_ai_agents_page_handler');
349
350 // Getting Started
351 add_submenu_page('pagelayer', __('Getting Started'), __('Getting Started'), $capability, 'pagelayer_getting_started', 'pagelayer_getting_started');
352
353 // Its Free
354 if(!defined('PAGELAYER_PREMIUM')){
355
356 // Go Pro link
357 add_submenu_page('pagelayer', __('Pagelayer Go Pro'), __('Go Pro'), $capability, PAGELAYER_PRO_PRICE_URL);
358
359 }else{
360
361 // License Page
362 add_submenu_page('pagelayer', __('Pagelayer License'), __('License'), $capability, 'pagelayer_license', 'pagelayer_license_page');
363
364 }
365
366 // Replace Media
367 add_submenu_page('admin.php', __('Replace media', 'pagelayer'), __('Replace media', 'pagelayer'), 'upload_files', 'pagelayer_replace_media', 'pagelayer_replace_media');
368
369 }
370
371 // This function will handle the Settings Pages in Pagelayer
372 function pagelayer_website_page(){
373
374 global $wp_version, $pagelayer;
375
376 include_once(PAGELAYER_DIR.'/main/website.php');
377
378 pagelayer_website_settings();
379
380 }
381
382 function pagelayer_wp_abilities_api_categories_init(){
383 include_once(PAGELAYER_DIR.'/main/abilities.php');
384 include_once(PAGELAYER_DIR.'/main/abilitiesregister.php');
385 if(class_exists('Pagelayer_Abilities_Register')){
386 Pagelayer_Abilities_Register::register_categories();
387 }
388 }
389
390 function pagelayer_wp_abilities_api_init(){
391 include_once(PAGELAYER_DIR.'/main/abilities.php');
392 include_once(PAGELAYER_DIR.'/main/abilitiesregister.php');
393 if(class_exists('Pagelayer_Abilities_Register')){
394 Pagelayer_Abilities_Register::register_abilities();
395 }
396 }
397
398 // This function handles the AI Agents page
399 function pagelayer_ai_agents_page_handler(){
400 include_once(PAGELAYER_DIR.'/main/abilities.php');
401 Pagelayer_Abilities::render_page();
402 }
403
404 // Getting Started
405 function pagelayer_getting_started(){
406
407 global $wp_version, $pagelayer;
408
409 update_option('pagelayer_getting_started', time());
410
411 include_once(PAGELAYER_DIR.'/main/getting_started.php');
412
413 }
414
415 // This function will handle the post_metas Pages in Pagelayer
416 function pagelayer_meta_handler(){
417
418 global $wp_version, $pagelayer;
419
420 include_once(PAGELAYER_DIR.'/main/post_metas.php');
421
422 pagelayer_meta_page();
423
424 }
425
426 // Pagelayer post meta page view handler
427 add_action('admin_enqueue_scripts', 'pagelayer_post_meta_page');
428 function pagelayer_post_meta_page() {
429
430 // Set Current screen
431 $screen = get_current_screen();
432 $meta_id = 'admin_page_pagelayer_meta_setting';
433
434 if( !is_admin() || trim($screen->id) != $meta_id ) {
435 return;
436 }
437
438 if(!isset($_REQUEST['post'])){
439 return;
440 }
441
442 // Remove all the notice hooks
443 remove_all_actions('admin_notices');
444 remove_all_actions('all_admin_notices');
445
446 $_REQUEST['post'] = (int) $_REQUEST['post'];
447 $post = get_post( $_REQUEST['post'] );
448
449 // Enqueue Scripts
450 wp_enqueue_script( 'post' );
451
452 // Is support media
453 $thumbnail_support = current_theme_supports( 'post-thumbnails', $post->post_type ) && post_type_supports( $post->post_type, 'thumbnail' );
454 if ( ! $thumbnail_support && 'attachment' === $post->post_type && $post->post_mime_type ) {
455 if ( wp_attachment_is( 'audio', $post ) ) {
456 $thumbnail_support = post_type_supports( 'attachment:audio', 'thumbnail' ) || current_theme_supports( 'post-thumbnails', 'attachment:audio' );
457 } elseif ( wp_attachment_is( 'video', $post ) ) {
458 $thumbnail_support = post_type_supports( 'attachment:video', 'thumbnail' ) || current_theme_supports( 'post-thumbnails', 'attachment:video' );
459 }
460 }
461
462 if ( $thumbnail_support ) {
463 add_thickbox();
464 wp_enqueue_media( array( 'post' => $post->ID ) );
465 }
466
467 $meta_box_url = admin_url( 'post.php' );
468 $meta_box_url = add_query_arg(
469 array(
470 'post' => $post->ID,
471 'action' => 'editpost',
472 ),
473 $meta_box_url
474 );
475
476 echo '<style>
477 .'.$meta_id.' #adminmenumain, .'.$meta_id.' #wpfooter, .'.$meta_id.' #wpadminbar{
478 display:none;
479 }
480 .'.$meta_id.' #wpcontent{
481 margin:auto;
482 }
483 </style>
484
485 <script type="text/javascript">
486
487 function pagelayer_post_edit(jEle, e){
488
489 e.preventDefault();
490 var formData = new FormData( jQuery(jEle)[0] );
491
492 jQuery.ajax({
493 url: "'.$meta_box_url.'",
494 type: "POST",
495 data: formData,
496 processData: false,
497 contentType: false,
498 cache:false,
499 success:function(result){
500 //window.location.reload();
501 alert("Post meta has been updated successfully !");
502 },
503 error:function(result){
504 alert("There is an error while updating post meta !");
505 }
506 });
507 }
508
509 </script>';
510
511 }
512
513 // Update post meta via gutenberg handler
514 add_filter('sanitize_post_meta_pagelayer_header_code', 'pagelayer_sanitize_postmeta', 10, 2);
515 add_filter('sanitize_post_meta_pagelayer_body_open_code', 'pagelayer_sanitize_postmeta', 10, 2);
516 add_filter('sanitize_post_meta_pagelayer_footer_code', 'pagelayer_sanitize_postmeta', 10, 2);
517 function pagelayer_sanitize_postmeta( $meta_value, $meta_key ) {
518
519 // Sanitize Header, body and footer code
520 if(
521 in_array( $meta_key, array( 'pagelayer_header_code', 'pagelayer_body_open_code', 'pagelayer_footer_code' ) ) &&
522 !pagelayer_user_can_add_js_content()
523 ){
524 return sanitize_textarea_field($meta_value);
525 }
526
527 return $meta_value;
528 }
529
530 // Pre post save handler
531 add_filter( 'content_save_pre', 'pagelayer_content_save_pre' );
532 function pagelayer_content_save_pre($content){
533
534 if(!pagelayer_user_can_add_js_content() && strpos($content, '[') !== false){
535 $content = pagelayer_sanitize_shortcode_atts($content);
536 }
537
538 if(pagelayer_user_can_add_js_content() || !pagelayer_has_blocks($content)){
539 return $content;
540 }
541
542 $blocks = parse_blocks( wp_unslash($content) );
543 $output = '';
544
545 foreach ( $blocks as $block ) {
546
547 // Sanitize Pagelayer blocks at any depth, they can be nested inside
548 // any other block
549 $output .= serialize_block( pagelayer_sanitize_block_tree( $block ) );
550 }
551
552 return wp_slash($output);
553 }
554
555 // On post save handler
556 add_action('save_post', 'pagelayer_save_post', 10, 3);
557 function pagelayer_save_post( $post_id, $post, $update ) {
558
559 if( !isset($_REQUEST['is_pagelayer_editor']) || !pagelayer_user_can_edit($post_id)){
560 return;
561 }
562
563 check_admin_referer('update-post_' . $post_id);
564
565 // Save Header, body and footer code
566 $header_code = !empty($_REQUEST['pagelayer_header_code']) ? $_REQUEST['pagelayer_header_code'] : '' ;
567 $body_code = !empty($_REQUEST['pagelayer_body_open_code']) ? $_REQUEST['pagelayer_body_open_code'] : '' ;
568 $footer_code = !empty($_REQUEST['pagelayer_footer_code']) ? $_REQUEST['pagelayer_footer_code'] : '' ;
569
570 // Set Custom header, body and footer code
571 if(!empty($header_code)){
572 update_post_meta($post_id, 'pagelayer_header_code', $header_code);
573 }else{
574 delete_post_meta($post_id, 'pagelayer_header_code');
575 }
576
577 if(!empty($body_code)){
578 update_post_meta($post_id, 'pagelayer_body_open_code', $body_code);
579 }else{
580 delete_post_meta($post_id, 'pagelayer_body_open_code');
581 }
582
583 if(!empty($footer_code)){
584 update_post_meta($post_id, 'pagelayer_footer_code', $footer_code);
585 }else{
586 delete_post_meta($post_id, 'pagelayer_footer_code');
587 }
588
589 }
590
591 // This function will handle the Settings Pages in Pagelayer
592 function pagelayer_page_handler(){
593
594 global $wp_version, $pagelayer;
595
596 include_once(PAGELAYER_DIR.'/main/settings.php');
597
598 pagelayer_settings_page();
599
600 }
601
602 function pagelayer_tools_page_handler(){
603 global $wp_version, $pagelayer, $pagelayer_header_printed, $pagelayer_footer_printed;
604
605 include_once(PAGELAYER_DIR.'/main/settings.php');
606
607 // Render the single master Pagelayer Tools page header
608 pagelayer_page_header(__('Tools', 'pagelayer'));
609
610 // 1. Add New Template Tool Panel
611 echo '<div id="add_new_template" class="pagelayer-tab-panel">';
612 if (function_exists('pagelayer_builder_template_wizard')) {
613 $pagelayer_footer_printed = true; // Mute inner footer
614 pagelayer_builder_template_wizard();
615 $pagelayer_footer_printed = false; // Reset
616 }
617 echo '</div>';
618
619 // 2. Export Theme Tool Panel (Premium only)
620 if(defined('PAGELAYER_PREMIUM')){
621 echo '<div id="export_theme" class="pagelayer-tab-panel" style="display:none;">';
622 if (function_exists('pagelayer_builder_export')) {
623 $pagelayer_footer_printed = true; // Mute inner footer
624 pagelayer_builder_export('');
625 $pagelayer_footer_printed = false; // Reset
626 }
627 echo '</div>';
628
629 // 3. Import Theme Tool Panel (Premium only)
630 echo '<div id="import_theme" class="pagelayer-tab-panel" style="display:none;">';
631 include_once(PAGELAYER_DIR.'/main/import.php');
632 if(function_exists('pagelayer_import')){
633 $pagelayer_footer_printed = true; // Mute inner footer
634 pagelayer_import();
635 $pagelayer_footer_printed = false; // Reset
636 }
637 echo '</div>';
638 } else {
639 // Output high premium promotion templates for export & import tools to enable hash tab switching and prevent page reload in Free version
640 echo'<div id="export_theme" class="pagelayer-tab-panel" style="display:none;">
641 <div class="pagelayer-settings-card" style="padding: 40px 24px; text-align: center; max-width: 600px; margin: 40px auto; border-radius: 12px; box-shadow: 0 8px 30px rgba(0,0,0,0.05); background: #fff; border: 1px solid #f0f0f0;">
642 <span class="dashicons dashicons-upload" style="font-size: 64px; width: 64px; height: 64px; color: #2563eb; margin-bottom: 16px;"></span>
643 <h2 style="font-size: 24px; margin-top: 0; color: #333; font-weight: 600;">' . __('Export Theme', 'pagelayer') . '</h2>
644 <p style="color: #666; font-size: 15px; line-height: 1.6; margin-bottom: 24px; max-width: 480px; margin-left: auto; margin-right: auto;">' . __('Exporting your customized Pagelayer designs and layouts directly into a standalone WordPress theme is a Premium feature. Upgrade to Pagelayer Pro to build and export your own custom themes!', 'pagelayer') . '</p>
645 <a href="' . esc_url(PAGELAYER_PRO_PRICE_URL) . '" target="_blank" class="button-pagelayer" style="text-decoration: none;">' . __('Upgrade to Pagelayer Pro', 'pagelayer') . '</a>
646 </div>
647 </div>';
648
649 echo'<div id="import_theme" class="pagelayer-tab-panel" style="display:none;">
650 <div class="pagelayer-settings-card" style="padding: 40px 24px; text-align: center; max-width: 600px; margin: 40px auto; border-radius: 12px; box-shadow: 0 8px 30px rgba(0,0,0,0.05); background: #fff; border: 1px solid #f0f0f0;">
651 <span class="dashicons dashicons-download" style="font-size: 64px; width: 64px; height: 64px; color: #2563eb; margin-bottom: 16px;"></span>
652 <h2 style="font-size: 24px; margin-top: 0; color: #333; font-weight: 600;">' . __('Import Theme', 'pagelayer') . '</h2>
653 <p style="color: #666; font-size: 15px; line-height: 1.6; margin-bottom: 24px; max-width: 480px; margin-left: auto; margin-right: auto;">' . __('Importing pre-designed custom themes with all layouts, options, and page structures is a Premium feature. Upgrade to Pagelayer Pro to import complete themes with a single click!', 'pagelayer') . '</p>
654 <a href="' . esc_url(PAGELAYER_PRO_PRICE_URL) . '" target="_blank" class="button-pagelayer" style="text-decoration: none;">' . __('Upgrade to Pagelayer Pro', 'pagelayer') . '</a>
655 </div>
656 </div>';
657
658 echo'<div id="custom_fonts" class="pagelayer-tab-panel" style="display:none;">
659 <div class="pagelayer-settings-card" style="padding: 40px 24px; text-align: center; max-width: 600px; margin: 40px auto; border-radius: 12px; box-shadow: 0 8px 30px rgba(0,0,0,0.05); background: #fff; border: 1px solid #f0f0f0;">
660 <span class="dashicons dashicons-editor-bold" style="font-size: 64px; width: 64px; height: 64px; color: #2563eb; margin-bottom: 16px;"></span>
661 <h2 style="font-size: 24px; margin-top: 0; color: #333; font-weight: 600;">' . __('Custom Fonts', 'pagelayer') . '</h2>
662 <p style="color: #666; font-size: 15px; line-height: 1.6; margin-bottom: 24px; max-width: 480px; margin-left: auto; margin-right: auto;">' . __('Adding and using custom typography/fonts directly in your designs is a Premium feature. Upgrade to Pagelayer Pro to upload and manage your own custom fonts!', 'pagelayer') . '</p>
663 <a href="' . esc_url(PAGELAYER_PRO_PRICE_URL) . '" target="_blank" class="button-pagelayer" style="text-decoration: none;">' . __('Upgrade to Pagelayer Pro', 'pagelayer') . '</a>
664 </div>
665 </div>';
666 }
667
668 // Reset print flags to allow the final master footer to print correctly
669 $pagelayer_footer_printed = false;
670 pagelayer_page_footer();
671 }
672
673 // This function will handle the Settings Pages in Pagelayer
674 function pagelayer_license_page(){
675
676 global $wp_version, $pagelayer;
677
678 include_once(PAGELAYER_PRO_DIR.'/main/license.php');
679
680 pagelayer_license();
681
682 }
683
684 // Import Pagelayer Templates
685 function pagelayer_import_page(){
686
687 global $wp_version, $pagelayer;
688
689 include_once(PAGELAYER_DIR.'/main/import.php');
690
691 pagelayer_import();
692
693 }
694
695 // Load the Live Body
696 add_action('template_redirect', 'pagelayer_load_live_body', 4);
697
698 function pagelayer_load_live_body(){
699
700 global $post;
701
702 // If its not live editing then stop
703 if(!pagelayer_is_live()){
704 return;
705 }
706
707 // If its the iFRAME then return
708 if(pagelayer_is_live_iframe()){
709 return;
710 }
711
712 // Are you allowed to edit ?
713 if(!pagelayer_user_can_edit($post->ID)){
714 return;
715 }
716
717 // Load the editor live body
718 include_once(PAGELAYER_DIR.'/main/live-body.php');
719
720 pagelayer_live_body();
721
722 }
723
724 // Add the JS and CSS for Posts and Pages when being viewed ONLY if there is our content called
725 add_action('template_redirect', 'pagelayer_enqueue_frontend', 5);
726 function pagelayer_enqueue_frontend($force = false){
727
728 global $post, $pagelayer;
729
730 if(!empty($pagelayer->cache['enqueue_frontend'])){
731 return;
732 }
733
734 if(empty($post->ID) && empty($force)){
735 return;
736 }
737
738 $is_pagelayer = false;
739 $is_audio = false;
740
741 // This IF is for Archives mainly as $post->ID is only the first post in the archive
742 // and we need to make sure that other posts are pagelayer or not
743 if(!empty($GLOBALS['wp_query']->posts) && is_array($GLOBALS['wp_query']->posts)){
744 foreach($GLOBALS['wp_query']->posts as $v){
745 if(get_post_meta($v->ID , 'pagelayer-data')){
746 $is_pagelayer = true;
747 }
748
749 if(preg_match('/(\[pl_audio|pagelayer\/pl_audio)/is', $v->post_content)){
750 $is_audio = true;
751 }
752 }
753 }
754
755 // Enqueue the FRONTEND CSS
756 if((!empty($post->ID) && get_post_meta($post->ID , 'pagelayer-data')) || pagelayer_has_blocks() || $is_pagelayer || $force){
757
758 // We dont need the auto <p> and <br> as they interfere with us
759 remove_filter('the_content', 'wpautop');
760
761 // No need to add curly codes to the content
762 remove_filter('the_content', 'wptexturize');
763
764 pagelayer_load_shortcodes();
765
766 // Load global colors and fonts
767 pagelayer_load_global_palette();
768
769 $pagelayer->cache['enqueue_frontend'] = true;
770
771 // Load the global styles
772 add_action('wp_head', 'pagelayer_global_js', 2);
773
774 $premium_js = apply_filters('pagelayer_add_give_js', '');
775 $premium_css = apply_filters('pagelayer_add_give_css', '');
776
777 // Load this For audio widget
778 do_action('pagelayer_load_audio_widget', $is_audio);
779
780 if(pagelayer_enable_giver()){
781
782 $write = '';
783
784 // Dev mode - Dynamic JS and CSS
785 if(defined('PAGELAYER_DEV') && !empty(PAGELAYER_DEV)){
786 $write = '&write=1';
787 }
788
789 // Enqueue our Editor's Frontend JS
790 wp_register_script('pagelayer-frontend', PAGELAYER_JS.'/givejs.php?give=pagelayer-frontend.js,nivo-lightbox.min.js,wow.min.js,jquery-numerator.js,simpleParallax.min.js,owl.carousel.min.js'.$premium_js.$write, array('jquery'), PAGELAYER_VERSION);
791
792 // Get list of enabled icons
793 $icons_css = '';
794 $icons = pagelayer_enabled_icons();
795 foreach($icons as $icon){
796 $icons_css .= ','.$icon.'.min.css';
797 }
798
799 wp_register_style('pagelayer-frontend', PAGELAYER_CSS.'/givecss.php?give=pagelayer-frontend.css,nivo-lightbox.css,animate.min.css,owl.carousel.min.css,owl.theme.default.min.css'.$icons_css.$premium_css.$write, array(), PAGELAYER_VERSION);
800
801 // Static Files
802 }else{
803
804 wp_register_script('pagelayer-frontend', (empty($premium_js) ? PAGELAYER_JS : PAGELAYER_PRO_JS).'/combined.js', array('jquery'), PAGELAYER_VERSION);
805
806 wp_register_style('pagelayer-frontend', PAGELAYER_CSS.'/combined'.(!empty($premium_css) ? '.premium' : '').'.css', array(), PAGELAYER_VERSION);
807 }
808
809 wp_enqueue_script('pagelayer-frontend');
810 wp_enqueue_style('pagelayer-frontend');
811
812 // Load the global styles
813 add_action('wp_head', 'pagelayer_global_styles', 5);
814 add_filter('body_class', 'pagelayer_body_class', 10, 2);
815
816 // Load the global styles for gutenberg
817 if(pagelayer_is_gutenberg_editor()){
818 add_action('admin_print_scripts', 'pagelayer_global_styles', 5);
819 }
820
821 // Load custom widgets
822 do_action('pagelayer_custom_frontend_enqueue');
823
824 }
825
826 }
827
828 // Load the google and custom fonts
829 add_action('wp_footer', 'pagelayer_enqueue_fonts', 5);
830 function pagelayer_enqueue_fonts($suffix = '-header'){
831
832 global $pagelayer;
833
834 if(empty($pagelayer->cache['enqueue_frontend'])){
835 return;
836 }
837
838 $url = [];
839 $cst = [];
840
841 foreach($pagelayer->css as $k => $set){
842
843 $font_family = pagelayer_isset($set, 'font-family');
844
845 if(empty($font_family)){
846 $key = str_replace(['_mobile', '_tablet'], '', $k);
847 $font_family = isset($pagelayer->css[$key]['font-family'])? $pagelayer->css[$key]['font-family']: '';
848 }
849
850 // Fetch body font if given
851 if(!empty($font_family)){
852 pagelayer_load_font_family($font_family, pagelayer_isset($set, 'font-weight'), pagelayer_isset($set, 'font-style'));
853 }
854
855 }
856
857 foreach($pagelayer->runtime_fonts as $font => $weights){
858
859 if(in_array($font, $pagelayer->system_fonts)){
860 continue;
861 }
862
863 if(strpos($font, '_plf')){
864 if(!in_array($font, $pagelayer->fonts_sent)){
865 $pagelayer->fonts_sent[] = $font;
866 $cst[] = preg_replace('/_plf$/is', '', $font);
867 }
868 }else{
869 $v = $font.':'.implode(',', $weights);
870 if(!in_array($v, $pagelayer->fonts_sent)){
871 $url[] = $v;
872 $pagelayer->fonts_sent[] = $v;
873 }
874 }
875 }
876
877 // If no fonts are to be set, then we dont set
878 if(!empty($url)){
879 $fonts_url = 'https://fonts.googleapis.com/css?family='.rawurlencode(implode('|', $url));
880
881 $fonts_url = apply_filters('pagelayer_google_fonts_url', $fonts_url);
882
883 wp_register_style('pagelayer-google-font'.$suffix, $fonts_url, array(), PAGELAYER_VERSION);
884 wp_enqueue_style('pagelayer-google-font'.$suffix);
885
886 echo '<link rel="preload" href="'.$fonts_url.'" as="fetch" crossorigin="anonymous">';
887 }
888
889 if(empty($cst)){
890 return;
891 }
892
893 $args = [
894 'post_type' => PAGELAYER_FONT_POST_TYPE,
895 'status' => 'publish',
896 'post_name__in' => $cst
897 ];
898
899 //var_dump($args);
900
901 $query = get_posts($args);
902 //var_dump($query);
903
904 if(empty($query)){
905 return;
906 }
907
908 foreach($query as $font){
909 $meta_box_value = get_post_meta($font->ID, 'pagelayer_font_link', true);
910 if(empty($meta_box_value)){
911 continue;
912 }
913
914 echo '<style id="'.$font->post_name.'_plf" >@font-face { font-family: "'.$font->post_name.'_plf"'.'; src: url("'.$meta_box_value.'"); font-weight: 100 200 300 400 500 600 700 800 900;}</style>';
915 }
916 }
917
918 // Load any header we have
919 function pagelayer_global_js(){
920 global $pagelayer;
921
922 $pagelayer_recaptch_lang = get_option('pagelayer_google_captcha_lang');
923 $pagelayer_recaptch_version = get_option('pagelayer_recaptcha_version', '');
924
925 echo '<script>
926 var pagelayer_ajaxurl = "'.admin_url( 'admin-ajax.php' ).'?";
927 var pagelayer_global_nonce = "'.wp_create_nonce('pagelayer_global').'";
928 var pagelayer_server_time = '.time().';
929 var pagelayer_is_live = "'.pagelayer_is_live().'";
930 var pagelayer_facebook_id = "'.get_option('pagelayer-fbapp-id').'";
931 var pagelayer_settings = '.json_encode($pagelayer->settings).';
932 var pagelayer_recaptch_lang = "'.(!empty($pagelayer_recaptch_lang) ? $pagelayer_recaptch_lang : '').'";
933 var pagelayer_recaptch_version = "'.(!empty($pagelayer_recaptch_version) ? $pagelayer_recaptch_version : '').'";
934 </script>';
935
936 }
937
938 // We need to handle global styles
939 function pagelayer_load_global_css(){
940 global $pagelayer;
941
942 // Load CSS settings
943 foreach($pagelayer->css_settings as $k => $params){
944 $tmp_desk = '';
945 foreach($pagelayer->screens as $sk => $sv){
946 $suffix = (!empty($sv) ? '_'.$sv : '');
947 $setting = empty($params['key']) ? 'pagelayer_'.$k.'_css' : $params['key'];
948 $tmp = get_option($setting.$suffix);
949
950 if($sk == 'desktop'){
951 $tmp_desk = $tmp;
952 }
953
954 $tmp = pagelayer_sanitize_global_style($tmp, $tmp_desk, $sk);
955
956 if(empty($tmp)){
957 continue;
958 }
959
960 $pagelayer->css[$k.$suffix] = $tmp;
961 }
962 }
963
964 // Backward compat for colors
965 if(!empty($pagelayer->settings['color']['background']) && empty($pagelayer->css['body']['background-color'])){
966 $pagelayer->css['body']['background-color'] = $pagelayer->settings['color']['background'];
967 }
968
969 if(!empty($pagelayer->settings['color']['text']) && empty($pagelayer->css['body']['color'])){
970 $pagelayer->css['body']['color'] = $pagelayer->settings['color']['text'];
971 }
972
973 // Link Color
974 if(!empty($pagelayer->settings['color']['link']) && empty($pagelayer->css['a']['color'])){
975 $pagelayer->css['a']['color'] = $pagelayer->settings['color']['link'];
976 }
977
978 // Link Hover Color
979 if(!empty($pagelayer->settings['color']['link-hover']) && empty($pagelayer->css['a-hover']['color'])){
980 $pagelayer->css['a-hover']['color'] = $pagelayer->settings['color']['link-hover'];
981 }
982
983 // Headings Color
984 if(!empty($pagelayer->settings['color']['heading'])){
985 $htmp = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'];
986 foreach($htmp as $k => $v){
987 if(empty($pagelayer->css[$v]['color'])){
988 $pagelayer->css[$v]['color'] = $pagelayer->settings['color']['heading'];
989 }
990 }
991 }
992
993 // Backward compat for body font
994 if(!empty($pagelayer->settings['body_font'])){
995 $pagelayer->settings['body']['font-family'] = $pagelayer->settings['body_font'];
996 }
997 }
998
999 // We need to handle global styles
1000 function pagelayer_global_styles(){
1001
1002 global $pagelayer, $post;
1003
1004 // Load css from settings
1005 pagelayer_load_global_css();
1006
1007 $styles = '<style id="pagelayer-wow-animation-style" type="text/css">.pagelayer-wow{visibility: hidden;}</style>
1008 <style id="pagelayer-global-styles" type="text/css">'.PHP_EOL;
1009
1010 $screen_style['tablet'] = '';
1011 $screen_style['mobile'] = '';
1012
1013 // PX suffix
1014 $pxs = ['font-size', 'letter-spacing', 'word-spacing'];
1015 $arrays = ['padding', 'margin'];
1016
1017 $styles .= ':root{';
1018
1019 // Set global colors
1020 foreach($pagelayer->global_colors as $gk => $gv){
1021 if (isset($gv['value'])) {
1022 $styles .= '--pagelayer-color-'.$gk.':'.$gv['value'].';';
1023 }
1024 }
1025
1026 // Set global fonts
1027 foreach($pagelayer->global_fonts as $gk => $gv){
1028
1029 if (empty($gv['value']) || !is_array($gv['value'])) {
1030 continue;
1031 }
1032
1033 foreach($gv['value'] as $fk => $fv){
1034
1035 if(empty($fv)){
1036 continue;
1037 }
1038
1039 $unit = in_array($fk, $pxs) ? 'px' : '';
1040
1041 if(is_array($fv)){
1042 foreach($fv as $mode => $mv){
1043
1044 if(empty($mv)){
1045 continue;
1046 }
1047
1048 $font_css = '--pagelayer-font-'.$gk.'-'.$fk.':'.$mv.$unit.';';
1049
1050 if($mode == 'tablet' || $mode == 'mobile'){
1051 $screen_style[$mode] .= ':root{'.$font_css.'}';
1052 continue;
1053 }
1054
1055 $styles .= $font_css;
1056 }
1057 continue;
1058 }
1059
1060 $styles .= '--pagelayer-font-'.$gk.'-'.$fk .':'.$fv.$unit.';';
1061 }
1062 }
1063
1064 $styles .= '}'.PHP_EOL;
1065
1066 // Style for only child row holder
1067 $styles .= '.pagelayer-row-stretch-auto > .pagelayer-row-holder, .pagelayer-row-stretch-full > .pagelayer-row-holder.pagelayer-width-auto{ max-width: '.$pagelayer->settings['max_width'].'px; margin-left: auto; margin-right: auto;}'.PHP_EOL;
1068
1069 if(!pagelayer_is_live() && !pagelayer_is_gutenberg_editor()){
1070
1071 // Set responsive value
1072 $styles .= '@media (min-width: '.($pagelayer->settings['tablet_breakpoint'] + 1).'px){
1073 .pagelayer-hide-desktop{
1074 display:none !important;
1075 }
1076 }
1077
1078 @media (max-width: '.$pagelayer->settings['tablet_breakpoint'].'px) and (min-width: '.($pagelayer->settings['mobile_breakpoint'] + 1).'px){
1079 .pagelayer-hide-tablet{
1080 display:none !important;
1081 }
1082 .pagelayer-wp-menu-holder[data-drop_breakpoint="tablet"] .pagelayer-wp_menu-ul{
1083 display:none;
1084 }
1085 }
1086
1087 @media (max-width: '.$pagelayer->settings['mobile_breakpoint'].'px){
1088 .pagelayer-hide-mobile{
1089 display:none !important;
1090 }
1091 .pagelayer-wp-menu-holder[data-drop_breakpoint="mobile"] .pagelayer-wp_menu-ul{
1092 display:none;
1093 }
1094 }'.PHP_EOL;
1095
1096 }
1097
1098 // Setup CSS as per post. This overright the global styles
1099 foreach($pagelayer->css_settings as $k => $params){
1100 $tmp_desk = '';
1101 foreach($pagelayer->screens as $sk => $sv){
1102 $suffix = (!empty($sv) ? '_'.$sv : '');
1103 $setting = empty($params['key']) ? 'pagelayer_'.$k.'_css_'.@$post->post_type : $params['key'].'_'.@$post->post_type;
1104 $tmp = get_option($setting.$suffix);
1105
1106 if($sk == 'desktop'){
1107 $tmp_desk = $tmp;
1108 }
1109
1110 $tmp = pagelayer_sanitize_global_style($tmp, $tmp_desk, $sk);
1111
1112 if(empty($tmp)){
1113 continue;
1114 }
1115
1116 if(!empty($pagelayer->css[$k.$suffix])){
1117
1118 $typo_on = false;
1119 $_typo = array();
1120 $typo = $pagelayer->typo_props;
1121
1122 // Check if all font properties are empty then we do not overright the global typo styles
1123 foreach($typo as $prop){
1124
1125 if(!empty($tmp[$prop])){
1126 $typo_on = true;
1127 }
1128
1129 $_typo[$prop] = empty($tmp[$prop]) ? '' : $tmp[$prop];
1130 }
1131
1132 foreach($tmp as $tkk => $tvv){
1133
1134 $tvv_is_empty = is_array($tvv) ? pagelayer_is_empty_array($tvv) : empty($tvv);
1135
1136 // Skip update for empty value and if type is empty
1137 if($tvv_is_empty || in_array($tkk, $typo)){
1138 continue;
1139 }
1140
1141 $pagelayer->css[$k.$suffix][$tkk] = $tvv;
1142 }
1143
1144 if($typo_on){
1145 $pagelayer->css[$k.$suffix] = array_merge($pagelayer->css[$k.$suffix], $_typo);
1146 }
1147
1148 continue;
1149 }
1150
1151 $pagelayer->css[$k.$suffix] = $tmp;
1152 }
1153 }
1154
1155 // If is not loaded then the pagelayer_parse_vars, pagelayer_css_render not working
1156 if(empty($pagelayer->customizer_params)){
1157 pagelayer_load_shortcodes();
1158 }
1159
1160 // Customizer CSS
1161 foreach($pagelayer->customizer_params as $prop => $param){
1162
1163 if(empty($param['customizer_css']) || empty($param['css'])){
1164 continue;
1165 }
1166
1167 if(!is_array($param['css'])){
1168 $param['css'] = array($param['css']);
1169 }
1170
1171 $customize_el = array();
1172 $customize_el['atts'] = $pagelayer->customizer_mods;
1173
1174 // Get Image URL
1175 $attachment = ($param['type'] == 'image') ? pagelayer_image(@$pagelayer->customizer_mods[$prop]) : '';
1176
1177 if(!empty($attachment)){
1178 foreach($attachment as $k => $v){
1179 $customize_el['tmp'][$prop.'-'.$k] = $v;
1180 }
1181 }
1182
1183 // Loop the modes and check for values
1184 foreach($pagelayer->screens as $sk => $sv){
1185
1186 $suffix = (!empty($sv) ? '_'.$sv : '');
1187 $M_prop = $prop.$suffix;
1188
1189 // Any value ?
1190 if(empty($pagelayer->customizer_mods[$M_prop])){
1191 continue;
1192 }
1193
1194 // Loop through
1195 foreach($param['css'] as $k => $v){
1196
1197 // Make the selector
1198 $selector = (!is_numeric($k) && !empty($k) ? $k : 'body.pagelayer-body');
1199
1200 // Make the CSS
1201 $customize_css = $selector.'{'. rtrim( trim( pagelayer_css_render($v, $pagelayer->customizer_mods[$M_prop], @$param['sep']) ), ';' ) .'}' ;
1202
1203 $customize_css = pagelayer_parse_vars($customize_css, $customize_el);
1204
1205 if($sk == 'tablet'){
1206 $screen_style['tablet'] .= $customize_css;
1207 continue;
1208 }
1209
1210 if($sk == 'mobile'){
1211 $screen_style['mobile'] .= $customize_css;
1212 continue;
1213 }
1214
1215 $styles .= $customize_css;
1216 }
1217
1218 }
1219 }
1220
1221 // Loop CSS settings
1222 foreach($pagelayer->css as $k => $v){
1223
1224 $r = [];
1225
1226 foreach($pagelayer->css[$k] as $kk => $vv){
1227
1228 if(empty($vv)){
1229 continue;
1230 }
1231
1232 if(in_array($kk, $arrays)){
1233 $unit = 'px';
1234
1235 if(!empty($vv['unit'])){
1236 $unit = $vv['unit'];
1237 unset($vv['unit']);
1238 }
1239
1240 $vv = array_filter($vv, function($value){ return !empty($value);});
1241 if(empty($vv)){
1242 continue;
1243 }
1244
1245 $skel = [0, 0, 0, 0];
1246 $vv = array_replace($skel, $vv);
1247 $vv = implode($unit.' ', $vv).$unit;
1248 }
1249
1250 $r[] = $kk.':'.$vv.(in_array($kk, $pxs) && strripos($vv, 'var(') === false ? 'px' : '');
1251
1252 }
1253
1254 if(empty($r)){
1255 continue;
1256 }
1257
1258 $matches = [];
1259 preg_match('/_(mobile|tablet)$/is', $k, $matches);
1260 $key = str_replace(['_mobile', '_tablet'], '', $k);
1261 $screen = isset($matches[1]) ? $matches[1] : '';
1262
1263 //echo $key.' - '.$k;pagelayer_print($matches);
1264
1265 $params = $pagelayer->css_settings[$key];
1266
1267 $sel = !isset($params['sel']) ? ($key == 'body' ? '' : $key) : $params['sel'];
1268
1269 $style = 'body.pagelayer-body '.$sel.'{'.implode(';', $r)."}\n";
1270
1271 // Mobile or tablet ?
1272 if(!empty($screen)){
1273 $screen_style[$screen] .= $style;
1274 }else{
1275 $styles .= $style;
1276 }
1277 }
1278
1279 // Tablet Styles
1280 $styles .= '@media (max-width: '.$pagelayer->settings['tablet_breakpoint'].'px){
1281 [class^="pagelayer-offset-"],
1282 [class*=" pagelayer-offset-"] {
1283 margin-left: 0;
1284 }
1285
1286 .pagelayer-row .pagelayer-col {
1287 margin-left: 0;
1288 width: 100%;
1289 }
1290 .pagelayer-row.pagelayer-gutters .pagelayer-col {
1291 margin-bottom: 16px;
1292 }
1293 .pagelayer-first-sm {
1294 order: -1;
1295 }
1296 .pagelayer-last-sm {
1297 order: 1;
1298 }
1299
1300 '.$screen_style['tablet'].'
1301 }'.PHP_EOL;
1302
1303 // Any mobile style ?
1304 if(!empty($screen_style['mobile'])){
1305 $styles .= '@media (max-width: '.$pagelayer->settings['mobile_breakpoint'].'px){
1306 '.$screen_style['mobile'].'}'.PHP_EOL;
1307 }
1308
1309 $styles .= PHP_EOL.'</style>';
1310
1311 // Lets just build a temporary list of fonts so that we can add prefetch !
1312 pagelayer_enqueue_fonts();
1313
1314 if(!empty($pagelayer->runtime_fonts)){
1315 echo '<link rel="dns-prefetch" href="https://fonts.gstatic.com">
1316 <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="anonymous">';
1317 }
1318
1319 echo $styles;
1320 }
1321
1322 function pagelayer_body_class($classes, $class){
1323 $classes[] = 'pagelayer-body';
1324 return $classes;
1325 }
1326
1327 // Load the live editor if needed
1328 // Changed this hook wp_enqueue_scripts to Template_include to make block theme compatibility
1329 add_action('template_include', 'pagelayer_load_live');
1330 function pagelayer_load_live($template){
1331
1332 global $post, $pagelayer;
1333
1334 $pagelayer->load_live_errors = array();
1335
1336 // If its not live editing then stop
1337 if(!pagelayer_is_live_iframe($pagelayer->load_live_errors)){
1338
1339 // Is it the live mode then lets throw an error ?
1340 if(pagelayer_optreq('pagelayer-iframe')){
1341 add_action('wp_head', 'pagelayer_load_live_errors', 999);
1342 }
1343
1344 return $template;
1345 }
1346
1347 // Are you allowed to edit ?
1348 if(!pagelayer_user_can_edit($post->ID)){
1349 return $template;
1350 }
1351
1352 // Load the editor class
1353 include_once(PAGELAYER_DIR.'/main/live.php');
1354
1355 // Call the constructor
1356 $pl_editor = new PageLayer_LiveEditor();
1357
1358 return $template;
1359 }
1360
1361 // Show the live errors if any
1362 function pagelayer_load_live_errors(){
1363
1364 global $post, $pagelayer;
1365
1366 // Any errors ?
1367 if(empty($pagelayer->load_live_errors)){
1368 return;
1369 }
1370
1371 echo '<script>
1372 alert("'.str_replace('"', '\\"', implode("\n", $pagelayer->load_live_errors)).'");
1373 </script>';
1374
1375 }
1376
1377 // If we are doing ajax and its a pagelayer ajax
1378 if(wp_doing_ajax()){
1379 include_once(PAGELAYER_DIR.'/main/ajax.php');
1380 }
1381
1382 // Show the backend editor options
1383 add_action('edit_form_after_title', 'pagelayer_after_title', 10);
1384 function pagelayer_after_title(){
1385
1386 global $post;
1387
1388 // Get the current screen
1389 $current_screen = get_current_screen();
1390
1391 // For gutenberg
1392 if(method_exists($current_screen, 'is_block_editor') && $current_screen->is_block_editor()){
1393
1394 // Add the code in the footer
1395 add_action('admin_footer', 'pagelayer_gutenberg_after_title');
1396
1397 return;
1398 }
1399
1400 // Is pagelayer supposed to edit this ?
1401 if(!pagelayer_user_can_edit($post)){
1402 return;
1403 }
1404
1405 $link = pagelayer_shortlink($post->ID).'&pagelayer-live=1';
1406
1407 echo '
1408 <div id="pagelayer-editor-button-row" style="margin-top:15px; display:inline-block;">
1409 <a id="pagelayer-editor-button" href="'.$link.'" class="button button-primary button-large" style="height:auto; padding:4px 8px; font-size:13px; display:flex; align-items:center; width: max-content;">
1410 <img src="'.PAGELAYER_URL.'/images/pagelayer-logo-40.png" width="22" style="margin-right:4px" /> <span>'.__('Edit with Pagelayer').'</span>
1411 </a>
1412 </div>';
1413
1414 }
1415
1416 function pagelayer_gutenberg_after_title(){
1417
1418 global $post;
1419
1420 // Is pagelayer supposed to edit this ?
1421 if(!pagelayer_user_can_edit($post)){
1422 return;
1423 }
1424
1425 $link = pagelayer_shortlink($post->ID).'&pagelayer-live=1';
1426
1427 echo '
1428 <div id="pagelayer-editor-button-row" style="margin-left:15px; display:none">
1429 <a id="pagelayer-editor-button" href="'.$link.'" class="button button-primary button-large" style="height:auto; font-size:13px; display:flex; align-items:center;width: max-content;">
1430 <img src="'.PAGELAYER_URL.'/images/pagelayer-logo-40.png" align="top" width="22" style="margin-right:4px"/> <span>'.__('Edit with Pagelayer').'</span>
1431 </a>
1432 </div>
1433
1434 <script type="text/javascript">
1435 jQuery(document).ready(function(){
1436
1437 var pagelayer_timer;
1438 var pagelayer_button = function(){
1439 var button = jQuery("#pagelayer-editor-button-row");
1440 var g = jQuery(".edit-post-header-toolbar");
1441 if(g.length < 1){
1442 return;
1443 }
1444 button.detach();
1445 //console.log(button);
1446 g.parent().append(button);
1447 button.show();
1448 clearInterval(pagelayer_timer);
1449 }
1450 pagelayer_timer = setInterval(pagelayer_button, 100);
1451 });
1452 </script>';
1453
1454 }
1455
1456 // Handle Old Slug URL redirect for live link
1457 add_filter( 'old_slug_redirect_url', 'pagelayer_old_slug_redirect', 10, 1);
1458 function pagelayer_old_slug_redirect($link){
1459
1460 if(pagelayer_optreq('pagelayer-live')){
1461 $link = add_query_arg('pagelayer-live', '1', $link);
1462 }
1463
1464 return $link;
1465 }
1466
1467 // Clone Post
1468 add_action('admin_action_pagelayer_clone_post', 'pagelayer_clone_post');
1469 function pagelayer_clone_post(){
1470
1471 // Nonce verification
1472 check_admin_referer('pagelayer-options');
1473
1474 // Get the original post id
1475 $post_id = (int) $_REQUEST['post'];
1476 $post = get_post( $post_id );
1477
1478 // If post data exists, create the post clone
1479 if(empty($post)){
1480 wp_die('No post found');
1481 }
1482
1483 if(!current_user_can('edit_post', $post->ID)){
1484 wp_die('You don\'t have access to clone this post.');
1485 }
1486
1487 $current_user = wp_get_current_user();
1488 $new_post_author = $current_user->ID;
1489
1490 unset($post->ID);
1491 $post->post_author = $new_post_author;
1492 $post->post_name = '';
1493 $post->post_status = 'draft';
1494 $post->post_title = $post->post_title.' Clone';
1495 $post->post_date = '';
1496 $post->post_date_gmt = '';
1497 $post->guid = '';
1498
1499 $new_post_id = wp_insert_post( $post );
1500
1501 if(empty($new_post_id)){
1502 wp_die('Post creation failed, could not find original post: ' . $post_id);
1503 }
1504
1505 // Get all current post terms and set them to the new post draft
1506 $taxonomies = get_object_taxonomies($post->post_type);
1507 foreach ($taxonomies as $taxonomy) {
1508 $post_terms = wp_get_object_terms($post_id, $taxonomy, array('fields' => 'slugs'));
1509 wp_set_object_terms($new_post_id, $post_terms, $taxonomy, false);
1510 }
1511
1512 // Clone all post meta info
1513 $post_meta_infos = get_post_meta($post_id);
1514 if (count($post_meta_infos) > 0) {
1515 foreach ($post_meta_infos as $meta_key => $meta_value){
1516 add_post_meta($new_post_id, $meta_key, wp_slash( maybe_unserialize($meta_value[0]) ));
1517 }
1518 }
1519
1520 // Finally, redirect to the edit post screen for the new draft
1521 wp_redirect( get_edit_post_link($new_post_id, '') );
1522 exit;
1523
1524 }
1525
1526 // Add the clone link to action list for post_row_actions
1527 add_filter('post_row_actions', 'pagelayer_clone_post_link', 10, 2);
1528 add_filter('page_row_actions', 'pagelayer_clone_post_link', 10, 2);
1529 function pagelayer_clone_post_link( $actions, $post ) {
1530 if (current_user_can('edit_posts') && $post->post_status !== 'trash' && !defined('SITEPAD') && get_option('pagelayer_disable_clone') != 1) {
1531 $actions['clone'] = '<a href="'.wp_nonce_url('admin.php?action=pagelayer_clone_post&post='.$post->ID, 'pagelayer-options') . '" rel="permalink">'.__( 'Clone', 'pagelayer') .'</a>';
1532 }
1533 return $actions;
1534 }
1535
1536 add_filter( 'post_row_actions', 'pagelayer_quick_link', 10, 2 );
1537 add_filter( 'page_row_actions', 'pagelayer_quick_link', 10, 2 );
1538 function pagelayer_quick_link($actions, $post){
1539 global $pagelayer;
1540
1541 // Some woocommerce pages are not having ID
1542 if(empty($post->ID)){
1543 return $actions;
1544 }
1545
1546 // Is pagelayer supposed to edit this ?
1547 if(!pagelayer_user_can_edit($post)){
1548 return $actions;
1549 }
1550
1551 $link = pagelayer_shortlink($post->ID).'&pagelayer-live=1';
1552
1553 $actions['pagelayer'] = '<a href="'.esc_url( $link ).'">'.__( 'Edit using Pagelayer', 'pagelayer') .'</a>';
1554
1555 return $actions;
1556 }
1557
1558 // Add settings link on plugin page
1559 add_filter('plugin_action_links_pagelayer/pagelayer.php', 'pagelayer_plugin_action_links');
1560 function pagelayer_plugin_action_links($links){
1561
1562 if(!defined('PAGELAYER_PREMIUM')){
1563 $links[] = '<a href="'.PAGELAYER_PRO_PRICE_URL.'" style="color:#3db634;" target="_blank">'._x('Go Pro', 'Upgrade to Pagelayer Pro for many more features', 'pagelayer').'</a>';
1564 }
1565
1566 $settings_link = '<a href="admin.php?page=pagelayer">Settings</a>';
1567 array_unshift($links, $settings_link);
1568
1569 return $links;
1570 }
1571
1572 // Add custom header
1573 add_action('wp_head', 'pagelayer_add_custom_head', 102);
1574 function pagelayer_add_custom_head(){
1575 global $post;
1576
1577 $global_code = wp_unslash( get_option('pagelayer_header_code') );
1578
1579 if(!empty($post)){
1580 $header_code = get_post_meta($post->ID , 'pagelayer_header_code', true);
1581 }
1582
1583 if(!empty($global_code)){
1584 echo $global_code."\n";
1585 }
1586
1587 if(!empty($header_code)){
1588 echo $header_code."\n";
1589 }
1590
1591 }
1592
1593 // Add custom body
1594 add_action('wp_body_open', 'pagelayer_body_open');
1595 function pagelayer_body_open(){
1596 global $post;
1597
1598 $global_code = wp_unslash( get_option('pagelayer_body_open_code') );
1599
1600 if(!empty($post)){
1601 $body_code = get_post_meta($post->ID , 'pagelayer_body_open_code', true);
1602 }
1603
1604 if(!empty($global_code)){
1605 echo $global_code."\n";
1606 }
1607
1608 if(!empty($body_code)){
1609 echo $body_code."\n";
1610 }
1611
1612 }
1613
1614 // Add custom footer
1615 add_action('wp_footer', 'pagelayer_add_custom_footer');
1616 function pagelayer_add_custom_footer(){
1617 global $post, $pagelayer;
1618
1619 if(!empty($pagelayer->localScript)){
1620
1621 //Add local Script to variable to footer
1622 wp_register_script('pagelayer-localScript', false, true);
1623 wp_localize_script('pagelayer-localScript','pagelayer_local_scripts', $pagelayer->localScript);
1624 wp_enqueue_script( 'pagelayer-localScript');
1625 }
1626
1627 if($pagelayer->append_yt_api){
1628 wp_register_script('pagelayer-youtube-script',"https://www.youtube.com/iframe_api", array(), PAGELAYER_VERSION, true);
1629 wp_enqueue_script('pagelayer-youtube-script');
1630
1631 }
1632
1633 $global_code = wp_unslash( get_option('pagelayer_footer_code') );
1634
1635 if(!empty($post)){
1636 $footer_code = get_post_meta($post->ID , 'pagelayer_footer_code', true);
1637 }
1638
1639 if(!empty($global_code)){
1640 echo $global_code."\n";
1641 }
1642
1643 if(!empty($footer_code)){
1644 echo $footer_code."\n";
1645 }
1646
1647
1648 }
1649
1650 // Handle Logout Redirect here
1651 add_action('wp_logout', 'pagelayer_after_logout');
1652 function pagelayer_after_logout($user_id){
1653
1654 // Get the URL
1655 $url = get_user_option('pagelayer_logout_url', $user_id);
1656
1657 // Now blank it
1658 update_user_option($user_id, 'pagelayer_logout_url', '');
1659
1660 // We will redirect if we have the given item set.
1661 if(!empty($url)){
1662 wp_redirect( $url );
1663 exit();
1664 }
1665
1666 }
1667
1668 // Replace Media
1669 $pagelayer_media_replace = get_option( 'pagelayer_disable_media_replace');
1670 if(empty($pagelayer_media_replace)){
1671
1672 // Add URL to Replace Meda
1673 add_filter('media_row_actions', 'pagelayer_add_media_action', 10, 2);
1674 function pagelayer_add_media_action($actions, $post){
1675
1676 $url = admin_url('upload.php');
1677 $url = add_query_arg(array(
1678 'page' => 'pagelayer_replace_media',
1679 'id' => $post->ID,
1680 ), $url);
1681
1682 $actions['pagelayer_replace_media'] = '<a href="'.$url.'" rel="permalink">'.esc_html__('Replace media', 'pagelayer').'</a>';
1683
1684 return $actions;
1685
1686 }
1687
1688 }
1689
1690 // Replace Media Function
1691 function pagelayer_replace_media(){
1692
1693 include_once(PAGELAYER_DIR.'/main/replace-media.php');
1694
1695 pagelayer_replace_page();
1696
1697 }
1698
1699 // Hide admin bar
1700 add_action( 'init', 'pagelayer_hide_admin_bar');
1701 function pagelayer_hide_admin_bar(){
1702
1703 // Is it the live mode ?
1704 if(!pagelayer_optreq('pagelayer-live', false) || !pagelayer_optreq('pagelayer-iframe', false)){
1705 return false;
1706 }
1707
1708 show_admin_bar(false);
1709 }
1710
1711 // Check is gutenberg editor
1712 function pagelayer_is_gutenberg_editor(){
1713
1714 if(!function_exists('get_current_screen')){
1715 return false;
1716 }
1717
1718 $screen = get_current_screen();
1719
1720 if(empty($screen) || !method_exists($screen, 'is_block_editor')){
1721 return false;
1722 }
1723
1724 return $screen->is_block_editor();
1725 }
1726
1727 // Pagelayer Template Loading Mechanism
1728 include_once(PAGELAYER_DIR.'/main/template.php');
1729
1730 // Convert Pagelayer widgets to gutenberg block
1731 if(file_exists(PAGELAYER_DIR.'/main/blocks.php')){
1732 include_once(PAGELAYER_DIR.'/main/blocks.php');
1733 }