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

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