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

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

2,891 lines 82.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 //////////////////////////////////////////////////////////////
4 //===========================================================
5 // ajax.php
6 //===========================================================
7 // PAGELAYER
8 // Inspired by the DESIRE to be the BEST OF ALL
9 // ----------------------------------------------------------
10 // Started by: Pulkit Gupta
11 // Date: 23rd Jan 2017
12 // Time: 23:00 hrs
13 // Site: http://pagelayer.com/wordpress (PAGELAYER)
14 // ----------------------------------------------------------
15 // Please Read the Terms of use at http://pagelayer.com/tos
16 // ----------------------------------------------------------
17 //===========================================================
18 // (c)Pagelayer Team
19 //===========================================================
20 //////////////////////////////////////////////////////////////
21
22 // Are we being accessed directly ?
23 if(!defined('PAGELAYER_VERSION')) {
24 exit('Hacking Attempt !');
25 }
26
27 // Recommended Plugins Installation and Activation Action Handlers
28 // NOTE: These must be registered BEFORE the pagelayer_nonce gate below,
29 // because install/activate requests do NOT send pagelayer_nonce.
30 add_action('wp_ajax_pagelayer_install_plugin', 'pagelayer_install_recommended_plugin');
31 function pagelayer_install_recommended_plugin(){
32 check_ajax_referer('pagelayer_recommended_plugins', 'security');
33
34 if(!current_user_can('install_plugins')){
35 wp_send_json_error(array('message' => __('You do not have permission to install plugins.', 'pagelayer')));
36 }
37
38 $slug = !empty($_REQUEST['plugin']) ? sanitize_text_field(wp_unslash($_REQUEST['plugin'])) : '';
39 if(empty($slug)){
40 wp_send_json_error(array('message' => __('Plugin slug is required.', 'pagelayer')));
41 }
42
43 require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
44 require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
45 require_once ABSPATH . 'wp-admin/includes/plugin.php';
46 require_once ABSPATH . 'wp-admin/includes/file.php';
47
48 // Initialize WP_Filesystem - required before Plugin_Upgrader can write files
49 $creds = request_filesystem_credentials(site_url() . '/wp-admin/', '', false, false, null);
50 if(!WP_Filesystem($creds)){
51 wp_send_json_error(array('message' => __('Could not initialize filesystem. Please check file permissions.', 'pagelayer')));
52 }
53
54 $api = plugins_api('plugin_information', array('slug' => $slug, 'fields' => array('sections' => false)));
55
56 if(is_wp_error($api)){
57 wp_send_json_error(array('message' => $api->get_error_message()));
58 }
59
60 // Use Automatic_Upgrader_Skin (silent); buffer any stray output to keep response clean JSON
61 $skin = new \Automatic_Upgrader_Skin();
62 $upgrader = new \Plugin_Upgrader($skin);
63
64 ob_start();
65 $result = $upgrader->install($api->download_link);
66 ob_end_clean();
67
68 if(is_wp_error($result)){
69 wp_send_json_error(array('message' => $result->get_error_message()));
70 }
71 if($result === false || $result === null){
72 $error_msgs = $skin->get_upgrade_messages();
73 $msg = !empty($error_msgs) ? implode(' ', $error_msgs) : __('Plugin installation failed. Please check file permissions.', 'pagelayer');
74 wp_send_json_error(array('message' => $msg));
75 }
76
77 $all_plugins = get_plugins();
78 $installed_plugin = '';
79 foreach($all_plugins as $path => $data){
80 if(strpos($path, $slug . '/') === 0){
81 $installed_plugin = $path;
82 break;
83 }
84 }
85
86 if(empty($installed_plugin)){
87 wp_send_json_error(array('message' => __('Plugin installed but could not be located for activation.', 'pagelayer')));
88 }
89
90 $result = activate_plugin($installed_plugin);
91 if(is_wp_error($result)){
92 wp_send_json_error(array('message' => $result->get_error_message()));
93 }
94
95 wp_send_json_success(array('message' => __('Plugin installed and activated successfully.', 'pagelayer')));
96 }
97
98 add_action('wp_ajax_pagelayer_activate_plugin', 'pagelayer_activate_recommended_plugin');
99 function pagelayer_activate_recommended_plugin(){
100 check_ajax_referer('pagelayer_recommended_plugins', 'security');
101
102 if(!current_user_can('activate_plugins')){
103 wp_send_json_error(array('message' => __('You do not have permission to activate plugins.', 'pagelayer')));
104 }
105
106 $slug = !empty($_REQUEST['plugin']) ? sanitize_text_field(wp_unslash($_REQUEST['plugin'])) : '';
107 if(empty($slug)){
108 wp_send_json_error(array('message' => __('Plugin slug is required.', 'pagelayer')));
109 }
110
111 if(!function_exists('get_plugins')){
112 require_once ABSPATH . 'wp-admin/includes/plugin.php';
113 }
114
115 $all_plugins = get_plugins();
116 $plugin_path = '';
117 foreach($all_plugins as $path => $data){
118 if(strpos($path, $slug . '/') === 0){
119 $plugin_path = $path;
120 break;
121 }
122 }
123
124 if(empty($plugin_path)){
125 wp_send_json_error(array('message' => __('Plugin not found.', 'pagelayer')));
126 }
127
128 $result = activate_plugin($plugin_path);
129 if(is_wp_error($result)){
130 wp_send_json_error(array('message' => $result->get_error_message()));
131 }
132
133 wp_send_json_success(array('message' => __('Plugin activated successfully.', 'pagelayer')));
134 }
135
136 // AI Agents Connection AJAX handlers
137 // NOTE: These must be registered BEFORE the pagelayer_nonce gate below,
138 // because they use their own nonce (pagelayer_mcp_nonce) or basic auth.
139 add_action('wp_ajax_pagelayer_mcp_generate_app_password', 'pagelayer_mcp_generate_app_password');
140 add_action('wp_ajax_pagelayer_mcp_adapter_action', 'pagelayer_mcp_adapter_action');
141 add_action('wp_ajax_pagelayer_mcp_test_connection', 'pagelayer_mcp_test_connection');
142 add_action('wp_ajax_pagelayer_mcp_save_test_status', 'pagelayer_mcp_save_test_status');
143 add_action('wp_ajax_pagelayer_mcp_save_image_api_key', 'pagelayer_mcp_save_image_api_key');
144
145 // Verifies, without any HTTP round trip, the two things a loopback request would
146 // have proved: that the supplied Application Password authenticates this user,
147 // and that the Pagelayer abilities are registered. Used when the loopback itself
148 // fails (cURL timeout etc.) so the panel can still tell the user where they stand.
149 function pagelayer_mcp_verify_locally($username, $password) {
150 $result = array('password_ok' => false, 'abilities' => 0, 'message' => '');
151
152 if(!class_exists('WP_Application_Passwords')){
153 $result['message'] = __('Application Passwords are not supported on this WordPress version.', 'pagelayer');
154 return $result;
155 }
156
157 $user = get_user_by('login', $username);
158 if(!$user && is_email($username)){
159 $user = get_user_by('email', $username);
160 }
161
162 if(!$user){
163 $result['message'] = sprintf(__('No user named "%s" exists on this site.', 'pagelayer'), $username);
164 return $result;
165 }
166
167 // Core strips non-alphanumerics before comparing, so the password works with
168 // or without the readability spaces (see wp_authenticate_application_password).
169 $stripped = preg_replace('/[^a-z\d]/i', '', $password);
170
171 foreach(\WP_Application_Passwords::get_user_application_passwords($user->ID) as $item){
172 if(\WP_Application_Passwords::check_password($stripped, $item['password'])){
173 $result['password_ok'] = true;
174 break;
175 }
176 }
177
178 if(function_exists('wp_get_abilities')){
179 foreach(wp_get_abilities() as $name => $ability){
180 $name = is_string($name) ? $name : '';
181 if(strpos($name, 'pagelayer-') === 0){
182 $result['abilities']++;
183 }
184 }
185 }
186
187 if($result['password_ok']){
188 $result['message'] = sprintf(
189 __('Checked locally instead: your Application Password IS valid for "%1$s", and %2$d Pagelayer abilities are registered.', 'pagelayer'),
190 $username,
191 $result['abilities']
192 );
193 }else{
194 $result['message'] = sprintf(
195 __('Checked locally instead: the supplied Application Password does NOT match any password stored for "%s" — generate a new one below.', 'pagelayer'),
196 $username
197 );
198 }
199
200 return $result;
201 }
202
203 function pagelayer_mcp_test_connection() {
204 include_once(PAGELAYER_DIR.'/main/abilities.php');
205 check_ajax_referer('pagelayer_mcp_nonce', 'nonce');
206
207 if(!current_user_can('manage_options')){
208 wp_send_json_error(__('You do not have permission to test the connection.', 'pagelayer'));
209 }
210
211 $start = microtime(true);
212 $url = trailingslashit(home_url()) . ltrim(Pagelayer_Abilities::$ABILITIES_ENDPOINT, '/');
213
214 $username = isset($_POST['username']) ? sanitize_text_field(wp_unslash($_POST['username'])) : '';
215 $password = isset($_POST['password']) ? sanitize_text_field(wp_unslash($_POST['password'])) : '';
216
217 // Application Passwords are silently inert unless the site is on HTTPS or the
218 // environment type is "local" (wp_is_application_passwords_supported()). WP
219 // still hands out a password string in that state, so the only symptom is a
220 // 401 on every request — check it up front instead of blaming the password.
221 if(function_exists('wp_is_application_passwords_available') && !wp_is_application_passwords_available()){
222 $message = sprintf(
223 __('Application Passwords are disabled on this site, so every request is treated as anonymous (HTTP 401). WordPress only enables them over HTTPS or when the environment type is "local". This site reports %1$s and environment type "%2$s". Either serve the site over HTTPS, or add define(\'WP_ENVIRONMENT_TYPE\', \'local\'); to wp-config.php for a development site.', 'pagelayer'),
224 is_ssl() ? 'HTTPS' : 'HTTP',
225 function_exists('wp_get_environment_type') ? wp_get_environment_type() : 'unknown'
226 );
227 Pagelayer_Abilities::save_test_connection_status(false, $message);
228 wp_send_json_error(['message' => $message]);
229 }
230
231 $response = wp_remote_get($url, [
232 // wp_remote_get() defaults to a 5s timeout, which a local dev stack will
233 // blow through on a loopback request (TLS handshake plus a full second
234 // WordPress bootstrap, often with WP_DEBUG on).
235 'timeout' => 20,
236 'headers' => [
237 'Accept' => 'application/json',
238 'Authorization' => 'Basic ' . base64_encode($username . ':' . $password),
239 ],
240 'sslverify' => false,
241 ]);
242
243 $elapsed = round((microtime(true) - $start) * 1000);
244
245 if(is_wp_error($response)){
246 // The loopback never completed, so it told us nothing about the HTTP path.
247 // Verify in-process what we actually can — that the Application Password
248 // is valid and the abilities are registered — and say plainly which part
249 // is still unverified, instead of reporting a flat failure.
250 $local = pagelayer_mcp_verify_locally($username, $password);
251
252 $message = sprintf(
253 __('Could not complete the loopback request to %1$s (%2$s). %3$s %4$s', 'pagelayer'),
254 $url,
255 $response->get_error_message(),
256 $local['message'],
257 __('A loopback failure is usually the local server itself, not your setup: many dev stacks run too few PHP workers to serve a second request while this one is still open, so the site cannot call itself. Your AI client connects from outside and is not affected. Confirm from a terminal with: curl -ik -u "USERNAME:APP PASSWORD" ', 'pagelayer') . $url
258 );
259
260 Pagelayer_Abilities::save_test_connection_status(false, $message);
261 wp_send_json_error([
262 'message' => $message,
263 'local_check' => $local,
264 'loopback_failed' => true,
265 ]);
266 }
267
268 $code = wp_remote_retrieve_response_code($response);
269 $body = json_decode(wp_remote_retrieve_body($response), true);
270
271 if($code >= 200 && $code < 300 && is_array($body)){
272 $pagelayer_abilities = 0;
273 foreach($body as $ability){
274 $name = isset($ability['name']) ? $ability['name'] : (isset($ability['id']) ? $ability['id'] : '');
275 if(is_string($name) && strpos($name, 'pagelayer-') === 0){
276 $pagelayer_abilities++;
277 }
278 }
279
280 $message = sprintf(__('Authenticated with your Application Password and discovered %1$d Pagelayer abilities in %2$dms. Your site is ready to connect.', 'pagelayer'), $pagelayer_abilities, $elapsed);
281
282 Pagelayer_Abilities::save_test_connection_status(true, $message);
283
284 wp_send_json_success([
285 'message' => $message,
286 'abilities' => $pagelayer_abilities,
287 'elapsed_ms' => $elapsed,
288 ]);
289 }
290
291 // A 401 means the request arrived with no authenticated user at all; a 403
292 // means it authenticated but lacked the capability. Those need different fixes.
293 if($code === 401){
294 $auth_header_seen = (bool) (function_exists('wp_get_authorization_header') ? wp_get_authorization_header() : (!empty($_SERVER['HTTP_AUTHORIZATION']) || !empty($_SERVER['REDIRECT_HTTP_AUTHORIZATION'])));
295
296 $message = __('The abilities endpoint treated the request as anonymous (HTTP 401), so the Application Password never authenticated. The two usual causes are: (1) the password was revoked or mistyped — generate a new one below; or (2) your web server is stripping the Authorization header before PHP sees it. For Apache, ensure the "RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]" line is present in .htaccess and that AllowOverride permits it. For nginx/FastCGI, ensure the Authorization header is forwarded to PHP-FPM.', 'pagelayer');
297
298 if(!$auth_header_seen){
299 $message .= ' ' . __('Note: this admin request itself arrived without an Authorization header, which is normal here but means the stripping check is inconclusive — test with curl -u user:app-password against the endpoint to confirm.', 'pagelayer');
300 }
301
302 Pagelayer_Abilities::save_test_connection_status(false, $message);
303 wp_send_json_error([
304 'message' => $message,
305 ]);
306 }
307
308 if($code === 403){
309 $message = __('The Application Password authenticated, but the account was refused (HTTP 403). Check that this user still has the required capabilities, and that no security plugin is blocking REST API requests.', 'pagelayer');
310 Pagelayer_Abilities::save_test_connection_status(false, $message);
311 wp_send_json_error([
312 'message' => $message,
313 ]);
314 }
315
316 $message = sprintf(__('The abilities endpoint responded with status %1$d. Check the MCP Adapter is active and try again.', 'pagelayer'), $code);
317 Pagelayer_Abilities::save_test_connection_status(false, $message);
318 wp_send_json_error([
319 'message' => $message,
320 ]);
321 }
322
323 function pagelayer_mcp_save_test_status() {
324 include_once(PAGELAYER_DIR.'/main/abilities.php');
325 check_ajax_referer('pagelayer_mcp_nonce', 'nonce');
326
327 if(!current_user_can('manage_options')){
328 wp_send_json_error(__('You do not have permission to do that.', 'pagelayer'));
329 }
330
331 $ok = !empty($_POST['ok']);
332 $message = !empty($_POST['message']) ? sanitize_text_field(wp_unslash($_POST['message'])) : '';
333
334 Pagelayer_Abilities::save_test_connection_status($ok, $message);
335
336 wp_send_json_success();
337 }
338
339 function pagelayer_mcp_save_image_api_key() {
340 check_ajax_referer('pagelayer_mcp_nonce', 'nonce');
341
342 if(!current_user_can('manage_options')){
343 wp_send_json_error(array('message' => __('You do not have permission to do that.', 'pagelayer')));
344 }
345
346 $provider = !empty($_POST['provider']) ? sanitize_key(wp_unslash($_POST['provider'])) : '';
347 $api_key = !empty($_POST['api_key']) ? sanitize_text_field(wp_unslash($_POST['api_key'])) : '';
348
349 if(empty($api_key)){
350 wp_send_json_error(array('message' => __('An API key is required.', 'pagelayer')));
351 }
352
353 if($provider !== 'pexels'){
354 wp_send_json_error(array('message' => __('Unsupported image provider.', 'pagelayer')));
355 }
356
357 update_option('pagelayer_pexels_api_key', $api_key, false);
358
359 wp_send_json_success(array('message' => __('Image search API key saved.', 'pagelayer')));
360 }
361
362 function pagelayer_mcp_generate_app_password() {
363 include_once(PAGELAYER_DIR.'/main/abilities.php');
364 check_ajax_referer('pagelayer_mcp_nonce', 'nonce');
365
366 if(!current_user_can('manage_options')){
367 wp_send_json_error('Unauthorized');
368 }
369
370 $user_id = get_current_user_id();
371 if(!class_exists('WP_Application_Passwords')){
372 wp_send_json_error('Application Passwords not supported in this WP version.');
373 }
374
375 // WP_Application_Passwords::create_new_application_password() does NOT check
376 // availability, so without this the UI happily issues a password that
377 // wp_authenticate_application_password() will always reject — a "Generated"
378 // checkmark followed by a permanent 401.
379 if(function_exists('wp_is_application_passwords_available') && !wp_is_application_passwords_available()){
380 wp_send_json_error(sprintf(
381 __('Application Passwords are disabled on this site, so a generated password could never authenticate. WordPress enables them only over HTTPS or when the environment type is "local". This site reports %1$s and environment type "%2$s". Serve the site over HTTPS, or add define(\'WP_ENVIRONMENT_TYPE\', \'local\'); to wp-config.php for a development site.', 'pagelayer'),
382 is_ssl() ? 'HTTPS' : 'HTTP',
383 function_exists('wp_get_environment_type') ? wp_get_environment_type() : 'unknown'
384 ));
385 }
386
387 $passwords = \WP_Application_Passwords::get_user_application_passwords($user_id);
388 foreach($passwords as $app){
389 if(!empty($app['app_id']) && $app['app_id'] === Pagelayer_Abilities::$APP_PASSWORD_APP_ID){
390 \WP_Application_Passwords::delete_application_password($user_id, $app['uuid']);
391 }
392 }
393
394 $new_password = \WP_Application_Passwords::create_new_application_password($user_id, array(
395 'name' => Pagelayer_Abilities::$APP_PASSWORD_NAME,
396 'app_id' => Pagelayer_Abilities::$APP_PASSWORD_APP_ID,
397 ));
398
399 if(is_wp_error($new_password)){
400 wp_send_json_error($new_password->get_error_message());
401 }
402
403 wp_send_json_success(array('password' => $new_password[0]));
404 }
405
406 function pagelayer_mcp_adapter_action() {
407 include_once(PAGELAYER_DIR.'/main/abilities.php');
408 check_ajax_referer('pagelayer_mcp_nonce', 'nonce');
409
410 if(!current_user_can('manage_options')){
411 wp_send_json_error('Unauthorized');
412 }
413
414 $type = isset($_POST['type']) ? sanitize_text_field($_POST['type']) : '';
415
416 if(!function_exists('get_plugins')){
417 require_once ABSPATH . 'wp-admin/includes/plugin.php';
418 }
419
420 if ($type === 'install') {
421 include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
422 include_once ABSPATH . 'wp-admin/includes/file.php';
423
424 // The MCP Adapter is hosted on GitHub, not WordPress.org, so fetch the download URL from the GitHub API
425 $download_url = Pagelayer_Abilities::get_mcp_adapter_download_url();
426
427 $upgrader = new \Plugin_Upgrader(new \Automatic_Upgrader_Skin());
428 $installed = $upgrader->install($download_url);
429
430 if(is_wp_error($installed)){
431 wp_send_json_error($installed->get_error_message());
432 }elseif(!$installed){
433 wp_send_json_error('Installation failed. The MCP Adapter plugin is downloaded from GitHub. Please check your server can reach github.com.');
434 }
435
436 $plugin_file = Pagelayer_Abilities::get_installed_mcp_adapter_file();
437 if($plugin_file){
438 activate_plugin($plugin_file);
439 wp_send_json_success('Installed and activated');
440 }
441 wp_send_json_success('Installed but not activated');
442
443 } elseif ($type === 'activate') {
444 $plugin_file = Pagelayer_Abilities::get_installed_mcp_adapter_file();
445 if($plugin_file){
446 $result = activate_plugin($plugin_file);
447 if(is_wp_error($result)){
448 wp_send_json_error($result->get_error_message());
449 }
450 wp_send_json_success('Activated');
451 }
452 wp_send_json_error('Plugin not found');
453 }
454
455 wp_send_json_error('Invalid action');
456 }
457
458 // Is the nonce there ?
459 if(empty($_REQUEST['pagelayer_nonce'])){
460 return;
461 }
462
463 pagelayer_memory_limit(128);
464
465 // The ajax handler
466 add_action('wp_ajax_pagelayer_wp_widget', 'pagelayer_wp_widget_ajax');
467 function pagelayer_wp_widget_ajax(){
468
469 global $pagelayer;
470
471 // Some AJAX security
472 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
473
474 if(!current_user_can('edit_theme_options')){
475 $ret['error'][] = __pl('no_permission');
476 pagelayer_json_output($ret);
477 }
478
479 pagelayer_load_shortcodes();
480
481 header('Content-Type: application/json');
482
483 $ret = [];
484 $tag = @$_POST['tag'];
485 //pagelayer_print($pagelayer->shortcodes[$tag]);
486
487 // No tag ?
488 if(empty($pagelayer->shortcodes[$tag])){
489 $ret['error'][] = __pl('no_tag');
490 pagelayer_json_output($ret);
491 }
492
493 // Include the widgets
494 $widgets = ABSPATH . 'site-admin/includes/widgets.php';
495 $widgets = file_exists($widgets) ? $widgets : ABSPATH . 'wp-admin/includes/widgets.php';
496 require_once($widgets);
497
498 $class = $pagelayer->shortcodes[$tag]['widget'];
499
500 // Check the widget class exists ?
501 if(empty($class) || !class_exists($class)){
502 $ret['error'][] = __pl('no_widget_class');
503 pagelayer_json_output($ret);
504 }
505
506 $instance = [];
507 $widget = new $class();
508 $widget->_set('pagelayer-widget-1234567890');
509
510 // Is there any existing data ?
511 if(!empty($_POST['widget_data'])){
512 $json = json_decode(stripslashes($_POST['widget_data']), true);
513 //pagelayer_print($json);die();
514 if(!empty($json)){
515 $instance = $json;
516 }
517 }
518
519 // Are there any form values ?
520 if(!empty($_POST['values'])){
521 parse_str(stripslashes($_POST['values']), $data);
522 //pagelayer_print($data);die();
523
524 // Any data ?
525 if(!empty($data)){
526
527 // Rss widget checkboxes fix
528 if(!empty($data['widget-rss'])){
529 $data['widget-rss']['pagelayer-widget-1234567890']['show_summary'] = empty($data['widget-rss']['pagelayer-widget-1234567890']['show_summary'])? 0 : 1;
530 $data['widget-rss']['pagelayer-widget-1234567890']['show_author'] = empty($data['widget-rss']['pagelayer-widget-1234567890']['show_author'])? 0 : 1;
531 $data['widget-rss']['pagelayer-widget-1234567890']['show_date'] = empty($data['widget-rss']['pagelayer-widget-1234567890']['show_date'])? 0 : 1;
532 }
533
534 // First key is useless
535 $data = current($data);
536
537 // Do we still have valid data ?
538 if(!empty($data)){
539
540 // 2nd key is useless and just over-ride instance
541 $instance = current($data);
542
543 }
544 }
545 }
546
547 // Settings instance For Text widget
548 if($widget->id_base == 'text'){
549 $instance['visual'] = false;
550 $instance['legacy'] = false;
551 }
552
553 // Get the form
554 ob_start();
555 $widget->form($instance);
556 $ret['form'] = ob_get_contents();
557 ob_end_clean();
558
559 // Get the html
560 ob_start();
561 $widget->widget([], $instance);
562 $ret['html'] = ob_get_contents();
563 ob_end_clean();
564
565 // Widget data to set
566 if(!empty($instance)){
567 $ret['widget_data'] = $instance;
568 }
569
570 // Custom html widget form elements
571 if(!empty($widget) && $widget->name=='Custom HTML'){
572 $custom_html = explode('>', $ret['form']);
573
574 $custom_html[0] = '<label for="widget-custom_html-pagelayer-widget-1234567890-title">Title:</label>'.$custom_html[0];
575 $custom_html[0] = str_replace('type="hidden"', 'type="text"',$custom_html[0]);
576
577 $custom_html[1] = '<label for="widget-custom_html-pagelayer-widget-1234567890-content">Content:</label>'.$custom_html[1];
578 $custom_html[1] = str_replace('hidden', '', $custom_html[1]);
579
580 $ret['form'] = implode('>', $custom_html);
581 }
582
583 pagelayer_json_output($ret);
584
585 }
586
587 // Build with AI — wrappers; generation/settings logic lives in Pagelayer_AI_Controller
588 add_action('wp_ajax_pagelayer_ai_generate', 'pagelayer_ai_generate');
589 function pagelayer_ai_generate(){
590
591 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
592
593 $done = [];
594
595 if(!current_user_can('edit_posts')){
596 $done['error'][] = __pl('no_permission');
597 pagelayer_json_output($done);
598 }
599
600 $ctrl = Pagelayer_AI_Controller::get_instance();
601 $res = $ctrl->process_generate();
602
603 if(is_wp_error($res)){
604 $done['error'] = $res->get_error_message();
605 pagelayer_json_output($done);
606 }
607
608 $done = is_array($res) ? $res : [];
609 if(!isset($done['success'])){
610 $done['success'] = true;
611 }
612 pagelayer_json_output($done);
613 }
614
615 add_action('wp_ajax_pagelayer_ai_settings', 'pagelayer_ai_settings');
616 function pagelayer_ai_settings(){
617
618 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
619
620 $done = [];
621
622 if(!current_user_can('edit_posts')){
623 $done['error'][] = __pl('no_permission');
624 pagelayer_json_output($done);
625 }
626
627 $ctrl = Pagelayer_AI_Controller::get_instance();
628 $res = $ctrl->process_get_settings();
629
630 if(is_wp_error($res)){
631 $done['error'] = $res->get_error_message();
632 pagelayer_json_output($done);
633 }
634
635 $done = is_array($res) ? $res : [];
636 if(!isset($done['success'])){
637 $done['success'] = true;
638 }
639 pagelayer_json_output($done);
640 }
641
642 add_action('wp_ajax_pagelayer_ai_save_settings', 'pagelayer_ai_save_settings');
643 function pagelayer_ai_save_settings(){
644
645 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
646
647 $done = [];
648
649 if(!current_user_can('edit_posts')){
650 $done['error'][] = __pl('no_permission');
651 pagelayer_json_output($done);
652 }
653
654 $ctrl = Pagelayer_AI_Controller::get_instance();
655 $res = $ctrl->process_save_settings();
656
657 if(is_wp_error($res)){
658 $done['error'] = $res->get_error_message();
659 pagelayer_json_output($done);
660 }
661
662 $done = is_array($res) ? $res : [];
663 if(!isset($done['success'])){
664 $done['success'] = true;
665 }
666 pagelayer_json_output($done);
667 }
668
669 // Update Post content
670 add_action('wp_ajax_pagelayer_save_content', 'pagelayer_save_content');
671 function pagelayer_save_content(){
672
673 // Some AJAX security
674 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
675
676 $content = $_POST['pagelayer_update_content'];
677
678 $postID = (int) $_GET['postID'];
679
680 if(empty($postID)){
681 $msg['error'] = __pl('invalid_post_id');
682 pagelayer_json_output($msg);
683 }
684
685 $_post = get_post($postID);
686
687 // Post found ?
688 if(empty($_post)){
689 $msg['error'] = __pl('invalid_post_id');
690 pagelayer_json_output($msg);
691 }
692
693 // Get the post type and its capabilities
694 $post_type = $_post->post_type;
695 $post_type_obj = get_post_type_object($post_type);
696
697 // Are you allowed to edit ?
698 if(!pagelayer_user_can_edit($postID)){
699 $msg['error'][] = __pl('no_permission');
700 pagelayer_json_output($msg);
701 }
702
703 // Check if the post exists
704 if(!empty($postID)){
705
706 $content = base64_decode($content);
707
708 /*if(!pagelayer_is_utf8($content)){
709 $content = utf8_encode($content);
710 }*/
711
712 $is_xss = pagelayer_xss_content($content);
713
714 if(!pagelayer_user_can_add_js_content() && strlen($is_xss) > 0){
715 $msg['error'][] = __pl('xss_found').' - '.$is_xss;
716 pagelayer_json_output($msg);
717 }
718
719 // Is comment mode?
720 if(pagelayer_is_comment_mode()){
721 global $pagelayer_comment_errors, $pagelayer_comment_alerts;
722 $content = pagelayer_extract_comment_atts($postID, $content);
723 }
724
725 // Add slash to save data in post
726 $content = wp_slash($content);
727
728 $post = array(
729 'ID' => $postID,
730 'post_content' => $content,
731 );
732
733 // Any properties ?
734 $allowed = ['post_title', 'post_name', 'post_excerpt', 'post_status', 'post_password', 'post_date', 'post_parent', 'menu_order'];
735
736 foreach($allowed as $k){
737 if(isset($_REQUEST[$k])){
738 $post[$k] = sanitize_text_field($_REQUEST[$k]);
739 }
740 }
741
742 // Restrict contributors from setting 'publish' or modifying unauthorized fields
743 $current_user_can_publish = current_user_can($post_type_obj->cap->publish_posts);
744 if(!$current_user_can_publish){
745 if(!in_array($post['post_status'], ['draft', 'pending'])){
746 $post['post_status'] = 'pending'; // Force pending status
747 }
748 }
749
750 if(!empty($post['post_password'])){
751 if($_REQUEST['post_sticky'] == true){
752 $msg['error'] = __pl('post_pass_with_sticky_err');
753 pagelayer_json_output($msg);
754 }
755
756 // Prevent unauthorized password protection
757 $can_protect = current_user_can($post_type_obj->cap->edit_private_posts);
758 if(!$can_protect){
759 $msg['error'][] = __pl('no_permission_to_set_password');
760 pagelayer_json_output($msg);
761 }
762 }
763
764 // Prevent unauthorized modification of `post_author`
765 if(isset($_REQUEST['post_author']) && $_REQUEST['post_author'] != $_post->post_author){
766
767 $edit_others_posts = current_user_can($post_type_obj->cap->edit_others_posts);
768
769 if($edit_others_posts){
770 $post['post_author'] = (int) $_REQUEST['post_author'];
771 }else{
772 $msg['error'][] = __pl('no_permission_to_change_author');
773 pagelayer_json_output($msg);
774 }
775 }
776
777 $post['comment_status'] = !empty($_REQUEST['comment_status']) ? 'open' : 'closed';
778 $post['ping_status'] = !empty($_REQUEST['ping_status']) ? 'open' : 'closed';
779 $post['post_status'] = empty($post['post_status']) ? $_post->post_status : $post['post_status'];
780
781 if(!empty($post['post_status']) && $post['post_status'] == 'publish'){
782
783 // Allowed to publish pages ?
784 if($_post->post_type == 'page' && !current_user_can('publish_pages')){
785 $msg['error'][] = __pl('no_publish_permission');
786 pagelayer_json_output($msg);
787 }
788
789 // Allowed to publish posts ?
790 if($_post->post_type == 'post' && !current_user_can('publish_posts')){
791 $post['post_status'] = 'pending';
792 }
793 }
794
795 if(!empty($post['post_password'])){
796 $post['post_password'] = (in_array($post['post_status'], array('pass_protected', 'publish')) ? $post['post_password'] : '');
797 $post['post_status'] = 'publish';
798 }else{
799 $post['post_status'] = ($post['post_status'] == 'pass_protected') ? 'publish' : $post['post_status'];
800 $post['post_password'] = '';
801 }
802
803 // Set post GMT time
804 if(!empty($post['post_date']) && '0000-00-00 00:00:00' !== $post['post_date']){
805 $post['post_date_gmt'] = get_gmt_from_date( $post['post_date'] );
806
807 if( in_array($post['post_status'], array('future', 'publish')) && $_post->post_date_gmt === '0000-00-00 00:00:00' ){
808 $post['edit_date'] = true;
809 }
810 }
811
812 $_REQUEST['featured_image'] = (int) $_REQUEST['featured_image'];
813 if(!empty($_REQUEST['featured_image'])){
814 set_post_thumbnail($postID, $_REQUEST['featured_image']);
815 }else{
816 delete_post_thumbnail($postID);
817 }
818
819 if(!isset($_REQUEST['post_category'])){
820 $_REQUEST['post_category'] = '';
821 }
822
823 if(!isset($_REQUEST['post_tags'])){
824 $_REQUEST['post_tags'] = '';
825 }
826
827 if($_post->post_type == 'post'){
828 $post['post_category'] = pagelayer_sanitize_text_field($_REQUEST['post_category']);
829
830 $post['tags_input'] = pagelayer_sanitize_text_field($_REQUEST['post_tags']);
831 }else{
832 $cat_name = pagelayer_post_type_category($_post->post_type);
833 if($cat_name){
834 $post['tax_input'][$cat_name] = pagelayer_sanitize_text_field($_REQUEST['post_category']);
835 }
836
837 $tag_name = pagelayer_post_type_tag($_post->post_type);
838 if($tag_name){
839 $post['tax_input'][$tag_name] = pagelayer_sanitize_text_field($_REQUEST['post_tags']);
840 }
841 }
842
843 if(isset($_REQUEST['post_sticky']) && !empty($_REQUEST['post_sticky'])){
844 stick_post( $postID );
845 }else{
846 if(is_sticky($postID)){
847 unstick_post( $postID );
848 }
849 }
850
851 // Any contact templates ?
852 if(!empty($_REQUEST['contacts']) && current_user_can('activate_plugins')){
853 update_post_meta($postID, 'pagelayer_contact_templates', $_REQUEST['contacts']);
854 }else{
855 delete_post_meta($postID, 'pagelayer_contact_templates');
856 }
857
858 // Save copyright
859 if(isset($_REQUEST['copyright']) && current_user_can('manage_options')){
860 update_option('pagelayer-copyright', wp_unslash($_REQUEST['copyright']));
861 }
862
863 // Apply a filter
864 $post = apply_filters('pagelayer_save_content', $post);
865
866 // Update the post into the database
867 $ret = wp_update_post($post, true);
868
869 // Render the post
870 //update_post_meta($postID, 'pagelayer_rendered_post', pagelayer_get_post_content($postID));
871
872 if (is_wp_error($ret)) {
873 $errors = $ret->get_error_messages();
874 $msg['error'] = __pl('post_update_err').' : '.implode('', $errors);
875 }else{
876
877 // Get the updated post
878 $_post = get_post($postID);
879
880 // Is this a Pagelayer post
881 $data = get_post_meta($postID, 'pagelayer-data', true);
882
883 if(empty($data)){
884
885 // Convert to pagelayer accessed post
886 if(!add_post_meta($postID, 'pagelayer-data', time(), true)){
887 update_post_meta($postID, 'pagelayer-data', time());
888 }
889 }
890
891 if(!empty($pagelayer_comment_alerts)){
892 $msg['comment_alerts'] = $pagelayer_comment_alerts;
893 }
894
895 if(!empty($pagelayer_comment_errors)){
896 $msg['error'][] = 'Comment Mode errrors found !';
897 $msg['comment_errors'] = $pagelayer_comment_errors;
898 }
899
900 $msg['success'] = __pl('post_update_success');
901 }
902
903 }else{
904 $msg['error'] = __pl('post_update_err');
905 }
906
907 $msg['post_status'] = (empty($_post->post_password)) ? $_post->post_status : 'pass_protected';
908
909 // Save global widgets data
910 if(!empty($_REQUEST['global_widgets'])){
911 pagelayer_save_templ_content(true);
912 }
913
914 // Save nav menu data
915 if(!empty($_REQUEST['pagelayer_nav_items']) && current_user_can('edit_theme_options')){
916 $menu_items = (array) $_REQUEST['pagelayer_nav_items'];
917 foreach($menu_items as $items){
918 pagelayer_save_nav_menu_items($items);
919 }
920 }
921
922 // Save Customizer data
923 if(!empty($_REQUEST['pagelayer_customizer_options']) && current_user_can('edit_theme_options')){
924
925 $customizer_options = wp_unslash($_REQUEST['pagelayer_customizer_options']);
926 $customizer_options = json_decode($customizer_options, true);
927
928 // Add current post type
929 $customizer_options['pagelayer_current_post_type'] = $_post->post_type;
930
931 pagelayer_save_customizer_options($customizer_options);
932 }
933
934 pagelayer_json_output($msg);
935
936 }
937
938 // Save sections and global sections
939 add_action('wp_ajax_pagelayer_save_templ_content', 'pagelayer_save_templ_content');
940 function pagelayer_save_templ_content($echo = false){
941
942 // Some AJAX security
943 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
944
945 if ( ! current_user_can( get_post_type_object( 'pagelayer-template' )->cap->create_posts ) ) {
946 $ret['error'][$g_post_id] = __pl('no_permission');
947 pagelayer_json_output($ret);
948 return false;
949 }
950
951 // Are you allowed to edit ?
952 if(!pagelayer_user_can_edit($_REQUEST['postID'])){
953 $msg['error'][] = __pl('no_permission');
954 pagelayer_json_output($msg);
955 }
956
957 $ret = array();
958
959 // Save global widgets data
960 if(empty($_REQUEST['global_widgets'])){
961 $ret['error'][] = 'No widgets given';
962 pagelayer_json_output($ret);
963 return false;
964 }
965
966 $global_widgets = $_REQUEST['global_widgets'];
967
968 foreach($global_widgets as $key => $value){
969
970 $g_post_id = (int) $value['post_id'];
971
972 // Are you allowed to edit ?
973 if(!empty($g_post_id) && !pagelayer_user_can_edit($g_post_id)){
974 $ret['error'][$g_post_id] = __pl('no_permission').' : '.$g_post_id;
975 continue;
976 }
977
978 // Decode base64 data
979 $value['content'] = base64_decode($value['content']);
980
981 $is_xss = pagelayer_xss_content($value['content']);
982
983 if(!current_user_can('manage_options') && strlen($is_xss) > 0){
984 $ret['error'][$g_post_id] = __pl('xss_found').' - '.$is_xss;
985 pagelayer_json_output($ret);
986 }
987
988 // Add slash to save data in post
989 $value['content'] = wp_slash($value['content']);
990
991 // We need to create the post
992 if(empty($value['post_id'])){
993
994 $g_ret = wp_insert_post([
995 'post_type' => 'pagelayer-template',
996 'post_title' => $value['title'],
997 'post_content' => $value['content'],
998 'post_status' => 'publish',
999 'comment_status' => 'closed',
1000 'ping_status' => 'closed'
1001 ]);
1002
1003 $g_post_id = $g_ret;
1004
1005 // Save our template metas
1006 update_post_meta($g_post_id, 'pagelayer_template_type', $value['type']);
1007 update_post_meta($g_post_id, 'pagelayer-data', time());
1008
1009 }else if(!empty($value['content'])){
1010
1011 // Save global widget content
1012 $post = array(
1013 'ID' => $g_post_id,
1014 'post_title' => $value['title'],
1015 'post_content' => $value['content'],
1016 );
1017
1018 wp_update_post($post);
1019 }
1020
1021 if(is_wp_error($g_post_id)){
1022 $ret['error'][$g_post_id] = __pl('template_update_err');
1023 }else{
1024 $ret['success'][$g_post_id] = __pl('template_update_success');
1025 }
1026 }
1027
1028 if(!$echo){
1029 pagelayer_json_output($ret);
1030 }else{
1031 return $ret;
1032 }
1033 }
1034
1035 // Update the Site Title
1036 add_action('wp_ajax_pagelayer_set_jscss_giver', 'pagelayer_set_jscss_giver');
1037 function pagelayer_set_jscss_giver(){
1038 global $wpdb;
1039
1040 // Some AJAX security
1041 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
1042
1043 if( !current_user_can('manage_options') ){
1044 $ret['error'] = __pl('no_permission');
1045 pagelayer_json_output($ret);
1046 }
1047
1048 $val = (int) @$_REQUEST['set'];
1049
1050 if(in_array($val, [1, -1])){
1051 update_option('pagelayer_enable_giver', $val);
1052 }
1053
1054 $ret['success'] = 1;
1055 pagelayer_json_output($ret);
1056 }
1057
1058 // Shortcodes Widget Handler
1059 add_action('wp_ajax_pagelayer_do_shortcodes', 'pagelayer_do_shortcodes');
1060 function pagelayer_do_shortcodes(){
1061
1062 // Some AJAX security
1063 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
1064
1065 if(!current_user_can('edit_posts')){// TODO : WooCommerce
1066 $ret['error'][] = __pl('no_permission');
1067 pagelayer_json_output($ret);
1068 }
1069
1070 $data = '';
1071 if(isset($_REQUEST['shortcode_data'])){
1072 $data = stripslashes($_REQUEST['shortcode_data']);
1073 }
1074
1075 // Load shortcodes
1076 pagelayer_load_shortcodes();
1077
1078 $data = pagelayer_the_content($data);
1079
1080 // Create the HTML object
1081 $node = pagelayerQuery::parseStr($data);
1082 $node->query('.pagelayer-ele')->removeClass('pagelayer-ele');
1083 echo $node->html();
1084
1085 wp_die();
1086
1087 }
1088
1089 // Give the JS
1090 add_action('wp_ajax_pagelayer_givejs', 'pagelayer_givejs');
1091 function pagelayer_givejs(){
1092
1093 global $pagelayer;
1094
1095 // WordPress adds the Expires header in all AJAX calls. We need to remove it for cache to work
1096 header_remove("Expires");
1097 header_remove("Cache-Control");
1098
1099 // Load shortcodes
1100 pagelayer_load_shortcodes();
1101
1102 // Load font options
1103 pagelayer_load_font_options();
1104
1105 // Pagelayer Template Loading Mechanism
1106 include_once(PAGELAYER_DIR.'/js/givejs.php');
1107
1108 exit();
1109
1110 }
1111
1112 add_action('wp_ajax_pagelayer_givecss', 'pagelayer_givecss');
1113 add_action('wp_ajax_nopriv_pagelayer_givecss', 'pagelayer_givecss');
1114 function pagelayer_givecss(){
1115
1116 global $pagelayer;
1117
1118 // WordPress adds the Expires header in all AJAX calls. We need to remove it for cache to work
1119 header_remove("Expires");
1120 header_remove("Cache-Control");
1121
1122 // Pagelayer Template Loading Mechanism
1123 include_once(PAGELAYER_DIR.'/css/givecss.php');
1124
1125 exit();
1126
1127 }
1128
1129 // Shortcodes Widget Handler
1130 add_action('wp_ajax_pagelayer_get_section_shortcodes', 'pagelayer_get_section_shortcodes');
1131 function pagelayer_get_section_shortcodes(){
1132
1133 global $pagelayer;
1134
1135 // Some AJAX security
1136 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
1137
1138 if(!current_user_can('edit_posts')){
1139 $ret['error'][] = __pl('no_permission');
1140 pagelayer_json_output($ret);
1141 }
1142
1143 $data = '';
1144 if(isset($_REQUEST['pagelayer_section_id'])){
1145
1146 $get_url = PAGELAYER_API.'/library.php?give_id='.sanitize_text_field($_REQUEST['pagelayer_section_id']).(!empty($pagelayer->license['license']) ? '&license='.$pagelayer->license['license'] : '').'&url='.rawurlencode(site_url());
1147
1148 // For SitePad users
1149 if(function_exists('get_softaculous_file')){
1150 $get_url = get_softaculous_file($get_url, 1);
1151 }
1152
1153 $fetch = wp_remote_get($get_url, array('timeout' => 60));
1154
1155 if ( is_array( $fetch ) && ! is_wp_error( $fetch ) && isset( $fetch['body'] ) ) {
1156 $data = json_decode( $fetch['body'], true ); // use the content
1157 }else{
1158 $data['error'] = __pl('The response was malformed');
1159 pagelayer_json_output($data);
1160 }
1161 }
1162
1163 if(isset($_REQUEST['postID'])){
1164 $post_id = (int) $_REQUEST['postID'];
1165
1166 if(!empty($post_id)){
1167 $post = get_post( $post_id );
1168 // Need to make the reviews post global
1169 if ( !empty( $post ) ) {
1170 $GLOBALS['post'] = $post;
1171
1172 $GLOBALS['wp_query'] = new WP_Query([
1173 'post_type' => $GLOBALS['post']->post_type,
1174 'post__in' => array($post_id),
1175 ]);
1176 }
1177 }
1178 }
1179
1180 // Upload the images if any in the shortcode
1181 preg_match_all('/"'.preg_quote('{{pl_lib_images}}', '/').'([^"]*)"/is', $data['code'], $matches);
1182
1183 foreach($matches[0] as $k => $v){
1184 $image_url = trim($v, '"\'');
1185 $urls[$image_url] = $image_url;
1186 }
1187
1188 foreach($urls as $k => $image_url){
1189
1190 $file = basename($image_url);
1191 $id = 0;
1192
1193 // Upload this
1194 if(!empty($data[$file])){
1195
1196 $id = pagelayer_upload_media($file, base64_decode($data[$file]));
1197
1198 if(!empty($id)){
1199 $data['code'] = str_replace('"'.$image_url.'"', '"'.$id.'"', $data['code']);
1200 }
1201 }
1202
1203 }
1204
1205 // Load shortcodes
1206 pagelayer_load_shortcodes();
1207
1208 if(!empty($data['code'])){
1209 $data['code'] = pagelayer_the_content($data['code'], true);
1210 }
1211
1212 pagelayer_json_output($data);
1213
1214 }
1215
1216 // Shortcodes Widget Handler
1217 add_action('wp_ajax_pagelayer_get_section_blocks', 'pagelayer_get_section_blocks');
1218 function pagelayer_get_section_blocks(){
1219
1220 global $pagelayer;
1221
1222 // Some AJAX security
1223 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
1224
1225 if(!current_user_can('edit_posts')){
1226 $ret['error'][] = __pl('no_permission');
1227 pagelayer_json_output($ret);
1228 }
1229
1230 $data = '';
1231 if(isset($_REQUEST['pagelayer_section_id'])){
1232
1233 $get_url = PAGELAYER_API.'/library.php?give_id='.sanitize_text_field($_REQUEST['pagelayer_section_id']).(!empty($pagelayer->license['license']) ? '&license='.$pagelayer->license['license'] : '').'&url='.rawurlencode(site_url());
1234
1235 // For SitePad users
1236 if(function_exists('get_softaculous_file')){
1237 $get_url = get_softaculous_file($get_url, 1);
1238 }
1239
1240 $fetch = wp_remote_get($get_url, array('timeout' => 60));
1241
1242 if ( is_array( $fetch ) && ! is_wp_error( $fetch ) && isset( $fetch['body'] ) ) {
1243 $data = json_decode( $fetch['body'], true ); // use the content
1244 }else{
1245 $data['error'] = __pl('The response was malformed');
1246 pagelayer_json_output($data);
1247 }
1248 }
1249
1250 // Upload the images if any in the shortcode
1251 preg_match_all('/"'.preg_quote('{{pl_lib_images}}', '/').'([^"]*)"/is', $data['code'], $matches);
1252
1253 foreach($matches[0] as $k => $v){
1254 $image_url = trim($v, '"\'');
1255 $urls[$image_url] = $image_url;
1256 }
1257
1258 foreach($urls as $k => $image_url){
1259
1260 $file = basename($image_url);
1261 $id = 0;
1262
1263 // Upload this
1264 if(!empty($data[$file])){
1265
1266 $id = pagelayer_upload_media($file, base64_decode($data[$file]));
1267
1268 if(!empty($id)){
1269 $data['code'] = str_replace('"'.$image_url.'"', '"'.$id.'"', $data['code']);
1270 }
1271 }
1272
1273 }
1274
1275 if ( false !== strpos( $data['code'], '[pl_' ) ) {
1276 // Load shortcodes
1277 pagelayer_load_shortcodes();
1278
1279 // Load Parse Shortcodes
1280 include_once(PAGELAYER_DIR.'/main/parse-shortcodes.php');
1281
1282 $data['code'] = pagelayer_do_shortcode_to_block($data['code']);
1283 }
1284
1285 $data['code'] = pagelayer_add_tmp_atts($data['code']);
1286
1287 pagelayer_json_output($data);
1288
1289 }
1290
1291 // Get the Site Title
1292 add_action('wp_ajax_pagelayer_fetch_site_title', 'pagelayer_fetch_site_title');
1293 function pagelayer_fetch_site_title(){
1294
1295 // Some AJAX security
1296 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
1297
1298 echo get_bloginfo('name');
1299 wp_die();
1300 }
1301
1302 // Update the Site Title
1303 add_action('wp_ajax_pagelayer_update_site_title', 'pagelayer_update_site_title');
1304 function pagelayer_update_site_title(){
1305 global $wpdb;
1306
1307 // Some AJAX security
1308 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
1309
1310 $site_title = $_POST['site_title'];
1311
1312 if(!current_user_can('manage_options')){
1313 $ret['error'][] = __pl('no_permission');
1314 pagelayer_json_output($ret);
1315 }
1316
1317 update_option('blogname', $site_title);
1318
1319 wp_die();
1320 }
1321
1322 // Show the SideBars
1323 add_action('wp_ajax_pagelayer_fetch_sidebar', 'pagelayer_fetch_sidebar');
1324 function pagelayer_fetch_sidebar(){
1325
1326 global $wp_registered_sidebars;
1327
1328 // Some AJAX security
1329 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
1330
1331 // Create a list
1332 $pagelayer_wp_widgets = array();
1333
1334 foreach($wp_registered_sidebars as $v){
1335 $pagelayer_wp_widgets[$v['id']] = $v['name'];
1336 }
1337
1338 $id = @$_REQUEST['sidebar'];
1339
1340 if(function_exists('dynamic_sidebar') && !empty($pagelayer_wp_widgets[$id])) {
1341 ob_start();
1342 dynamic_sidebar($id);
1343 $result = ob_get_clean();
1344 }else{
1345 $result = __pl('no_widget_area');
1346 }
1347
1348 echo $result;
1349 wp_die();
1350
1351 }
1352
1353 // Show the primary menu !
1354 add_action('wp_ajax_pagelayer_fetch_primary_menu', 'pagelayer_fetch_primary_menu');
1355 function pagelayer_fetch_primary_menu(){
1356
1357 // Some AJAX security
1358 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
1359
1360 if(isset($_POST['nav_list'])){
1361 $_POST['nav_list'] = (int) $_POST['nav_list'];
1362
1363 // Load Pagelayer nav menu walker
1364 include_once(PAGELAYER_DIR.'/main/nav_walker.php');
1365
1366 $postID = (int) $_REQUEST['postID'];
1367
1368 // To on live mode
1369 $GLOBALS['post'] = get_post($postID);
1370 $GLOBALS['wp_query'] = new WP_Query([
1371 'post_type' => $GLOBALS['post']->post_type,
1372 'post__in' => array($postID),
1373 ]);
1374
1375 // Load short
1376 pagelayer_load_shortcodes();
1377
1378 wp_nav_menu([
1379 'menu' => wp_get_nav_menu_object($_POST['nav_list']),
1380 'menu_id' => $_POST["nav_list"],
1381 'menu_class' => 'pagelayer-wp_menu-ul',
1382 'walker' => new Pagelayer_Walker_Nav_Menu(),
1383 //'theme_location' => 'primary',
1384 'echo' => true,
1385 ]);
1386 }
1387
1388 wp_die();
1389 }
1390
1391 // Save post revision
1392 add_action('wp_ajax_pagelayer_create_post_autosave', 'pagelayer_create_post_autosave');
1393 function pagelayer_create_post_autosave(){
1394
1395 // Some AJAX security
1396 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
1397
1398 $ret = array();
1399 $postID = (int) $_GET['postID'];
1400 $content = $_REQUEST['pagelayer_post_content'];
1401
1402 // Decode base64 data
1403 $content = base64_decode($content);
1404 $content = wp_slash($content);
1405
1406 // Are you allowed to edit ?
1407 if(!pagelayer_user_can_edit($postID)){
1408 $ret['error'][] = __pl('no_permission');
1409 pagelayer_json_output($ret);
1410 }
1411
1412 if(empty($postID)){
1413 $ret['error'] = __pl('invalid_post_id');
1414 }else{
1415
1416 $post = array(
1417 'post_ID' => $postID,
1418 'post_content' => $content,
1419 );
1420
1421 $ret['id'] = wp_create_post_autosave($post);
1422 }
1423
1424 $ret['url'] = get_preview_post_link($postID);
1425
1426 pagelayer_json_output($ret);
1427
1428 }
1429
1430 // Get post revision
1431 add_action('wp_ajax_pagelayer_get_revision', 'pagelayer_get_revision');
1432 function pagelayer_get_revision(){
1433
1434 // Some AJAX security
1435 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
1436
1437 $ret = array();
1438 $postID = (int) $_GET['postID'];
1439
1440 // Are you allowed to edit ?
1441 if(!pagelayer_user_can_edit($postID)){
1442 $ret['error'][] = __pl('no_permission');
1443 pagelayer_json_output($ret);
1444 }
1445
1446 if(empty($postID)){
1447 $ret['error'] = __pl('invalid_post_id');
1448 }else{
1449 $ret = pagelayer_get_post_revision_by_id($postID);
1450 }
1451
1452 pagelayer_json_output($ret);
1453
1454 }
1455
1456 // Apply post revision
1457 add_action('wp_ajax_pagelayer_apply_revision', 'pagelayer_apply_revision');
1458 function pagelayer_apply_revision(){
1459
1460 // Some AJAX security
1461 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
1462
1463 $revisionID = (int) $_REQUEST['revisionID'];
1464 $parID = wp_get_post_parent_id($revisionID);
1465 $ret = array();
1466
1467 if(empty($parID)){
1468 $parID = $revisionID;
1469 }
1470
1471 // Are you allowed to edit ?
1472 if(!pagelayer_user_can_edit($parID)){
1473 $ret['error'][] = __pl('no_permission');
1474 pagelayer_json_output($ret);
1475 }
1476
1477 if(empty($revisionID)){
1478 $ret['error'] = __pl('invalid_post_id');
1479 }else{
1480
1481 $post = get_post( $revisionID );
1482
1483 if ( empty( $post ) ) {
1484 $ret['error'] = __pl('invalid_revision');
1485 pagelayer_json_output($ret);
1486 }
1487
1488 // Need to make the reviews post global
1489 $GLOBALS['post'] = $post;
1490 $GLOBALS['wp_query'] = new WP_Query([
1491 'post_type' => $GLOBALS['post']->post_type,
1492 'post__in' => array($parID),
1493 ]);
1494
1495 // Need to reload the shortcodes
1496 pagelayer_load_shortcodes();
1497
1498 $ret['id'] = $revisionID;
1499 $ret['content'] = pagelayer_the_content($post->post_content, true);
1500
1501 if(is_wp_error($post)) {
1502 $ret['error'] = __pl('rev_load_error');
1503 }else{
1504 $ret['success'] = __pl('rev_load_success');
1505 }
1506
1507 wp_reset_postdata();
1508 }
1509
1510 pagelayer_json_output($ret);
1511
1512 }
1513
1514 // Get post revision
1515 add_action('wp_ajax_pagelayer_delete_revision', 'pagelayer_delete_revision');
1516 function pagelayer_delete_revision() {
1517
1518 // Some AJAX security
1519 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
1520
1521 $revisionID = (int) $_REQUEST['revisionID'];
1522 $parID = wp_get_post_parent_id($revisionID);
1523 $ret = array();
1524
1525 // Are you allowed to edit ?
1526 if(!pagelayer_user_can_edit($parID)){
1527 $ret['error'][] = __pl('no_permission');
1528 pagelayer_json_output($ret);
1529 }
1530
1531 if(empty($revisionID)){
1532 $ret['error'] = __pl('invalid_post_id');
1533 }else{
1534
1535 $revision = get_post( $revisionID );
1536
1537 if ( empty( $revision ) ) {
1538 $ret['error'] = __pl('invalid_revision');
1539 }else{
1540
1541 if ( ! current_user_can( 'delete_post', $parID ) ) {
1542 $ret['error'] = __pl('access_denied');
1543 pagelayer_json_output($ret);
1544 }
1545
1546 $deleted = wp_delete_post_revision( $revision->ID );
1547
1548 if ( ! $deleted || is_wp_error( $deleted ) ) {
1549 $ret['error'] = __pl('delete_rev_error');
1550 }else{
1551 $ret['success'] = __pl('delete_rev_success');
1552 }
1553 }
1554 }
1555
1556 pagelayer_json_output($ret);
1557
1558 }
1559
1560 // Get post navigation
1561 add_action('wp_ajax_pagelayer_post_nav', 'pagelayer_post_nav');
1562 function pagelayer_post_nav() {
1563
1564 // Some AJAX security
1565 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
1566
1567 if(!isset($_REQUEST['data']) || !isset($_REQUEST['postID'])){
1568 return;
1569 }
1570
1571 $el['atts'] = $_REQUEST['data'];
1572
1573 $post = get_post($_REQUEST['postID']);
1574
1575 // Need to make this post global
1576 $GLOBALS['post'] = $post;
1577
1578 $in_same_term = false;
1579 $taxonomies = 'category';
1580 $title = '';
1581 $arrows_list = $el['atts']['arrows_list'];
1582
1583 if($el['atts']['in_same_term']){
1584 $in_same_term = true;
1585 $taxonomies = $el['atts']['taxonomies'];
1586 }
1587
1588 if($el['atts']['post_title']){
1589 $title = '<span class="pagelayer-post-nav-title">%title</span>';
1590 }
1591
1592 $next_label = '<span class="pagelayer-next-holder">
1593 <span class="pagelayer-post-nav-link"> '.$el["atts"]["next_label"].'</span>'.$title.'
1594 </span>
1595 <span class="pagelayer-post-nav-icon fa fa-'.$arrows_list.'-right"></span>';
1596
1597 $prev_label = '<span class="pagelayer-post-nav-icon fa fa-'.$arrows_list.'-left"></span>
1598 <span class="pagelayer-next-holder">
1599 <span class="pagelayer-post-nav-link"> '.$el["atts"]["prev_label"].'</span>'.$title.'
1600 </span>';
1601
1602 $el['atts']['next_link'] = get_next_post_link('%link', $next_label, $in_same_term, '', $taxonomies);
1603
1604 $el['atts']['prev_link'] = get_previous_post_link('%link', $prev_label, $in_same_term, '', $taxonomies );
1605
1606 pagelayer_json_output($el);
1607
1608 }
1609
1610 // Get post comment template
1611 add_action('wp_ajax_pagelayer_post_comment', 'pagelayer_post_comment');
1612 function pagelayer_post_comment() {
1613 global $post;
1614
1615 // Some AJAX security
1616 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
1617
1618 if(!isset($_REQUEST['postID'])){
1619 return true;
1620 }
1621
1622 $GLOBALS['post'] = get_post($_REQUEST['postID']);
1623 $GLOBALS['withcomments'] = true;
1624
1625 // Load shortcodes
1626 pagelayer_load_shortcodes();
1627
1628 $el = [];
1629 pagelayer_sc_post_comment($el);
1630
1631 echo $el['atts']['post_comment'];
1632
1633 wp_die();
1634
1635 }
1636
1637 // Get post comment template
1638 add_action('wp_ajax_pagelayer_post_info', 'pagelayer_post_info');
1639 function pagelayer_post_info() {
1640 global $post;
1641
1642 // Some AJAX security
1643 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
1644
1645 if(!isset($_REQUEST['postID']) || !isset($_REQUEST['el'])){
1646 return true;
1647 }
1648
1649 $el['atts'] = $_REQUEST['el'];
1650
1651 $GLOBALS['post'] = get_post($_REQUEST['postID']);
1652
1653 // Load shortcodes
1654 pagelayer_load_shortcodes();
1655
1656 pagelayer_sc_post_info_list($el);
1657
1658 pagelayer_json_output($el['atts']);
1659
1660 }
1661
1662 // Get the Featured Image
1663 add_action('wp_ajax_pagelayer_fetch_featured_img', 'pagelayer_fetch_featured_img');
1664 function pagelayer_fetch_featured_img(){
1665
1666 // Some AJAX security
1667 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
1668
1669 $id = get_post_thumbnail_id( (int) $_POST['post_id'] );
1670 $img = [];
1671
1672 if(empty($id)){
1673 pagelayer_json_output($img);
1674 }
1675
1676 $img = pagelayer_image($id);
1677 pagelayer_json_output($img);
1678
1679 }
1680
1681 // Get the postfolio posts
1682 add_action('wp_ajax_pagelayer_fetch_posts', 'pagelayer_fetch_posts');
1683 function pagelayer_fetch_posts(){
1684
1685 // Some AJAX security
1686 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
1687
1688 // This ajax call is only used during post/page editing
1689 if(!current_user_can('edit_posts')){
1690 echo __pl('no_permission');
1691 wp_die();
1692 }
1693
1694 $sanitized_post = pagelayer_sanitize_posts_data($_POST);
1695 echo pagelayer_widget_posts($sanitized_post);
1696
1697 wp_die();
1698 }
1699
1700 // Get the Posts
1701 add_action('wp_ajax_pagelayer_posts_data', 'pagelayer_posts_data');
1702 function pagelayer_posts_data(){
1703
1704 // Some AJAX security
1705 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
1706
1707 // This ajax call is only used during post/page editing
1708 if(!current_user_can('edit_posts')){
1709 echo __pl('no_permission');
1710 wp_die();
1711 }
1712
1713 // Load shortcodes
1714 pagelayer_load_shortcodes();
1715
1716 $sanitized_post = pagelayer_sanitize_posts_data($_POST, false);
1717 echo pagelayer_posts($sanitized_post);
1718 wp_die();
1719 }
1720
1721 // Get the Posts
1722 add_action('wp_ajax_pagelayer_archive_posts_data', 'pagelayer_archive_posts_data');
1723 function pagelayer_archive_posts_data(){
1724
1725 // Some AJAX security
1726 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
1727
1728 // Set excerpt length
1729 if(!empty($_POST['atts']['exc_length'])){
1730 $exc_length = (int) $_POST['atts']['exc_length'];
1731 add_filter( 'excerpt_length', function($length) use($exc_length){
1732 return $exc_length;
1733 }, 999 );
1734 }
1735
1736 // Load shortcodes
1737 pagelayer_load_shortcodes();
1738
1739 foreach($_POST['atts'] as $k => $v){
1740 $v = pagelayer_maybe_implode($v);
1741 $r[] = esc_html($k).'="'.pagelayer_escapeHTML($v).'"';
1742 }
1743
1744 $string = implode(' ', $r);
1745 if(preg_match('/\]/is', $string)){
1746 die('Hacking Attempt');
1747 }
1748
1749 $sc = '[pl_archive_posts '.$string.'][/pl_archive_posts]';
1750
1751 echo pagelayer_the_content($sc);
1752 wp_die();
1753 }
1754
1755 // Handle Contact Form Data
1756 add_action('wp_ajax_pagelayer_contact_submit', 'pagelayer_contact_submit');
1757 add_action('wp_ajax_nopriv_pagelayer_contact_submit', 'pagelayer_contact_submit' );
1758 function pagelayer_contact_submit(){
1759
1760 // Some AJAX security
1761 check_ajax_referer('pagelayer_global', 'pagelayer_nonce');
1762
1763 // A filter to short circuit this contact form
1764 $continue = apply_filters('pagelayer_contact_submit_start', 1);
1765 if(empty($continue)){
1766 return false;
1767 }
1768
1769 $formdata = wp_unslash($_POST);
1770 // NOTE : NEVER add anything to $formdata except $_POST vars
1771
1772 if(isset($_POST['g-recaptcha-response']) ){
1773
1774 if(!pagelayer_captcha_verify()){
1775 $wp['failed'] = get_option('pagelayer_recaptcha_failed', __pl('cap_ver_fail'));
1776 pagelayer_json_output($wp);
1777 }
1778
1779 unset($formdata['g-recaptcha-response']);
1780 }
1781
1782 // Unset the nonce
1783 unset($formdata['pagelayer_nonce']);
1784
1785 $to_mail = get_option('pagelayer_cf_to_email');
1786 $from_mail = get_option('pagelayer_cf_from_email');
1787 $subject = get_option('pagelayer_cf_subject');
1788 $additional_headers = get_option('pagelayer_cf_headers');
1789 $reply_to = '';
1790 $body = '';
1791 $headers = '';
1792 $custom_templ = array();
1793 $use_custom = false;
1794 $use_html = false;
1795 $pagelayer_id = sanitize_text_field($formdata['cfa-pagelayer-id']);
1796
1797 if(isset($formdata['cfa-custom-template']) && !empty($formdata['cfa-post-id'])){
1798 $post_id = (int) $formdata['cfa-post-id'];
1799
1800 if(!empty($post_id) && ( get_post_status( $post_id ) === 'publish' || current_user_can('publish_posts') )){
1801 $contact_array = get_post_meta($post_id, 'pagelayer_contact_templates', true);
1802
1803 if(!empty($contact_array) && !empty($contact_array[$pagelayer_id])){
1804 $custom_templ = $contact_array[$pagelayer_id];
1805 $use_custom = true;
1806 }
1807 }
1808 }
1809
1810 if($use_custom && !empty($custom_templ)){
1811
1812 if(!empty($custom_templ['to_email'])){
1813 $to_mail = $custom_templ['to_email'];
1814 }
1815
1816 if(!empty($custom_templ['from_email'])){
1817 $from_mail = $custom_templ['from_email'];
1818 }
1819
1820 if(!empty($custom_templ['cont_subject'])){
1821 $subject = $custom_templ['cont_subject'];
1822 }
1823
1824 if(!empty($custom_templ['cont_header'])){
1825 $additional_headers = $custom_templ['cont_header'];
1826 }
1827
1828 if(!empty($custom_templ['cont_body'])){
1829 $body = $custom_templ['cont_body'];
1830 }
1831
1832 if(!empty($custom_templ['cont_use_html'])){
1833 $use_html = true;
1834 $headers .= "Content-Type: text/html\n";
1835 }
1836 }
1837
1838 if(!empty($from_mail)){
1839 $headers .= "From: $from_mail\n";
1840 }
1841
1842 if ( !empty($additional_headers) ) {
1843 $headers .= $additional_headers . "\n";
1844 }
1845
1846 if ( empty($body) ) {
1847
1848 // Make the email content
1849 foreach($formdata as $k => $i){
1850
1851 $not_allow = ['cfa-pagelayer-id', 'cfa-redirect', 'cfa-post-id', 'cfa-custom-template', 'pagelayer-contact-submit'];
1852 if(in_array($k, $not_allow)){
1853 continue;
1854 }
1855
1856 $body .= sanitize_text_field($k)."\t : \t $".$k."\n";
1857
1858 }
1859
1860 $body .= "\n\n --\n This e-mail was sent from a contact form (".get_home_url().")";
1861
1862 }
1863
1864 // Add attachment
1865 if(!empty($_FILES)){
1866 add_action('phpmailer_init', 'pagelayer_cf_email_attachment', 10, 1);
1867 }
1868
1869 $sanitized_data = array();
1870
1871 // If we are using HTML, then we should escape html as well
1872 foreach($formdata as $k => $i){
1873
1874 if(is_array($i)){
1875 $i = pagelayer_flat_join($i);
1876 }
1877
1878 $i = pagelayer_esc_crlf($i);
1879
1880 if(!empty($use_html)){
1881 $i = esc_html($i);
1882 }
1883
1884 // Sanitize text field
1885 $i = sanitize_text_field($i);
1886
1887 // Record a reply to if it is to be used
1888 if(is_email($i) && empty($reply_to)){
1889 $reply_to = $i;
1890 }
1891
1892 $sanitized_data[$k] = $i;
1893 }
1894
1895 // Dow we have a reply to in the headers ?
1896 if(!preg_match('/reply\-to/is', $headers) && !empty($reply_to)){
1897 $headers .= "Reply-To: $reply_to\n";
1898 }
1899
1900 // Add Site Title as option in formdata
1901 $sanitized_data['site_title'] = get_bloginfo( 'name' );
1902
1903 // Do parse a variables
1904 $to_mail = pagelayer_replace_vars($to_mail, $sanitized_data, '$');
1905 $from_mail = pagelayer_replace_vars($from_mail, $sanitized_data, '$');
1906 $subject = pagelayer_replace_vars($subject, $sanitized_data, '$');
1907 $headers = pagelayer_replace_vars($headers, $sanitized_data, '$');
1908 $body = pagelayer_replace_vars($body, $sanitized_data, '$');
1909
1910 if ( $use_html && ! preg_match( '%<html[>\s].*</html>%is', $body ) ) {
1911 $header = '<!doctype html>
1912 <html xmlns="http://www.w3.org/1999/xhtml">
1913 <head><title>' . esc_html( $subject ) . '</title></head>
1914 <body>';
1915
1916 $footer = '</body></html>';
1917
1918 $body = $header . wpautop( $body ) . $footer;
1919 }
1920
1921 $to_mail = apply_filters('pagelayer_contact_send', $to_mail, $sanitized_data);
1922
1923 // Send the email
1924 if(!empty($to_mail)){
1925 $r = wp_mail( $to_mail, $subject, $body, $headers );
1926 }
1927
1928 if($r == TRUE){
1929 $wp['success'] = pagelayer_get_option( 'pagelayer_cf_success' );
1930 }else{
1931 $wp['failed'] = pagelayer_get_option( 'pagelayer_cf_failed' );
1932 }
1933
1934 pagelayer_json_output($wp);
1935
1936 }
1937
1938 // Handle Login Submit
1939 add_action('wp_ajax_pagelayer_login_submit', 'pagelayer_login_submit');
1940 add_action('wp_ajax_nopriv_pagelayer_login_submit', 'pagelayer_login_submit');
1941 function pagelayer_login_submit(){
1942
1943 // Some AJAX security
1944 check_ajax_referer('pagelayer_global', 'pagelayer_nonce');
1945
1946 $creds = array();
1947 $creds['user_login'] = $_REQUEST['username'];
1948 $creds['user_password'] = $_REQUEST['password'];
1949 $creds['remember'] = $_REQUEST['remember_me'];
1950
1951 // Login the user
1952 $user = wp_signon( $creds, false );
1953
1954 if ( is_wp_error($user) ){
1955 $data['error'] = $user->get_error_message();
1956 }else{
1957
1958 // If After logout URL, then save
1959 if(!empty($_REQUEST['logout_url'])){
1960 update_user_option($user->ID, 'pagelayer_logout_url', sanitize_url($_REQUEST['logout_url']));
1961 }
1962
1963 $data['redirect'] = (empty($_REQUEST['login_url']) ? '' : sanitize_url($_REQUEST['login_url']));
1964 $data['error'] = '';
1965 }
1966
1967 pagelayer_json_output($data);
1968
1969 }
1970
1971 // Get Page List for SiteMap
1972 add_action('wp_ajax_pagelayer_get_pages_list', 'pagelayer_get_pages_list');
1973 function pagelayer_get_pages_list(){
1974
1975 // Some AJAX security
1976 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
1977
1978 if(!current_user_can('edit_posts')){
1979 echo __pl('no_permission');
1980 wp_die();
1981 }
1982
1983 $args = array(
1984 'post_type' => sanitize_text_field($_POST['type']),
1985 'orderby' => sanitize_text_field($_POST['post_order']),
1986 'order' => sanitize_text_field($_POST['order']),
1987 'hierarchical' => (empty($_POST['hier']) || $_POST['hier'] == null ? '' : sanitize_text_field($_POST['hier'])),
1988 'number' => (empty($_POST['depth']) || $_POST['depth'] == null ? '' : sanitize_text_field($_POST['depth'])),
1989 'posts_per_page' => -1,
1990 );
1991
1992 $option = '<ul>';
1993 $pages = new WP_Query($args);
1994 $posts = $pages->posts;
1995 foreach ( $posts as $page ) {
1996 $option .= '<li class="pagelayer-sitemap-list-item" data-postID="'.$page->ID.'"><a class="pagelayer-ele-link" href="'.$page->guid.'">'.$page->post_name.'</a></li>';
1997 }
1998 $option .= '</ul>';
1999
2000 echo $option;
2001
2002 wp_die();
2003 }
2004
2005 // Get the data for template
2006 add_action('wp_ajax_pagelayer_search_ids', 'pagelayer_search_ids');
2007 function pagelayer_search_ids() {
2008
2009 // Some AJAX security
2010 check_ajax_referer('pagelayer_builder', 'pagelayer_nonce');
2011
2012 if ( empty( $_POST['filter_type'] ) || empty( $_POST['search'] ) ) {
2013 wp_die();
2014 }
2015
2016 $sel_opt = '';
2017
2018 switch ( $_POST['filter_type'] ) {
2019 case 'taxonomy':
2020 $query_params = [
2021 'taxonomy' => $_POST['object_type'],
2022 'search' => $_POST['search'],
2023 'hide_empty' => false,
2024 ];
2025
2026 $terms = get_terms( $query_params );
2027
2028 global $wp_taxonomies;
2029
2030 foreach ( $terms as $term ) {
2031 $sel_opt .= '<span class="pagelayer-temp-search-sel-span" value="'. $term->term_taxonomy_id .'">'. $term->name .'</span>';
2032 }
2033
2034 break;
2035
2036 case 'post':
2037 $query_params = [
2038 'post_type' => $_POST['object_type'], //$this->extract_post_type( $data ),
2039 's' => $_POST['search'],
2040 'posts_per_page' => -1,
2041 ];
2042
2043 if ( 'attachment' === $query_params['post_type'] ) {
2044 $query_params['post_status'] = 'inherit';
2045 }
2046
2047 $query = new \WP_Query( $query_params );
2048
2049 foreach ( $query->posts as $post ) {
2050 $sel_opt .= '<span class="pagelayer-temp-search-sel-span" value="'. $post->ID .'">'. $post->post_title .'</span>';
2051 }
2052 break;
2053
2054 case 'author':
2055 $query_params = [
2056 'capability' => array( 'edit_posts' ),
2057 'fields' => [
2058 'ID',
2059 'display_name',
2060 ],
2061 'search' => '*' . $_POST["search"] . '*',
2062 'search_columns' => [
2063 'user_login',
2064 'user_nicename',
2065 ],
2066 ];
2067
2068 // Capability queries were only introduced in WP 5.9.
2069 if( version_compare( $GLOBALS['wp_version'], '5.9-alpha', '<' ) ){
2070 $args['who'] = 'authors';
2071 unset( $args['capability'] );
2072 }
2073
2074 $user_query = new \WP_User_Query( $query_params );
2075
2076 foreach ( $user_query->get_results() as $author ) {
2077 $sel_opt .= '<span class="pagelayer-temp-search-sel-span" value="'. $author->ID .'">'. $author->display_name .'</span>';
2078 }
2079 break;
2080
2081 /* case 'menu':
2082
2083 $menuItems = wp_get_nav_menu_items( (int)$_POST['object_type']);
2084
2085 foreach ( $menuItems as $item ) {
2086
2087 if($item -> menu_item_parent !=0 ){
2088 continue;
2089 }
2090 $sel_opt .= '<span class="pagelayer-temp-search-sel-span" value="'. $item -> ID .'">'. $item -> title.'</span>';
2091 }
2092
2093 break; */
2094
2095 default:
2096 $sel_opt = 'Result Not Found';
2097 }
2098
2099 if(!empty($sel_opt)){
2100 echo $sel_opt;
2101 }else{
2102 echo 'Result Not Found';
2103 }
2104
2105 wp_die();
2106 }
2107
2108 // Save the post data from pagelayer setting page
2109 add_action('wp_ajax_pagelayer_save_template', 'pagelayer_save_template');
2110 function pagelayer_save_template() {
2111
2112 // Some AJAX security
2113 check_ajax_referer('pagelayer_builder', 'pagelayer_nonce');
2114
2115 $done = [];
2116
2117 $post_id = (int) $_GET['postID'];
2118
2119 // Are you allowed to edit ?
2120 if(!empty($post_id) && !pagelayer_user_can_edit($post_id)){
2121 $done['error'][] = __pl('no_permission');
2122 pagelayer_json_output($done);
2123 }
2124
2125 // We need to create the post
2126 if(empty($post_id)){
2127
2128 if (!current_user_can('edit_posts')) {
2129 $done['error'] = __pl('access_denied');
2130 pagelayer_json_output($done);
2131 }
2132
2133 // Get the template type
2134 if(empty($_POST['pagelayer_template_type'])){
2135 $done['error'] = __pl('temp_error_type');
2136 pagelayer_json_output($done);
2137 }
2138
2139 $ret = wp_insert_post([
2140 'post_title' => $_POST['pagelayer_lib_title'],
2141 'post_type' => 'pagelayer-template',
2142 'post_status' => 'publish',
2143 'comment_status' => 'closed',
2144 'ping_status' => 'closed'
2145 ]);
2146
2147 // An error occured
2148 if(is_wp_error($ret)){
2149 $done['error'] = __pl('temp_error').' : '.$ret->get_error_message();
2150 pagelayer_json_output($done);
2151 }
2152
2153 $post_id = $ret;
2154 $done['id'] = $post_id;
2155
2156 // Save our template type
2157 $ret = update_post_meta($post_id, 'pagelayer_template_type', $_POST['pagelayer_template_type']);
2158
2159 }
2160
2161 // The ID in consideration
2162 $done['id'] = $post_id;
2163
2164 // Check if the post title in not empty
2165 if(!empty($_POST['pagelayer_lib_title'])){
2166
2167 $post = array(
2168 'ID' => $post_id,
2169 'post_title' => $_POST['pagelayer_lib_title'],
2170 );
2171
2172 // Update the post into the database
2173 $ret = wp_update_post($post);
2174
2175 }
2176
2177 // Save template library display conditions
2178 $condi_array = array();
2179 $condi_len = count($_POST['pagelayer_condition_type']);
2180 if($_POST['pagelayer_template_type'] != 'section'){
2181 for( $i =0; $i < $condi_len; $i++ ){
2182 $condi_array[$i] = array(
2183 'type' => $_POST['pagelayer_condition_type'][$i],
2184 'template' => $_POST['pagelayer_condition_name'][$i],
2185 'sub_template' => $_POST['pagelayer_condition_sub_template'][$i],
2186 'id' => $_POST['pagelayer_condition_id'][$i],
2187 );
2188 }
2189 }
2190 //print_r($condi_array);
2191
2192 $ret = update_post_meta($post_id, 'pagelayer_template_conditions', $condi_array);
2193
2194 if(is_wp_error($post_id)){
2195 $done['error'] = __pl('temp_error').' : '.$ret->get_error_message();
2196 }else{
2197 $done['success'] = __pl('temp_update_success');
2198 }
2199
2200 pagelayer_json_output($done);
2201
2202 }
2203
2204 // Products Categories Handler
2205 add_action('wp_ajax_pagelayer_product_categories', 'pagelayer_product_categories');
2206 function pagelayer_product_categories(){
2207
2208 // Some AJAX security
2209 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
2210
2211 $attributes = '';
2212 $attributes .= ' number="'. $_POST['atts']['number'] .'" ';
2213 $attributes .= ' columns="'. $_POST['atts']['columns'] .'" ';
2214 $attributes .= ' hide_empty="'. (!empty($_POST['atts']['hide_empty']) ? 1 : 0) .'" ';
2215 $attributes .= ' orderby="'. $_POST['atts']['nuorderbymber'] .'" ';
2216 $attributes .= ' order="'. $_POST['atts']['order'] .'" ';
2217
2218 if ( 'by_id' === $_POST['atts']['source'] ) {
2219 $attributes .= ' ids="'. $_POST['atts']['by_id'] .'" ';
2220 } elseif ( 'by_parent' === $_POST['atts']['source'] ) {
2221 $attributes .= ' parent="'. $_POST['atts']['parent'] .'" ';
2222 } elseif ( 'current_subcategories' === $_POST['atts']['source'] ) {
2223 $attributes .= ' parent="'. get_queried_object_id() .'" ';
2224 }
2225
2226 $shortcode = '[product_categories '. $attributes .']';
2227
2228 // do_shortcode the shortcode
2229 echo pagelayer_the_content($shortcode);
2230
2231 wp_die();
2232 }
2233
2234 // Products Categories Handler
2235 add_action('wp_ajax_pagelayer_products_ajax', 'pagelayer_products_ajax');
2236 function pagelayer_products_ajax(){
2237
2238 // Some AJAX security
2239 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
2240
2241 if ( WC()->session ) {
2242 wc_print_notices();
2243 }
2244
2245 $no_found = $_POST['atts']['no_found'];
2246
2247 $attributes = '';
2248 $type = $_POST['atts']['source'];
2249 $attributes .= ' columns="'. $_POST['atts']['columns'] .'" ';
2250 $attributes .= ' rows="'. $_POST['atts']['rows'] .'" ';
2251 $attributes .= ' paginate="'. (!empty($_POST['atts']['paginate']) ? true : false) .'" ';
2252 $attributes .= ' orderby="'. $_POST['atts']['orderby'] .'" ';
2253 $attributes .= ' order="'. $_POST['atts']['order'] .'" ';
2254 $attributes .= ' cache="false" ';
2255
2256 // Hide the catalog order
2257 if( empty($_POST['atts']['allow_order']) ){
2258 remove_action( 'woocommerce_before_shop_loop', 'woocommerce_catalog_ordering', 30 );
2259 }
2260
2261 // Hide the result count
2262 if( empty($_POST['atts']['show_result']) ){
2263 remove_action( 'woocommerce_before_shop_loop', 'woocommerce_result_count', 20 );
2264 }
2265
2266 if( $type == 'by_id' ){
2267 $type = 'products';
2268 $attributes .= ' ids="'. (!empty($_POST['atts']['ids']) ? $_POST['atts']['ids'] : '') .'" ';
2269 }elseif( $type == 'pagelayer_current_query' ){
2270
2271 $atts['paginate'] = (!empty($_POST['atts']['paginate']) ? true : false);
2272 $atts['cache'] = false;
2273
2274 $type = 'pagelayer_current_query';
2275
2276 // Set the current query
2277 add_action( 'woocommerce_shortcode_products_query', 'pagelayer_shortcode_current_query', 10, 10);
2278
2279 // If product not found
2280 add_action( "woocommerce_shortcode_{$type}_loop_no_results", function ($attributes) use ($no_found){
2281 echo '<div class="pagelayer-product-no-found">'.$no_found.'</div>';
2282 } );
2283
2284 // Get the products list
2285 $shortcode = new WC_Shortcode_Products( $atts, $type );
2286
2287 echo $shortcode->get_content();
2288 return true;
2289 }
2290
2291 $shortcode = '['.$type.' '. $attributes .']';
2292
2293 $content = pagelayer_the_content($shortcode);
2294
2295 // If product not found
2296 if('<div class="woocommerce columns-'.$_POST['atts']['columns'] .' "></div>' == $content){
2297 $content = '<div class="pagelayer-product-no-found">'. $no_found .'</div>';
2298 }
2299
2300 echo $content;
2301
2302 wp_die();
2303 }
2304
2305 // Markdown Handler
2306 add_action('wp_ajax_pagelayer_handle_markdown', 'pagelayer_handle_markdown');
2307 function pagelayer_handle_markdown(){
2308
2309 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
2310
2311 if(!defined('PAGELAYER_PRO_VERSION')){
2312 wp_send_json_error(['message' => __('Markdown feature requires Pagelayer Pro.', 'pagelayer')]);
2313 return;
2314 }
2315
2316 include_once(PAGELAYER_PRO_DIR.'/main/premium_functions.php');
2317
2318 $raw_atts = isset($_POST['data']) && is_array($_POST['data']) ? wp_unslash($_POST['data']) : [];
2319 $atts = [];
2320
2321 foreach($raw_atts as $key => $value){
2322 $clean_key = sanitize_key($key);
2323
2324 // Check for invalid UTF-8 to prevent database errors
2325 if(in_array($clean_key, ['markdown_text_file', 'markdown_text_url', 'active_markdown_text'])){
2326 $atts[$clean_key] = wp_check_invalid_utf8($value);
2327 } else{
2328 $atts[$clean_key] = sanitize_text_field($value);
2329 }
2330 }
2331
2332 $fetched = pagelayer_get_markdown_content($atts);
2333 $current_text = $fetched['text'];
2334 $default_text = __pl('Select a Markdown file or enter a URL to load content.');
2335
2336 // Compile HTML
2337 $html = '';
2338 if(!empty($fetched['is_error'])){
2339 $html = '<div class="pagelayer-markdown-error">' . esc_html($current_text) . '</div>';
2340 } else if($current_text === $default_text){
2341 $html = '<div class="pagelayer-markdown-placeholder">' . $default_text . '</div>';
2342 } else if(function_exists('pagelayer_markdown_to_html')){
2343 $html = pagelayer_markdown_to_html($current_text);
2344 }
2345
2346 $wp['html'] = wp_kses_post($html);
2347 $wp['raw_text'] = $current_text;
2348 $wp['is_error'] = !empty($fetched['is_error']);
2349
2350 pagelayer_json_output($wp);
2351
2352 wp_die();
2353 }
2354
2355 // Get Taxamony List for SiteMap
2356 add_action('wp_ajax_pagelayer_get_taxonomy_list', 'pagelayer_get_taxonomy_list');
2357 function pagelayer_get_taxonomy_list(){
2358
2359 // Some AJAX security
2360 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
2361
2362 if(!current_user_can('edit_posts')){
2363 echo __pl('no_permission');
2364 wp_die();
2365 }
2366
2367 $args = array(
2368 'title_li' => 0,
2369 'orderby' => $_POST['post_order'],
2370 'order' => $_POST['order'],
2371 'style' => '',
2372 'hide_empty' => $_POST['empty'],
2373 'echo' => false,
2374 'hierarchical' => (empty($_POST['hier']) || $_POST['hier'] == null ? '' : $_POST['hier']),
2375 'taxonomy' => $_POST['type'],
2376 'depth' => (empty($_POST['depth']) || $_POST['depth'] == null ? '' : $_POST['depth']),
2377 );
2378
2379 $taxonomies = get_categories( $args );
2380
2381 $option = '<ul>';
2382 foreach ( $taxonomies as $taxonomy ) {
2383 $option .= '<li class="pagelayer-sitemap-list-item" data-postID="'.$taxonomy->term_id.'"><a class="pagelayer-ele-link" href="'.get_term_link($taxonomy->term_id).'">'.$taxonomy->name.'</a></li>';
2384 }
2385 $option .= '</ul>';
2386
2387 echo $option;
2388 wp_die();
2389 }
2390
2391 // Export the template
2392 add_action('wp_ajax_pagelayer_export_template', 'pagelayer_export_template');
2393 function pagelayer_export_template(){
2394
2395 global $pagelayer;
2396
2397 // Some AJAX security
2398 check_ajax_referer('pagelayer_builder', 'pagelayer_nonce');
2399
2400 $done = [];
2401
2402 if(!current_user_can('edit_theme_options')){
2403 $done['error'][] = __pl('no_permission');
2404 pagelayer_json_output($done);
2405 }
2406
2407 // Load the templates
2408 pagelayer_builder_load_templates();
2409
2410 if(empty($pagelayer->templates)){
2411 $done['error'] = __pl('temp_export_empty');
2412 pagelayer_json_output($done);
2413 }
2414
2415 // Load Shortcodes
2416 pagelayer_load_shortcodes();
2417
2418 // Get the active theme
2419 $theme_dir = get_stylesheet_directory();
2420 $conf = [];
2421
2422 $pagelayer->export_mode = 1;
2423
2424 // Write the files
2425 foreach($pagelayer->templates as $k => $v){
2426
2427 // Are there specific templates to export
2428 if(!empty($_POST['templates'])){
2429 if(!isset($_POST['templates'][$v->ID])){
2430 continue;
2431 }
2432 }
2433
2434 // Only blocks allowed
2435 if(!has_blocks($v->post_content) && !empty($v->post_content)){
2436 $done['error'] = 'The pagelayer template '.$v->ID.' has Shortcodes which is not allowed for export !';
2437 pagelayer_json_output($done);
2438 }
2439
2440 $v->post_name = (empty($v->post_name) && $v->post_status == 'draft') ? sanitize_title($v->post_title).'-draft' : $v->post_name;
2441
2442 // Write the content
2443 file_put_contents($theme_dir.'/'.$v->post_name.'.pgl', pagelayer_export_content($v->post_content));
2444 $conf[$v->post_name] = [
2445 'type' => get_post_meta($v->ID, 'pagelayer_template_type', true),
2446 'title' => $v->post_title,
2447 'conditions' => get_post_meta($v->ID, 'pagelayer_template_conditions', true),
2448 ];
2449 }
2450
2451 // Write the config
2452 file_put_contents($theme_dir.'/pagelayer.conf', json_encode($conf, JSON_PRETTY_PRINT));
2453
2454 $conf = [];
2455
2456 // Load the other posts
2457 foreach($pagelayer->settings['post_types'] as $type){
2458
2459 // Anything to export for users ?
2460 if(!empty($_POST[$type]) && is_array($_POST[$type])){
2461
2462 mkdir($theme_dir.'/data/');
2463 mkdir($theme_dir.'/data/'.$type);
2464
2465 $pids = [];
2466
2467 foreach($_POST[$type] as $k => $v){
2468 $pids[] = (int) $k;
2469 }
2470
2471 // Load the type
2472 $_query = new WP_Query([
2473 'post_type' => $type,
2474 'status' => 'publish',
2475 'post__in' => $pids,
2476 'posts_per_page' => -1,
2477 ]);
2478
2479 $posts = $_query->posts;
2480
2481 // Write the files
2482 foreach($posts as $k => $v){
2483
2484 // Only blocks allowed
2485 if(!has_blocks($v->post_content) && !empty($v->post_content)){
2486 $done['error'] = 'The '.$type.' '.$v->ID.' has Shortcodes which is not allowed for export !';
2487 pagelayer_json_output($done);
2488 }
2489
2490 $v->post_name = (empty($v->post_name) && $v->post_status == 'draft') ? sanitize_title($v->post_title).'-draft' : $v->post_name;
2491
2492 file_put_contents($theme_dir.'/data/'.$type.'/'.$v->post_name, pagelayer_export_content($v->post_content));
2493 unset($v->post_content);
2494
2495 $meta = get_post_meta($v->ID);
2496 $meta = array_combine(array_keys($meta), array_column($meta, 0));
2497
2498 // Export media
2499 if(!empty($meta['_thumbnail_id'])){
2500
2501 $file = pagelayer_export_media_files($meta['_thumbnail_id'], $exp_img_url);
2502
2503 // Did it export ?
2504 if(!empty($file)){
2505 $meta['_thumbnail_id'] = $exp_img_url;
2506 }
2507
2508 }
2509
2510 // Also put the meta
2511 file_put_contents($theme_dir.'/data/'.$type.'/'.$v->post_name.'.meta', json_encode($meta, JSON_PRETTY_PRINT));
2512
2513 //Export taxonomies in post
2514 $taxonomies = get_object_taxonomies( $v->post_type, 'objects' );
2515 $post_taxonomies = wp_filter_object_list( $taxonomies, [
2516 'public' => true,
2517 'show_in_nav_menus' => true,
2518 ] );
2519
2520 foreach( $post_taxonomies as $slug => $object ){
2521
2522 if(empty($v->taxonomies) || !is_array($v->taxonomies)){
2523 $v->taxonomies = array();
2524 }
2525
2526 $tax_name = $object->name;
2527 $the_terms = get_the_terms($v->ID, $tax_name);
2528 $v->taxonomies[$tax_name] = '';
2529
2530 if(!empty($the_terms)){
2531 $v->taxonomies[$tax_name] = implode(',', array_column($the_terms, 'term_id'));
2532 }
2533 }
2534
2535 $conf[$type][$v->post_name] = $v;
2536
2537 do_action('pagelayer_'.$type.'_exported', $v, $theme_dir);
2538
2539 }
2540
2541 ksort($conf[$type]);
2542
2543 }
2544
2545 }
2546
2547 // Export menus
2548 if(!empty($pagelayer->export_menus) && is_array($pagelayer->export_menus)){
2549
2550 mkdir($theme_dir.'/data/menus');
2551
2552 foreach($pagelayer->export_menus as $k => $v){
2553
2554 $menu = (int) $k;
2555 $menu = wp_get_nav_menu_object( $menu );
2556
2557 if(empty($menu)){
2558 $done['error'] = 'Could not export menu ID - '.$k;
2559 continue;
2560 }
2561
2562 // Menu Items
2563 $menu_items = wp_get_nav_menu_items( $menu->term_id );
2564 $data = [];
2565
2566 if(is_array($menu_items) && !empty($menu_items)){
2567 foreach($menu_items as $kk => $singlenav){
2568 //$navmetas = get_post_meta($singlenav->ID);
2569 //$navmetas = array_combine(array_keys($navmetas), array_column($navmetas, 0));
2570 $data[$kk]['post'] = $singlenav;
2571 $navmetas = array();
2572
2573 $pl_content = get_post_meta($singlenav->ID, '_pagelayer_content', true);
2574 if(!empty($pl_content)){
2575 $navmetas['_pagelayer_content'] = pagelayer_export_content($pl_content);
2576 }
2577
2578 $data[$kk]['post_metas'] = $navmetas;
2579 }
2580 }
2581
2582 // Also put the meta
2583 file_put_contents($theme_dir.'/data/menus/'.$menu->slug, json_encode($data, JSON_PRETTY_PRINT));
2584
2585 $conf['menus'][$menu->slug] = $menu;
2586
2587 do_action('pagelayer_menus_exported', $v, $theme_dir);
2588
2589 }
2590
2591 }
2592
2593 // Export the settings
2594 $settings = ['pagelayer_content_width', 'pagelayer_body_font', 'pagelayer_tablet_breakpoint', 'pagelayer_mobile_breakpoint', 'pagelayer_header_code','pagelayer_body_open_code', 'pagelayer_footer_code', 'pagelayer_sidebar', 'page_for_posts', 'pagelayer_global_fonts', 'pagelayer_global_colors'];
2595
2596 foreach($settings as $v){
2597
2598 $vv = get_option($v);
2599
2600 if($vv){
2601 $conf['conf'][$v] = $vv;
2602 }
2603
2604 }
2605
2606 // Load CSS settings
2607 foreach($pagelayer->css_settings as $k => $params){
2608 foreach($pagelayer->screens as $sk => $sv){
2609 $suffix = (!empty($sv) ? '_'.$sv : '');
2610 $setting = empty($params['key']) ? 'pagelayer_'.$k.'_css' : $params['key'];
2611 $tmp = get_option($setting.$suffix);
2612 if(!empty($tmp)){
2613 $conf['conf'][$setting.$suffix] = $tmp;
2614 }
2615 }
2616 }
2617
2618 // Export all the taxonomies
2619 $post_types = pagelayer_get_public_post_types();
2620
2621 // Export all the Post Type CSS Settings
2622 foreach ( $post_types as $pt_slug => $type ) {
2623
2624 if ( $pt_slug == 'attachment' ) {
2625 continue;
2626 }
2627
2628 foreach($pagelayer->css_settings as $k => $params){
2629 foreach($pagelayer->screens as $sk => $sv){
2630 $suffix = (!empty($sv) ? '_'.$sv : '');
2631 $setting = empty($params['key']) ? 'pagelayer_'.$k.'_css_'.$pt_slug : $params['key'].'_'.$pt_slug;
2632 $tmp = get_option($setting.$suffix);
2633
2634 if(!empty($tmp)){
2635 $conf['conf'][$setting.$suffix] = $tmp;
2636 }
2637 }
2638 }
2639 }
2640
2641 // Export all the taxonomies
2642 foreach ( $post_types as $post_type => $label ) {
2643 $type_taxonomies = get_object_taxonomies( $post_type, 'objects' );
2644 $taxonomies = wp_filter_object_list( $type_taxonomies, [
2645 'public' => true,
2646 'show_in_nav_menus' => true,
2647 ] );
2648
2649 foreach( $taxonomies as $slug => $object ){
2650
2651 $query_params = [
2652 'taxonomy' => $object->name,
2653 'hide_empty' => false,
2654 ];
2655 $terms = get_terms( $query_params );
2656
2657 foreach($terms as $term){
2658 $conf['taxonomies'][$term->term_id] = $term;
2659 }
2660 }
2661
2662 }
2663
2664 // Write the config
2665 if(!empty($conf)){
2666 file_put_contents($theme_dir.'/pagelayer-data.conf', json_encode($conf, JSON_PRETTY_PRINT));
2667 }
2668
2669 // Are we to export any media ?
2670 if(!empty($pagelayer->media_to_export)){
2671 // TODO
2672 //$done['media'] = $pagelayer->media_to_export;
2673 }
2674
2675 do_action('pagelayer_template_export_completed');
2676
2677 $done['success'] = __pl('temp_export_success');
2678
2679 // Output and die
2680 pagelayer_json_output($done);
2681
2682 }
2683
2684 add_action('wp_ajax_pagelayer_get_cat_checkboxes', 'pagelayer_get_cat_checkboxes');
2685 function pagelayer_get_cat_checkboxes(){
2686
2687 // Some AJAX security
2688 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
2689
2690 $ret = [];
2691 $cat_name = '';
2692
2693 if(!current_user_can('manage_categories')){
2694 $ret['error'] = __pl('no_permission');
2695 pagelayer_json_output($ret);
2696 }
2697
2698 if(empty($_POST['postid']) || !is_numeric($_POST['postid'])){
2699 $ret['error'] = __pl('invalid_post_id');
2700 pagelayer_json_output($ret);
2701 }
2702
2703 $post = (int) $_POST['postid'];
2704 $post = get_post($post);
2705
2706 if(empty($post) || is_wp_error($post)){
2707 $ret['error'] = __pl('invalid_post_id');
2708 pagelayer_json_output($ret);
2709 }
2710
2711 $cat_name = pagelayer_post_type_category($post->post_type);
2712
2713 if(!empty($_POST['new_cat'])){
2714 parse_str($_POST['new_cat'], $formdata);
2715 $ret['new_cat_id'] = wp_insert_category([
2716 'taxonomy' => $cat_name,
2717 'cat_name' => $formdata['category_name'],
2718 'category_parent' => (($formdata['pagelayer_cat_parent'] == 0) ? '' : $formdata['pagelayer_cat_parent'])
2719 ]);
2720 }
2721
2722 $ret += pagelayer_post_cats($post);
2723
2724 pagelayer_json_output($ret);
2725
2726 }
2727
2728 add_action('wp_ajax_pagelayer_get_post_tags', 'pagelayer_get_post_tags');
2729 function pagelayer_get_post_tags(){
2730
2731 // Some AJAX security
2732 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
2733
2734 $ret = [];
2735 $tag_name = '';
2736
2737 if(!current_user_can('manage_categories')){
2738 $ret['error'] = __pl('no_permission');
2739 pagelayer_json_output($ret);
2740 }
2741
2742 if(empty($_POST['postid']) || !is_numeric($_POST['postid']) ){
2743 pagelayer_json_output($ret);
2744 }
2745
2746 $post = (int) $_POST['postid'];
2747 $post = get_post($post);
2748
2749 if(empty($post) || is_wp_error($post)){
2750 $ret['error'] = __pl('invalid_post_id');
2751 pagelayer_json_output($ret);
2752 }
2753
2754 $tag_name = pagelayer_post_type_tag($post->post_type);
2755
2756 if(!empty($_POST['new_tag'])){
2757 $ret['tag_id'] = wp_insert_term($_POST['new_tag'], $tag_name);
2758 $ret['tag_id'] = $ret['tag_id']['term_id'];
2759 }
2760
2761 $ret += pagelayer_post_tags($post);
2762
2763 pagelayer_json_output($ret);
2764
2765 }
2766
2767 add_action('wp_ajax_pagelayer_custom_font', 'pagelayer_custom_font');
2768 function pagelayer_custom_font(){
2769
2770 // Some AJAX security
2771 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
2772
2773 $ret = [];
2774
2775 if(empty($_POST['font_name'])){
2776 pagelayer_json_output($ret);
2777 }
2778
2779 $name = preg_replace('/_plf$/is', '', pagelayer_optREQ('font_name'));
2780 //echo $name;
2781
2782 $args = [
2783 'post_type' => PAGELAYER_FONT_POST_TYPE,
2784 'status' => 'publish',
2785 'posts_per_page' => 1,
2786 'name' => $name
2787 ];
2788
2789 //var_dump($pagelayer->fonts);
2790
2791 $query = get_posts($args);
2792 //var_dump($query);
2793
2794 if(empty($query)){
2795 pagelayer_json_output($ret);
2796 }
2797
2798 $post = $query[0];
2799 $meta_box_value = get_post_meta( $post->ID, 'pagelayer_font_link', true);
2800 if(empty($meta_box_value)){
2801 pagelayer_json_output($ret);
2802 }
2803
2804 $ret['style']= '<style id="'.$name.'_plf" >@font-face { font-family: "'.$name.'_plf"'.'; src: url("'.$meta_box_value.'"); font-weight: 100 200 300 400 500 600 700 800 900;}</style>';
2805
2806 pagelayer_json_output($ret);
2807
2808 }
2809
2810 add_action('wp_ajax_pagelayer_trash_post', 'pagelayer_trash_post');
2811 function pagelayer_trash_post(){
2812
2813 // Some AJAX security
2814 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
2815
2816 $ret = [];
2817
2818 if(empty($_POST['postid']) && !is_numeric($_POST['postid'])){
2819 $ret = ['error' => __pl('invalid_post_id')];
2820 pagelayer_json_output($ret);
2821 }
2822
2823 if(!current_user_can( 'delete_post', $_POST['postid'] )){
2824 $ret = ['error' => __pl('no_permission')];
2825 pagelayer_json_output($ret);
2826 }
2827
2828 $ret['url'] = admin_url('/edit.php?post_type=') .get_post_type($_POST['postid']);
2829
2830 wp_trash_post($_POST['postid']);
2831
2832 pagelayer_json_output($ret);
2833
2834 }
2835
2836 add_action('wp_ajax_pagelayer_infinite_posts', 'pagelayer_infinite_posts');
2837 add_action('wp_ajax_nopriv_pagelayer_infinite_posts', 'pagelayer_infinite_posts');
2838 function pagelayer_infinite_posts(){
2839
2840 // Some AJAX security
2841 check_ajax_referer('pagelayer_global', 'pagelayer_nonce');
2842
2843 pagelayer_load_shortcodes();
2844
2845 $tag = 'pl_posts';
2846
2847 if(isset($_REQUEST['data']['tag']) && $_REQUEST['data']['tag'] == 'pl_archive_posts' ){
2848 $tag = 'pl_archive_posts';
2849 }
2850
2851 $content = get_comment_delimited_block_content( 'pagelayer/'.$tag, $_REQUEST['data']['atts'] , '');
2852 $wp['posts'] = pagelayer_the_content($content);
2853 pagelayer_json_output( $wp );
2854 }
2855
2856 add_action('wp_ajax_pagelayer_pro_dismiss_expired_licenses', 'pagelayer_pro_dismiss_expired_licenses');
2857 function pagelayer_pro_dismiss_expired_licenses(){
2858 check_admin_referer('pagelayer_expiry_notice', 'security');
2859
2860 if(!current_user_can('activate_plugins')){
2861 wp_send_json_error(__('You do not have required access to do this action', 'pagelayer'));
2862 }
2863
2864 update_option('softaculous_expired_licenses', time());
2865 wp_send_json_success();
2866 }
2867
2868 add_action('wp_ajax_pagelayer_close_update_notice', 'pagelayer_close_plugin_update_notice');
2869 function pagelayer_close_plugin_update_notice(){
2870 check_ajax_referer('pagelayer_promo_nonce', 'pagelayer_nonce');
2871
2872 if(!current_user_can('manage_options')){
2873 wp_send_json_error('You don\'t have privilege to close this notice!');
2874 }
2875
2876 $plugin_update_notice = get_option('softaculous_plugin_update_notice', []);
2877 $available_update_list = get_site_transient('update_plugins');
2878 $to_update_plugins = apply_filters('softaculous_plugin_update_notice', []);
2879
2880 if(empty($available_update_list) || empty($available_update_list->response)){
2881 return;
2882 }
2883
2884 foreach($to_update_plugins as $plugin_path => $plugin_name){
2885 if(isset($available_update_list->response[$plugin_path])){
2886 $plugin_update_notice[$plugin_path] = $available_update_list->response[$plugin_path]->new_version;
2887 }
2888 }
2889
2890 update_option('softaculous_plugin_update_notice', $plugin_update_notice);
2891 }