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