PluginProbe
Page Builder: Pagelayer – Drag and Drop website builder / 2.2.0
Page Builder: Pagelayer – Drag and Drop website builder v2.2.0
2.2.1 2.2.0 2.1.9 2.1.8 2.1.7 2.1.6 2.1.5 2.1.4 2.1.3 trunk 0.9.0 0.9.1 0.9.2 0.9.3 0.9.4 0.9.5 0.9.6 0.9.7 0.9.8 0.9.9 1.0.0 1.0.2 1.0.3 1.0.4 1.0.5 All 129 releases
← All changes | init.php +1732 -1731 2.1.92.2.0 View file →
@@ -1,1732 +1,1733 @@
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.9');
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 -
546 - // Sanitize Pagelayer blocks at any depth, they can be nested inside
547 - // any other block
548 - $output .= serialize_block( pagelayer_sanitize_block_tree( $block ) );
549 - }
550 -
551 - return wp_slash($output);
552 -}
553 -
554 -// On post save handler
555 -add_action('save_post', 'pagelayer_save_post', 10, 3);
556 -function pagelayer_save_post( $post_id, $post, $update ) {
557 -
558 - if( !isset($_REQUEST['is_pagelayer_editor']) || !pagelayer_user_can_edit($post_id)){
559 - return;
560 - }
561 -
562 - check_admin_referer('update-post_' . $post_id);
563 -
564 - // Save Header, body and footer code
565 - $header_code = !empty($_REQUEST['pagelayer_header_code']) ? $_REQUEST['pagelayer_header_code'] : '' ;
566 - $body_code = !empty($_REQUEST['pagelayer_body_open_code']) ? $_REQUEST['pagelayer_body_open_code'] : '' ;
567 - $footer_code = !empty($_REQUEST['pagelayer_footer_code']) ? $_REQUEST['pagelayer_footer_code'] : '' ;
568 -
569 - // Set Custom header, body and footer code
570 - if(!empty($header_code)){
571 - update_post_meta($post_id, 'pagelayer_header_code', $header_code);
572 - }else{
573 - delete_post_meta($post_id, 'pagelayer_header_code');
574 - }
575 -
576 - if(!empty($body_code)){
577 - update_post_meta($post_id, 'pagelayer_body_open_code', $body_code);
578 - }else{
579 - delete_post_meta($post_id, 'pagelayer_body_open_code');
580 - }
581 -
582 - if(!empty($footer_code)){
583 - update_post_meta($post_id, 'pagelayer_footer_code', $footer_code);
584 - }else{
585 - delete_post_meta($post_id, 'pagelayer_footer_code');
586 - }
587 -
588 -}
589 -
590 -// This function will handle the Settings Pages in Pagelayer
591 -function pagelayer_page_handler(){
592 -
593 - global $wp_version, $pagelayer;
594 -
595 - include_once(PAGELAYER_DIR.'/main/settings.php');
596 -
597 - pagelayer_settings_page();
598 -
599 -}
600 -
601 -function pagelayer_tools_page_handler(){
602 - global $wp_version, $pagelayer, $pagelayer_header_printed, $pagelayer_footer_printed;
603 -
604 - include_once(PAGELAYER_DIR.'/main/settings.php');
605 -
606 - // Render the single master Pagelayer Tools page header
607 - pagelayer_page_header(__('Tools', 'pagelayer'));
608 -
609 - // 1. Add New Template Tool Panel
610 - echo '<div id="add_new_template" class="pagelayer-tab-panel">';
611 - if (function_exists('pagelayer_builder_template_wizard')) {
612 - $pagelayer_footer_printed = true; // Mute inner footer
613 - pagelayer_builder_template_wizard();
614 - $pagelayer_footer_printed = false; // Reset
615 - }
616 - echo '</div>';
617 -
618 - // 2. Export Theme Tool Panel (Premium only)
619 - if(defined('PAGELAYER_PREMIUM')){
620 - echo '<div id="export_theme" class="pagelayer-tab-panel" style="display:none;">';
621 - if (function_exists('pagelayer_builder_export')) {
622 - $pagelayer_footer_printed = true; // Mute inner footer
623 - pagelayer_builder_export('');
624 - $pagelayer_footer_printed = false; // Reset
625 - }
626 - echo '</div>';
627 -
628 - // 3. Import Theme Tool Panel (Premium only)
629 - echo '<div id="import_theme" class="pagelayer-tab-panel" style="display:none;">';
630 - include_once(PAGELAYER_DIR.'/main/import.php');
631 - if(function_exists('pagelayer_import')){
632 - $pagelayer_footer_printed = true; // Mute inner footer
633 - pagelayer_import();
634 - $pagelayer_footer_printed = false; // Reset
635 - }
636 - echo '</div>';
637 - } else {
638 - // Output high premium promotion templates for export & import tools to enable hash tab switching and prevent page reload in Free version
639 - echo'<div id="export_theme" class="pagelayer-tab-panel" style="display:none;">
640 - <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;">
641 - <span class="dashicons dashicons-upload" style="font-size: 64px; width: 64px; height: 64px; color: #2563eb; margin-bottom: 16px;"></span>
642 - <h2 style="font-size: 24px; margin-top: 0; color: #333; font-weight: 600;">' . __('Export Theme', 'pagelayer') . '</h2>
643 - <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>
644 - <a href="' . esc_url(PAGELAYER_PRO_PRICE_URL) . '" target="_blank" class="button-pagelayer" style="text-decoration: none;">' . __('Upgrade to Pagelayer Pro', 'pagelayer') . '</a>
645 - </div>
646 - </div>';
647 -
648 - echo'<div id="import_theme" class="pagelayer-tab-panel" style="display:none;">
649 - <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;">
650 - <span class="dashicons dashicons-download" style="font-size: 64px; width: 64px; height: 64px; color: #2563eb; margin-bottom: 16px;"></span>
651 - <h2 style="font-size: 24px; margin-top: 0; color: #333; font-weight: 600;">' . __('Import Theme', 'pagelayer') . '</h2>
652 - <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>
653 - <a href="' . esc_url(PAGELAYER_PRO_PRICE_URL) . '" target="_blank" class="button-pagelayer" style="text-decoration: none;">' . __('Upgrade to Pagelayer Pro', 'pagelayer') . '</a>
654 - </div>
655 - </div>';
656 -
657 - echo'<div id="custom_fonts" class="pagelayer-tab-panel" style="display:none;">
658 - <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;">
659 - <span class="dashicons dashicons-editor-bold" style="font-size: 64px; width: 64px; height: 64px; color: #2563eb; margin-bottom: 16px;"></span>
660 - <h2 style="font-size: 24px; margin-top: 0; color: #333; font-weight: 600;">' . __('Custom Fonts', 'pagelayer') . '</h2>
661 - <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>
662 - <a href="' . esc_url(PAGELAYER_PRO_PRICE_URL) . '" target="_blank" class="button-pagelayer" style="text-decoration: none;">' . __('Upgrade to Pagelayer Pro', 'pagelayer') . '</a>
663 - </div>
664 - </div>';
665 - }
666 -
667 - // Reset print flags to allow the final master footer to print correctly
668 - $pagelayer_footer_printed = false;
669 - pagelayer_page_footer();
670 -}
671 -
672 -// This function will handle the Settings Pages in Pagelayer
673 -function pagelayer_license_page(){
674 -
675 - global $wp_version, $pagelayer;
676 -
677 - include_once(PAGELAYER_PRO_DIR.'/main/license.php');
678 -
679 - pagelayer_license();
680 -
681 -}
682 -
683 -// Import Pagelayer Templates
684 -function pagelayer_import_page(){
685 -
686 - global $wp_version, $pagelayer;
687 -
688 - include_once(PAGELAYER_DIR.'/main/import.php');
689 -
690 - pagelayer_import();
691 -
692 -}
693 -
694 -// Load the Live Body
695 -add_action('template_redirect', 'pagelayer_load_live_body', 4);
696 -
697 -function pagelayer_load_live_body(){
698 -
699 - global $post;
700 -
701 - // If its not live editing then stop
702 - if(!pagelayer_is_live()){
703 - return;
704 - }
705 -
706 - // If its the iFRAME then return
707 - if(pagelayer_is_live_iframe()){
708 - return;
709 - }
710 -
711 - // Are you allowed to edit ?
712 - if(!pagelayer_user_can_edit($post->ID)){
713 - return;
714 - }
715 -
716 - // Load the editor live body
717 - include_once(PAGELAYER_DIR.'/main/live-body.php');
718 -
719 - pagelayer_live_body();
720 -
721 -}
722 -
723 -// Add the JS and CSS for Posts and Pages when being viewed ONLY if there is our content called
724 -add_action('template_redirect', 'pagelayer_enqueue_frontend', 5);
725 -function pagelayer_enqueue_frontend($force = false){
726 -
727 - global $post, $pagelayer;
728 -
729 - if(!empty($pagelayer->cache['enqueue_frontend'])){
730 - return;
731 - }
732 -
733 - if(empty($post->ID) && empty($force)){
734 - return;
735 - }
736 -
737 - $is_pagelayer = false;
738 - $is_audio = false;
739 -
740 - // This IF is for Archives mainly as $post->ID is only the first post in the archive
741 - // and we need to make sure that other posts are pagelayer or not
742 - if(!empty($GLOBALS['wp_query']->posts) && is_array($GLOBALS['wp_query']->posts)){
743 - foreach($GLOBALS['wp_query']->posts as $v){
744 - if(get_post_meta($v->ID , 'pagelayer-data')){
745 - $is_pagelayer = true;
746 - }
747 -
748 - if(preg_match('/(\[pl_audio|pagelayer\/pl_audio)/is', $v->post_content)){
749 - $is_audio = true;
750 - }
751 - }
752 - }
753 -
754 - // Enqueue the FRONTEND CSS
755 - if((!empty($post->ID) && get_post_meta($post->ID , 'pagelayer-data')) || pagelayer_has_blocks() || $is_pagelayer || $force){
756 -
757 - // We dont need the auto <p> and <br> as they interfere with us
758 - remove_filter('the_content', 'wpautop');
759 -
760 - // No need to add curly codes to the content
761 - remove_filter('the_content', 'wptexturize');
762 -
763 - pagelayer_load_shortcodes();
764 -
765 - // Load global colors and fonts
766 - pagelayer_load_global_palette();
767 -
768 - $pagelayer->cache['enqueue_frontend'] = true;
769 -
770 - // Load the global styles
771 - add_action('wp_head', 'pagelayer_global_js', 2);
772 -
773 - $premium_js = apply_filters('pagelayer_add_give_js', '');
774 - $premium_css = apply_filters('pagelayer_add_give_css', '');
775 -
776 - // Load this For audio widget
777 - do_action('pagelayer_load_audio_widget', $is_audio);
778 -
779 - if(pagelayer_enable_giver()){
780 -
781 - $write = '';
782 -
783 - // Dev mode - Dynamic JS and CSS
784 - if(defined('PAGELAYER_DEV') && !empty(PAGELAYER_DEV)){
785 - $write = '&write=1';
786 - }
787 -
788 - // Enqueue our Editor's Frontend JS
789 - 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);
790 -
791 - // Get list of enabled icons
792 - $icons_css = '';
793 - $icons = pagelayer_enabled_icons();
794 - foreach($icons as $icon){
795 - $icons_css .= ','.$icon.'.min.css';
796 - }
797 -
798 - 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);
799 -
800 - // Static Files
801 - }else{
802 -
803 - wp_register_script('pagelayer-frontend', (empty($premium_js) ? PAGELAYER_JS : PAGELAYER_PRO_JS).'/combined.js', array('jquery'), PAGELAYER_VERSION);
804 -
805 - wp_register_style('pagelayer-frontend', PAGELAYER_CSS.'/combined'.(!empty($premium_css) ? '.premium' : '').'.css', array(), PAGELAYER_VERSION);
806 - }
807 -
808 - wp_enqueue_script('pagelayer-frontend');
809 - wp_enqueue_style('pagelayer-frontend');
810 -
811 - // Load the global styles
812 - add_action('wp_head', 'pagelayer_global_styles', 5);
813 - add_filter('body_class', 'pagelayer_body_class', 10, 2);
814 -
815 - // Load the global styles for gutenberg
816 - if(pagelayer_is_gutenberg_editor()){
817 - add_action('admin_print_scripts', 'pagelayer_global_styles', 5);
818 - }
819 -
820 - // Load custom widgets
821 - do_action('pagelayer_custom_frontend_enqueue');
822 -
823 - }
824 -
825 -}
826 -
827 -// Load the google and custom fonts
828 -add_action('wp_footer', 'pagelayer_enqueue_fonts', 5);
829 -function pagelayer_enqueue_fonts($suffix = '-header'){
830 -
831 - global $pagelayer;
832 -
833 - if(empty($pagelayer->cache['enqueue_frontend'])){
834 - return;
835 - }
836 -
837 - $url = [];
838 - $cst = [];
839 -
840 - foreach($pagelayer->css as $k => $set){
841 -
842 - $font_family = pagelayer_isset($set, 'font-family');
843 -
844 - if(empty($font_family)){
845 - $key = str_replace(['_mobile', '_tablet'], '', $k);
846 - $font_family = isset($pagelayer->css[$key]['font-family'])? $pagelayer->css[$key]['font-family']: '';
847 - }
848 -
849 - // Fetch body font if given
850 - if(!empty($font_family)){
851 - pagelayer_load_font_family($font_family, pagelayer_isset($set, 'font-weight'), pagelayer_isset($set, 'font-style'));
852 - }
853 -
854 - }
855 -
856 - foreach($pagelayer->runtime_fonts as $font => $weights){
857 -
858 - if(in_array($font, $pagelayer->system_fonts)){
859 - continue;
860 - }
861 -
862 - if(strpos($font, '_plf')){
863 - if(!in_array($font, $pagelayer->fonts_sent)){
864 - $pagelayer->fonts_sent[] = $font;
865 - $cst[] = preg_replace('/_plf$/is', '', $font);
866 - }
867 - }else{
868 - $v = $font.':'.implode(',', $weights);
869 - if(!in_array($v, $pagelayer->fonts_sent)){
870 - $url[] = $v;
871 - $pagelayer->fonts_sent[] = $v;
872 - }
873 - }
874 - }
875 -
876 - // If no fonts are to be set, then we dont set
877 - if(!empty($url)){
878 - $fonts_url = 'https://fonts.googleapis.com/css?family='.rawurlencode(implode('|', $url));
879 -
880 - $fonts_url = apply_filters('pagelayer_google_fonts_url', $fonts_url);
881 -
882 - wp_register_style('pagelayer-google-font'.$suffix, $fonts_url, array(), PAGELAYER_VERSION);
883 - wp_enqueue_style('pagelayer-google-font'.$suffix);
884 -
885 - echo '<link rel="preload" href="'.$fonts_url.'" as="fetch" crossorigin="anonymous">';
886 - }
887 -
888 - if(empty($cst)){
889 - return;
890 - }
891 -
892 - $args = [
893 - 'post_type' => PAGELAYER_FONT_POST_TYPE,
894 - 'status' => 'publish',
895 - 'post_name__in' => $cst
896 - ];
897 -
898 - //var_dump($args);
899 -
900 - $query = get_posts($args);
901 - //var_dump($query);
902 -
903 - if(empty($query)){
904 - return;
905 - }
906 -
907 - foreach($query as $font){
908 - $meta_box_value = get_post_meta($font->ID, 'pagelayer_font_link', true);
909 - if(empty($meta_box_value)){
910 - continue;
911 - }
912 -
913 - 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>';
914 - }
915 -}
916 -
917 -// Load any header we have
918 -function pagelayer_global_js(){
919 - global $pagelayer;
920 -
921 - $pagelayer_recaptch_lang = get_option('pagelayer_google_captcha_lang');
922 - $pagelayer_recaptch_version = get_option('pagelayer_recaptcha_version', '');
923 -
924 - echo '<script>
925 -var pagelayer_ajaxurl = "'.admin_url( 'admin-ajax.php' ).'?";
926 -var pagelayer_global_nonce = "'.wp_create_nonce('pagelayer_global').'";
927 -var pagelayer_server_time = '.time().';
928 -var pagelayer_is_live = "'.pagelayer_is_live().'";
929 -var pagelayer_facebook_id = "'.get_option('pagelayer-fbapp-id').'";
930 -var pagelayer_settings = '.json_encode($pagelayer->settings).';
931 -var pagelayer_recaptch_lang = "'.(!empty($pagelayer_recaptch_lang) ? $pagelayer_recaptch_lang : '').'";
932 -var pagelayer_recaptch_version = "'.(!empty($pagelayer_recaptch_version) ? $pagelayer_recaptch_version : '').'";
933 -</script>';
934 -
935 -}
936 -
937 -// We need to handle global styles
938 -function pagelayer_load_global_css(){
939 - global $pagelayer;
940 -
941 - // Load CSS settings
942 - foreach($pagelayer->css_settings as $k => $params){
943 - $tmp_desk = '';
944 - foreach($pagelayer->screens as $sk => $sv){
945 - $suffix = (!empty($sv) ? '_'.$sv : '');
946 - $setting = empty($params['key']) ? 'pagelayer_'.$k.'_css' : $params['key'];
947 - $tmp = get_option($setting.$suffix);
948 -
949 - if($sk == 'desktop'){
950 - $tmp_desk = $tmp;
951 - }
952 -
953 - $tmp = pagelayer_sanitize_global_style($tmp, $tmp_desk, $sk);
954 -
955 - if(empty($tmp)){
956 - continue;
957 - }
958 -
959 - $pagelayer->css[$k.$suffix] = $tmp;
960 - }
961 - }
962 -
963 - // Backward compat for colors
964 - if(!empty($pagelayer->settings['color']['background']) && empty($pagelayer->css['body']['background-color'])){
965 - $pagelayer->css['body']['background-color'] = $pagelayer->settings['color']['background'];
966 - }
967 -
968 - if(!empty($pagelayer->settings['color']['text']) && empty($pagelayer->css['body']['color'])){
969 - $pagelayer->css['body']['color'] = $pagelayer->settings['color']['text'];
970 - }
971 -
972 - // Link Color
973 - if(!empty($pagelayer->settings['color']['link']) && empty($pagelayer->css['a']['color'])){
974 - $pagelayer->css['a']['color'] = $pagelayer->settings['color']['link'];
975 - }
976 -
977 - // Link Hover Color
978 - if(!empty($pagelayer->settings['color']['link-hover']) && empty($pagelayer->css['a-hover']['color'])){
979 - $pagelayer->css['a-hover']['color'] = $pagelayer->settings['color']['link-hover'];
980 - }
981 -
982 - // Headings Color
983 - if(!empty($pagelayer->settings['color']['heading'])){
984 - $htmp = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'];
985 - foreach($htmp as $k => $v){
986 - if(empty($pagelayer->css[$v]['color'])){
987 - $pagelayer->css[$v]['color'] = $pagelayer->settings['color']['heading'];
988 - }
989 - }
990 - }
991 -
992 - // Backward compat for body font
993 - if(!empty($pagelayer->settings['body_font'])){
994 - $pagelayer->settings['body']['font-family'] = $pagelayer->settings['body_font'];
995 - }
996 -}
997 -
998 -// We need to handle global styles
999 -function pagelayer_global_styles(){
1000 -
1001 - global $pagelayer, $post;
1002 -
1003 - // Load css from settings
1004 - pagelayer_load_global_css();
1005 -
1006 - $styles = '<style id="pagelayer-wow-animation-style" type="text/css">.pagelayer-wow{visibility: hidden;}</style>
1007 - <style id="pagelayer-global-styles" type="text/css">'.PHP_EOL;
1008 -
1009 - $screen_style['tablet'] = '';
1010 - $screen_style['mobile'] = '';
1011 -
1012 - // PX suffix
1013 - $pxs = ['font-size', 'letter-spacing', 'word-spacing'];
1014 - $arrays = ['padding', 'margin'];
1015 -
1016 - $styles .= ':root{';
1017 -
1018 - // Set global colors
1019 - foreach($pagelayer->global_colors as $gk => $gv){
1020 - if (isset($gv['value'])) {
1021 - $styles .= '--pagelayer-color-'.$gk.':'.$gv['value'].';';
1022 - }
1023 - }
1024 -
1025 - // Set global fonts
1026 - foreach($pagelayer->global_fonts as $gk => $gv){
1027 -
1028 - if (empty($gv['value']) || !is_array($gv['value'])) {
1029 - continue;
1030 - }
1031 -
1032 - foreach($gv['value'] as $fk => $fv){
1033 -
1034 - if(empty($fv)){
1035 - continue;
1036 - }
1037 -
1038 - $unit = in_array($fk, $pxs) ? 'px' : '';
1039 -
1040 - if(is_array($fv)){
1041 - foreach($fv as $mode => $mv){
1042 -
1043 - if(empty($mv)){
1044 - continue;
1045 - }
1046 -
1047 - $font_css = '--pagelayer-font-'.$gk.'-'.$fk.':'.$mv.$unit.';';
1048 -
1049 - if($mode == 'tablet' || $mode == 'mobile'){
1050 - $screen_style[$mode] .= ':root{'.$font_css.'}';
1051 - continue;
1052 - }
1053 -
1054 - $styles .= $font_css;
1055 - }
1056 - continue;
1057 - }
1058 -
1059 - $styles .= '--pagelayer-font-'.$gk.'-'.$fk .':'.$fv.$unit.';';
1060 - }
1061 - }
1062 -
1063 - $styles .= '}'.PHP_EOL;
1064 -
1065 - // Style for only child row holder
1066 - $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;
1067 -
1068 - if(!pagelayer_is_live() && !pagelayer_is_gutenberg_editor()){
1069 -
1070 - // Set responsive value
1071 - $styles .= '@media (min-width: '.($pagelayer->settings['tablet_breakpoint'] + 1).'px){
1072 - .pagelayer-hide-desktop{
1073 - display:none !important;
1074 - }
1075 - }
1076 -
1077 - @media (max-width: '.$pagelayer->settings['tablet_breakpoint'].'px) and (min-width: '.($pagelayer->settings['mobile_breakpoint'] + 1).'px){
1078 - .pagelayer-hide-tablet{
1079 - display:none !important;
1080 - }
1081 - .pagelayer-wp-menu-holder[data-drop_breakpoint="tablet"] .pagelayer-wp_menu-ul{
1082 - display:none;
1083 - }
1084 - }
1085 -
1086 - @media (max-width: '.$pagelayer->settings['mobile_breakpoint'].'px){
1087 - .pagelayer-hide-mobile{
1088 - display:none !important;
1089 - }
1090 - .pagelayer-wp-menu-holder[data-drop_breakpoint="mobile"] .pagelayer-wp_menu-ul{
1091 - display:none;
1092 - }
1093 - }'.PHP_EOL;
1094 -
1095 - }
1096 -
1097 - // Setup CSS as per post. This overright the global styles
1098 - foreach($pagelayer->css_settings as $k => $params){
1099 - $tmp_desk = '';
1100 - foreach($pagelayer->screens as $sk => $sv){
1101 - $suffix = (!empty($sv) ? '_'.$sv : '');
1102 - $setting = empty($params['key']) ? 'pagelayer_'.$k.'_css_'.@$post->post_type : $params['key'].'_'.@$post->post_type;
1103 - $tmp = get_option($setting.$suffix);
1104 -
1105 - if($sk == 'desktop'){
1106 - $tmp_desk = $tmp;
1107 - }
1108 -
1109 - $tmp = pagelayer_sanitize_global_style($tmp, $tmp_desk, $sk);
1110 -
1111 - if(empty($tmp)){
1112 - continue;
1113 - }
1114 -
1115 - if(!empty($pagelayer->css[$k.$suffix])){
1116 -
1117 - $typo_on = false;
1118 - $_typo = array();
1119 - $typo = $pagelayer->typo_props;
1120 -
1121 - // Check if all font properties are empty then we do not overright the global typo styles
1122 - foreach($typo as $prop){
1123 -
1124 - if(!empty($tmp[$prop])){
1125 - $typo_on = true;
1126 - }
1127 -
1128 - $_typo[$prop] = empty($tmp[$prop]) ? '' : $tmp[$prop];
1129 - }
1130 -
1131 - foreach($tmp as $tkk => $tvv){
1132 -
1133 - $tvv_is_empty = is_array($tvv) ? pagelayer_is_empty_array($tvv) : empty($tvv);
1134 -
1135 - // Skip update for empty value and if type is empty
1136 - if($tvv_is_empty || in_array($tkk, $typo)){
1137 - continue;
1138 - }
1139 -
1140 - $pagelayer->css[$k.$suffix][$tkk] = $tvv;
1141 - }
1142 -
1143 - if($typo_on){
1144 - $pagelayer->css[$k.$suffix] = array_merge($pagelayer->css[$k.$suffix], $_typo);
1145 - }
1146 -
1147 - continue;
1148 - }
1149 -
1150 - $pagelayer->css[$k.$suffix] = $tmp;
1151 - }
1152 - }
1153 -
1154 - // If is not loaded then the pagelayer_parse_vars, pagelayer_css_render not working
1155 - if(empty($pagelayer->customizer_params)){
1156 - pagelayer_load_shortcodes();
1157 - }
1158 -
1159 - // Customizer CSS
1160 - foreach($pagelayer->customizer_params as $prop => $param){
1161 -
1162 - if(empty($param['customizer_css']) || empty($param['css'])){
1163 - continue;
1164 - }
1165 -
1166 - if(!is_array($param['css'])){
1167 - $param['css'] = array($param['css']);
1168 - }
1169 -
1170 - $customize_el = array();
1171 - $customize_el['atts'] = $pagelayer->customizer_mods;
1172 -
1173 - // Get Image URL
1174 - $attachment = ($param['type'] == 'image') ? pagelayer_image(@$pagelayer->customizer_mods[$prop]) : '';
1175 -
1176 - if(!empty($attachment)){
1177 - foreach($attachment as $k => $v){
1178 - $customize_el['tmp'][$prop.'-'.$k] = $v;
1179 - }
1180 - }
1181 -
1182 - // Loop the modes and check for values
1183 - foreach($pagelayer->screens as $sk => $sv){
1184 -
1185 - $suffix = (!empty($sv) ? '_'.$sv : '');
1186 - $M_prop = $prop.$suffix;
1187 -
1188 - // Any value ?
1189 - if(empty($pagelayer->customizer_mods[$M_prop])){
1190 - continue;
1191 - }
1192 -
1193 - // Loop through
1194 - foreach($param['css'] as $k => $v){
1195 -
1196 - // Make the selector
1197 - $selector = (!is_numeric($k) && !empty($k) ? $k : 'body.pagelayer-body');
1198 -
1199 - // Make the CSS
1200 - $customize_css = $selector.'{'. rtrim( trim( pagelayer_css_render($v, $pagelayer->customizer_mods[$M_prop], @$param['sep']) ), ';' ) .'}' ;
1201 -
1202 - $customize_css = pagelayer_parse_vars($customize_css, $customize_el);
1203 -
1204 - if($sk == 'tablet'){
1205 - $screen_style['tablet'] .= $customize_css;
1206 - continue;
1207 - }
1208 -
1209 - if($sk == 'mobile'){
1210 - $screen_style['mobile'] .= $customize_css;
1211 - continue;
1212 - }
1213 -
1214 - $styles .= $customize_css;
1215 - }
1216 -
1217 - }
1218 - }
1219 -
1220 - // Loop CSS settings
1221 - foreach($pagelayer->css as $k => $v){
1222 -
1223 - $r = [];
1224 -
1225 - foreach($pagelayer->css[$k] as $kk => $vv){
1226 -
1227 - if(empty($vv)){
1228 - continue;
1229 - }
1230 -
1231 - if(in_array($kk, $arrays)){
1232 - $unit = 'px';
1233 -
1234 - if(!empty($vv['unit'])){
1235 - $unit = $vv['unit'];
1236 - unset($vv['unit']);
1237 - }
1238 -
1239 - $vv = array_filter($vv, function($value){ return !empty($value);});
1240 - if(empty($vv)){
1241 - continue;
1242 - }
1243 -
1244 - $skel = [0, 0, 0, 0];
1245 - $vv = array_replace($skel, $vv);
1246 - $vv = implode($unit.' ', $vv).$unit;
1247 - }
1248 -
1249 - $r[] = $kk.':'.$vv.(in_array($kk, $pxs) && strripos($vv, 'var(') === false ? 'px' : '');
1250 -
1251 - }
1252 -
1253 - if(empty($r)){
1254 - continue;
1255 - }
1256 -
1257 - $matches = [];
1258 - preg_match('/_(mobile|tablet)$/is', $k, $matches);
1259 - $key = str_replace(['_mobile', '_tablet'], '', $k);
1260 - $screen = isset($matches[1]) ? $matches[1] : '';
1261 -
1262 - //echo $key.' - '.$k;pagelayer_print($matches);
1263 -
1264 - $params = $pagelayer->css_settings[$key];
1265 -
1266 - $sel = !isset($params['sel']) ? ($key == 'body' ? '' : $key) : $params['sel'];
1267 -
1268 - $style = 'body.pagelayer-body '.$sel.'{'.implode(';', $r)."}\n";
1269 -
1270 - // Mobile or tablet ?
1271 - if(!empty($screen)){
1272 - $screen_style[$screen] .= $style;
1273 - }else{
1274 - $styles .= $style;
1275 - }
1276 - }
1277 -
1278 -// Tablet Styles
1279 -$styles .= '@media (max-width: '.$pagelayer->settings['tablet_breakpoint'].'px){
1280 - [class^="pagelayer-offset-"],
1281 - [class*=" pagelayer-offset-"] {
1282 - margin-left: 0;
1283 - }
1284 -
1285 - .pagelayer-row .pagelayer-col {
1286 - margin-left: 0;
1287 - width: 100%;
1288 - }
1289 - .pagelayer-row.pagelayer-gutters .pagelayer-col {
1290 - margin-bottom: 16px;
1291 - }
1292 - .pagelayer-first-sm {
1293 - order: -1;
1294 - }
1295 - .pagelayer-last-sm {
1296 - order: 1;
1297 - }
1298 -
1299 -'.$screen_style['tablet'].'
1300 -}'.PHP_EOL;
1301 -
1302 -// Any mobile style ?
1303 -if(!empty($screen_style['mobile'])){
1304 - $styles .= '@media (max-width: '.$pagelayer->settings['mobile_breakpoint'].'px){
1305 -'.$screen_style['mobile'].'}'.PHP_EOL;
1306 -}
1307 -
1308 - $styles .= PHP_EOL.'</style>';
1309 -
1310 - // Lets just build a temporary list of fonts so that we can add prefetch !
1311 - pagelayer_enqueue_fonts();
1312 -
1313 - if(!empty($pagelayer->runtime_fonts)){
1314 - echo '<link rel="dns-prefetch" href="https://fonts.gstatic.com">
1315 -<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="anonymous">';
1316 - }
1317 -
1318 - echo $styles;
1319 -}
1320 -
1321 -function pagelayer_body_class($classes, $class){
1322 - $classes[] = 'pagelayer-body';
1323 - return $classes;
1324 -}
1325 -
1326 -// Load the live editor if needed
1327 -// Changed this hook wp_enqueue_scripts to Template_include to make block theme compatibility
1328 -add_action('template_include', 'pagelayer_load_live');
1329 -function pagelayer_load_live($template){
1330 -
1331 - global $post, $pagelayer;
1332 -
1333 - $pagelayer->load_live_errors = array();
1334 -
1335 - // If its not live editing then stop
1336 - if(!pagelayer_is_live_iframe($pagelayer->load_live_errors)){
1337 -
1338 - // Is it the live mode then lets throw an error ?
1339 - if(pagelayer_optreq('pagelayer-iframe')){
1340 - add_action('wp_head', 'pagelayer_load_live_errors', 999);
1341 - }
1342 -
1343 - return $template;
1344 - }
1345 -
1346 - // Are you allowed to edit ?
1347 - if(!pagelayer_user_can_edit($post->ID)){
1348 - return $template;
1349 - }
1350 -
1351 - // Load the editor class
1352 - include_once(PAGELAYER_DIR.'/main/live.php');
1353 -
1354 - // Call the constructor
1355 - $pl_editor = new PageLayer_LiveEditor();
1356 -
1357 - return $template;
1358 -}
1359 -
1360 -// Show the live errors if any
1361 -function pagelayer_load_live_errors(){
1362 -
1363 - global $post, $pagelayer;
1364 -
1365 - // Any errors ?
1366 - if(empty($pagelayer->load_live_errors)){
1367 - return;
1368 - }
1369 -
1370 - echo '<script>
1371 -alert("'.str_replace('"', '\\"', implode("\n", $pagelayer->load_live_errors)).'");
1372 -</script>';
1373 -
1374 -}
1375 -
1376 -// If we are doing ajax and its a pagelayer ajax
1377 -if(wp_doing_ajax()){
1378 - include_once(PAGELAYER_DIR.'/main/ajax.php');
1379 -}
1380 -
1381 -// Show the backend editor options
1382 -add_action('edit_form_after_title', 'pagelayer_after_title', 10);
1383 -function pagelayer_after_title(){
1384 -
1385 - global $post;
1386 -
1387 - // Get the current screen
1388 - $current_screen = get_current_screen();
1389 -
1390 - // For gutenberg
1391 - if(method_exists($current_screen, 'is_block_editor') && $current_screen->is_block_editor()){
1392 -
1393 - // Add the code in the footer
1394 - add_action('admin_footer', 'pagelayer_gutenberg_after_title');
1395 -
1396 - return;
1397 - }
1398 -
1399 - // Is pagelayer supposed to edit this ?
1400 - if(!pagelayer_user_can_edit($post)){
1401 - return;
1402 - }
1403 -
1404 - $link = pagelayer_shortlink($post->ID).'&pagelayer-live=1';
1405 -
1406 - echo '
1407 -<div id="pagelayer-editor-button-row" style="margin-top:15px; display:inline-block;">
1408 - <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;">
1409 - <img src="'.PAGELAYER_URL.'/images/pagelayer-logo-40.png" width="22" style="margin-right:4px" /> <span>'.__('Edit with Pagelayer').'</span>
1410 - </a>
1411 -</div>';
1412 -
1413 -}
1414 -
1415 -function pagelayer_gutenberg_after_title(){
1416 -
1417 - global $post;
1418 -
1419 - // Is pagelayer supposed to edit this ?
1420 - if(!pagelayer_user_can_edit($post)){
1421 - return;
1422 - }
1423 -
1424 - $link = pagelayer_shortlink($post->ID).'&pagelayer-live=1';
1425 -
1426 - echo '
1427 -<div id="pagelayer-editor-button-row" style="margin-left:15px; display:none">
1428 - <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;">
1429 - <img src="'.PAGELAYER_URL.'/images/pagelayer-logo-40.png" align="top" width="22" style="margin-right:4px"/> <span>'.__('Edit with Pagelayer').'</span>
1430 - </a>
1431 -</div>
1432 -
1433 -<script type="text/javascript">
1434 -jQuery(document).ready(function(){
1435 -
1436 - var pagelayer_timer;
1437 - var pagelayer_button = function(){
1438 - var button = jQuery("#pagelayer-editor-button-row");
1439 - var g = jQuery(".edit-post-header-toolbar");
1440 - if(g.length < 1){
1441 - return;
1442 - }
1443 - button.detach();
1444 - //console.log(button);
1445 - g.parent().append(button);
1446 - button.show();
1447 - clearInterval(pagelayer_timer);
1448 - }
1449 - pagelayer_timer = setInterval(pagelayer_button, 100);
1450 -});
1451 -</script>';
1452 -
1453 -}
1454 -
1455 -// Handle Old Slug URL redirect for live link
1456 -add_filter( 'old_slug_redirect_url', 'pagelayer_old_slug_redirect', 10, 1);
1457 -function pagelayer_old_slug_redirect($link){
1458 -
1459 - if(pagelayer_optreq('pagelayer-live')){
1460 - $link = add_query_arg('pagelayer-live', '1', $link);
1461 - }
1462 -
1463 - return $link;
1464 -}
1465 -
1466 -// Clone Post
1467 -add_action('admin_action_pagelayer_clone_post', 'pagelayer_clone_post');
1468 -function pagelayer_clone_post(){
1469 -
1470 - // Nonce verification
1471 - check_admin_referer('pagelayer-options');
1472 -
1473 - // Get the original post id
1474 - $post_id = (int) $_REQUEST['post'];
1475 - $post = get_post( $post_id );
1476 -
1477 - // If post data exists, create the post clone
1478 - if(empty($post)){
1479 - wp_die('No post found');
1480 - }
1481 -
1482 - if(!current_user_can('edit_post', $post->ID)){
1483 - wp_die('You don\'t have access to clone this post.');
1484 - }
1485 -
1486 - $current_user = wp_get_current_user();
1487 - $new_post_author = $current_user->ID;
1488 -
1489 - unset($post->ID);
1490 - $post->post_author = $new_post_author;
1491 - $post->post_name = '';
1492 - $post->post_status = 'draft';
1493 - $post->post_title = $post->post_title.' Clone';
1494 - $post->post_date = '';
1495 - $post->post_date_gmt = '';
1496 - $post->guid = '';
1497 -
1498 - $new_post_id = wp_insert_post( $post );
1499 -
1500 - if(empty($new_post_id)){
1501 - wp_die('Post creation failed, could not find original post: ' . $post_id);
1502 - }
1503 -
1504 - // Get all current post terms and set them to the new post draft
1505 - $taxonomies = get_object_taxonomies($post->post_type);
1506 - foreach ($taxonomies as $taxonomy) {
1507 - $post_terms = wp_get_object_terms($post_id, $taxonomy, array('fields' => 'slugs'));
1508 - wp_set_object_terms($new_post_id, $post_terms, $taxonomy, false);
1509 - }
1510 -
1511 - // Clone all post meta info
1512 - $post_meta_infos = get_post_meta($post_id);
1513 - if (count($post_meta_infos) > 0) {
1514 - foreach ($post_meta_infos as $meta_key => $meta_value){
1515 - add_post_meta($new_post_id, $meta_key, wp_slash( maybe_unserialize($meta_value[0]) ));
1516 - }
1517 - }
1518 -
1519 - // Finally, redirect to the edit post screen for the new draft
1520 - wp_redirect( get_edit_post_link($new_post_id, '') );
1521 - exit;
1522 -
1523 -}
1524 -
1525 -// Add the clone link to action list for post_row_actions
1526 -add_filter('post_row_actions', 'pagelayer_clone_post_link', 10, 2);
1527 -add_filter('page_row_actions', 'pagelayer_clone_post_link', 10, 2);
1528 -function pagelayer_clone_post_link( $actions, $post ) {
1529 - if (current_user_can('edit_posts') && $post->post_status !== 'trash' && !defined('SITEPAD') && get_option('pagelayer_disable_clone') != 1) {
1530 - $actions['clone'] = '<a href="'.wp_nonce_url('admin.php?action=pagelayer_clone_post&post='.$post->ID, 'pagelayer-options') . '" rel="permalink">'.__( 'Clone', 'pagelayer') .'</a>';
1531 - }
1532 - return $actions;
1533 -}
1534 -
1535 -add_filter( 'post_row_actions', 'pagelayer_quick_link', 10, 2 );
1536 -add_filter( 'page_row_actions', 'pagelayer_quick_link', 10, 2 );
1537 -function pagelayer_quick_link($actions, $post){
1538 - global $pagelayer;
1539 -
1540 - // Some woocommerce pages are not having ID
1541 - if(empty($post->ID)){
1542 - return $actions;
1543 - }
1544 -
1545 - // Is pagelayer supposed to edit this ?
1546 - if(!pagelayer_user_can_edit($post)){
1547 - return $actions;
1548 - }
1549 -
1550 - $link = pagelayer_shortlink($post->ID).'&pagelayer-live=1';
1551 -
1552 - $actions['pagelayer'] = '<a href="'.esc_url( $link ).'">'.__( 'Edit using Pagelayer', 'pagelayer') .'</a>';
1553 -
1554 - return $actions;
1555 -}
1556 -
1557 -// Add settings link on plugin page
1558 -add_filter('plugin_action_links_pagelayer/pagelayer.php', 'pagelayer_plugin_action_links');
1559 -function pagelayer_plugin_action_links($links){
1560 -
1561 - if(!defined('PAGELAYER_PREMIUM')){
1562 - $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>';
1563 - }
1564 -
1565 - $settings_link = '<a href="admin.php?page=pagelayer">Settings</a>';
1566 - array_unshift($links, $settings_link);
1567 -
1568 - return $links;
1569 -}
1570 -
1571 -// Add custom header
1572 -add_action('wp_head', 'pagelayer_add_custom_head', 102);
1573 -function pagelayer_add_custom_head(){
1574 - global $post;
1575 -
1576 - $global_code = wp_unslash( get_option('pagelayer_header_code') );
1577 -
1578 - if(!empty($post)){
1579 - $header_code = get_post_meta($post->ID , 'pagelayer_header_code', true);
1580 - }
1581 -
1582 - if(!empty($global_code)){
1583 - echo $global_code."\n";
1584 - }
1585 -
1586 - if(!empty($header_code)){
1587 - echo $header_code."\n";
1588 - }
1589 -
1590 -}
1591 -
1592 -// Add custom body
1593 -add_action('wp_body_open', 'pagelayer_body_open');
1594 -function pagelayer_body_open(){
1595 - global $post;
1596 -
1597 - $global_code = wp_unslash( get_option('pagelayer_body_open_code') );
1598 -
1599 - if(!empty($post)){
1600 - $body_code = get_post_meta($post->ID , 'pagelayer_body_open_code', true);
1601 - }
1602 -
1603 - if(!empty($global_code)){
1604 - echo $global_code."\n";
1605 - }
1606 -
1607 - if(!empty($body_code)){
1608 - echo $body_code."\n";
1609 - }
1610 -
1611 -}
1612 -
1613 -// Add custom footer
1614 -add_action('wp_footer', 'pagelayer_add_custom_footer');
1615 -function pagelayer_add_custom_footer(){
1616 - global $post, $pagelayer;
1617 -
1618 - if(!empty($pagelayer->localScript)){
1619 -
1620 - //Add local Script to variable to footer
1621 - wp_register_script('pagelayer-localScript', false, true);
1622 - wp_localize_script('pagelayer-localScript','pagelayer_local_scripts', $pagelayer->localScript);
1623 - wp_enqueue_script( 'pagelayer-localScript');
1624 - }
1625 -
1626 - if($pagelayer->append_yt_api){
1627 - wp_register_script('pagelayer-youtube-script',"https://www.youtube.com/iframe_api", array(), PAGELAYER_VERSION, true);
1628 - wp_enqueue_script('pagelayer-youtube-script');
1629 -
1630 - }
1631 -
1632 - $global_code = wp_unslash( get_option('pagelayer_footer_code') );
1633 -
1634 - if(!empty($post)){
1635 - $footer_code = get_post_meta($post->ID , 'pagelayer_footer_code', true);
1636 - }
1637 -
1638 - if(!empty($global_code)){
1639 - echo $global_code."\n";
1640 - }
1641 -
1642 - if(!empty($footer_code)){
1643 - echo $footer_code."\n";
1644 - }
1645 -
1646 -
1647 -}
1648 -
1649 -// Handle Logout Redirect here
1650 -add_action('wp_logout', 'pagelayer_after_logout');
1651 -function pagelayer_after_logout($user_id){
1652 -
1653 - // Get the URL
1654 - $url = get_user_option('pagelayer_logout_url', $user_id);
1655 -
1656 - // Now blank it
1657 - update_user_option($user_id, 'pagelayer_logout_url', '');
1658 -
1659 - // We will redirect if we have the given item set.
1660 - if(!empty($url)){
1661 - wp_redirect( $url );
1662 - exit();
1663 - }
1664 -
1665 -}
1666 -
1667 -// Replace Media
1668 -$pagelayer_media_replace = get_option( 'pagelayer_disable_media_replace');
1669 -if(empty($pagelayer_media_replace)){
1670 -
1671 -// Add URL to Replace Meda
1672 -add_filter('media_row_actions', 'pagelayer_add_media_action', 10, 2);
1673 -function pagelayer_add_media_action($actions, $post){
1674 -
1675 - $url = admin_url('upload.php');
1676 - $url = add_query_arg(array(
1677 - 'page' => 'pagelayer_replace_media',
1678 - 'id' => $post->ID,
1679 - ), $url);
1680 -
1681 - $actions['pagelayer_replace_media'] = '<a href="'.$url.'" rel="permalink">'.esc_html__('Replace media', 'pagelayer').'</a>';
1682 -
1683 - return $actions;
1684 -
1685 -}
1686 -
1687 -}
1688 -
1689 -// Replace Media Function
1690 -function pagelayer_replace_media(){
1691 -
1692 - include_once(PAGELAYER_DIR.'/main/replace-media.php');
1693 -
1694 - pagelayer_replace_page();
1695 -
1696 -}
1697 -
1698 -// Hide admin bar
1699 -add_action( 'init', 'pagelayer_hide_admin_bar');
1700 -function pagelayer_hide_admin_bar(){
1701 -
1702 - // Is it the live mode ?
1703 - if(!pagelayer_optreq('pagelayer-live', false) || !pagelayer_optreq('pagelayer-iframe', false)){
1704 - return false;
1705 - }
1706 -
1707 - show_admin_bar(false);
1708 -}
1709 -
1710 -// Check is gutenberg editor
1711 -function pagelayer_is_gutenberg_editor(){
1712 -
1713 - if(!function_exists('get_current_screen')){
1714 - return false;
1715 - }
1716 -
1717 - $screen = get_current_screen();
1718 -
1719 - if(empty($screen) || !method_exists($screen, 'is_block_editor')){
1720 - return false;
1721 - }
1722 -
1723 - return $screen->is_block_editor();
1724 -}
1725 -
1726 -// Pagelayer Template Loading Mechanism
1727 -include_once(PAGELAYER_DIR.'/main/template.php');
1728 -
1729 -// Convert Pagelayer widgets to gutenberg block
1730 -if(file_exists(PAGELAYER_DIR.'/main/blocks.php')){
1731 - include_once(PAGELAYER_DIR.'/main/blocks.php');
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.0');
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');
1732 1733 }