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

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

2,809 lines 80.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 // Update Post content
588 add_action('wp_ajax_pagelayer_save_content', 'pagelayer_save_content');
589 function pagelayer_save_content(){
590
591 // Some AJAX security
592 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
593
594 $content = $_POST['pagelayer_update_content'];
595
596 $postID = (int) $_GET['postID'];
597
598 if(empty($postID)){
599 $msg['error'] = __pl('invalid_post_id');
600 pagelayer_json_output($msg);
601 }
602
603 $_post = get_post($postID);
604
605 // Post found ?
606 if(empty($_post)){
607 $msg['error'] = __pl('invalid_post_id');
608 pagelayer_json_output($msg);
609 }
610
611 // Get the post type and its capabilities
612 $post_type = $_post->post_type;
613 $post_type_obj = get_post_type_object($post_type);
614
615 // Are you allowed to edit ?
616 if(!pagelayer_user_can_edit($postID)){
617 $msg['error'][] = __pl('no_permission');
618 pagelayer_json_output($msg);
619 }
620
621 // Check if the post exists
622 if(!empty($postID)){
623
624 $content = base64_decode($content);
625
626 /*if(!pagelayer_is_utf8($content)){
627 $content = utf8_encode($content);
628 }*/
629
630 $is_xss = pagelayer_xss_content($content);
631
632 if(!pagelayer_user_can_add_js_content() && strlen($is_xss) > 0){
633 $msg['error'][] = __pl('xss_found').' - '.$is_xss;
634 pagelayer_json_output($msg);
635 }
636
637 // Is comment mode?
638 if(pagelayer_is_comment_mode()){
639 global $pagelayer_comment_errors, $pagelayer_comment_alerts;
640 $content = pagelayer_extract_comment_atts($postID, $content);
641 }
642
643 // Add slash to save data in post
644 $content = wp_slash($content);
645
646 $post = array(
647 'ID' => $postID,
648 'post_content' => $content,
649 );
650
651 // Any properties ?
652 $allowed = ['post_title', 'post_name', 'post_excerpt', 'post_status', 'post_password', 'post_date', 'post_parent', 'menu_order'];
653
654 foreach($allowed as $k){
655 if(isset($_REQUEST[$k])){
656 $post[$k] = sanitize_text_field($_REQUEST[$k]);
657 }
658 }
659
660 // Restrict contributors from setting 'publish' or modifying unauthorized fields
661 $current_user_can_publish = current_user_can($post_type_obj->cap->publish_posts);
662 if(!$current_user_can_publish){
663 if(!in_array($post['post_status'], ['draft', 'pending'])){
664 $post['post_status'] = 'pending'; // Force pending status
665 }
666 }
667
668 if(!empty($post['post_password'])){
669 if($_REQUEST['post_sticky'] == true){
670 $msg['error'] = __pl('post_pass_with_sticky_err');
671 pagelayer_json_output($msg);
672 }
673
674 // Prevent unauthorized password protection
675 $can_protect = current_user_can($post_type_obj->cap->edit_private_posts);
676 if(!$can_protect){
677 $msg['error'][] = __pl('no_permission_to_set_password');
678 pagelayer_json_output($msg);
679 }
680 }
681
682 // Prevent unauthorized modification of `post_author`
683 if(isset($_REQUEST['post_author']) && $_REQUEST['post_author'] != $_post->post_author){
684
685 $edit_others_posts = current_user_can($post_type_obj->cap->edit_others_posts);
686
687 if($edit_others_posts){
688 $post['post_author'] = (int) $_REQUEST['post_author'];
689 }else{
690 $msg['error'][] = __pl('no_permission_to_change_author');
691 pagelayer_json_output($msg);
692 }
693 }
694
695 $post['comment_status'] = !empty($_REQUEST['comment_status']) ? 'open' : 'closed';
696 $post['ping_status'] = !empty($_REQUEST['ping_status']) ? 'open' : 'closed';
697 $post['post_status'] = empty($post['post_status']) ? $_post->post_status : $post['post_status'];
698
699 if(!empty($post['post_status']) && $post['post_status'] == 'publish'){
700
701 // Allowed to publish pages ?
702 if($_post->post_type == 'page' && !current_user_can('publish_pages')){
703 $msg['error'][] = __pl('no_publish_permission');
704 pagelayer_json_output($msg);
705 }
706
707 // Allowed to publish posts ?
708 if($_post->post_type == 'post' && !current_user_can('publish_posts')){
709 $post['post_status'] = 'pending';
710 }
711 }
712
713 if(!empty($post['post_password'])){
714 $post['post_password'] = (in_array($post['post_status'], array('pass_protected', 'publish')) ? $post['post_password'] : '');
715 $post['post_status'] = 'publish';
716 }else{
717 $post['post_status'] = ($post['post_status'] == 'pass_protected') ? 'publish' : $post['post_status'];
718 $post['post_password'] = '';
719 }
720
721 // Set post GMT time
722 if(!empty($post['post_date']) && '0000-00-00 00:00:00' !== $post['post_date']){
723 $post['post_date_gmt'] = get_gmt_from_date( $post['post_date'] );
724
725 if( in_array($post['post_status'], array('future', 'publish')) && $_post->post_date_gmt === '0000-00-00 00:00:00' ){
726 $post['edit_date'] = true;
727 }
728 }
729
730 $_REQUEST['featured_image'] = (int) $_REQUEST['featured_image'];
731 if(!empty($_REQUEST['featured_image'])){
732 set_post_thumbnail($postID, $_REQUEST['featured_image']);
733 }else{
734 delete_post_thumbnail($postID);
735 }
736
737 if(!isset($_REQUEST['post_category'])){
738 $_REQUEST['post_category'] = '';
739 }
740
741 if(!isset($_REQUEST['post_tags'])){
742 $_REQUEST['post_tags'] = '';
743 }
744
745 if($_post->post_type == 'post'){
746 $post['post_category'] = pagelayer_sanitize_text_field($_REQUEST['post_category']);
747
748 $post['tags_input'] = pagelayer_sanitize_text_field($_REQUEST['post_tags']);
749 }else{
750 $cat_name = pagelayer_post_type_category($_post->post_type);
751 if($cat_name){
752 $post['tax_input'][$cat_name] = pagelayer_sanitize_text_field($_REQUEST['post_category']);
753 }
754
755 $tag_name = pagelayer_post_type_tag($_post->post_type);
756 if($tag_name){
757 $post['tax_input'][$tag_name] = pagelayer_sanitize_text_field($_REQUEST['post_tags']);
758 }
759 }
760
761 if(isset($_REQUEST['post_sticky']) && !empty($_REQUEST['post_sticky'])){
762 stick_post( $postID );
763 }else{
764 if(is_sticky($postID)){
765 unstick_post( $postID );
766 }
767 }
768
769 // Any contact templates ?
770 if(!empty($_REQUEST['contacts']) && current_user_can('activate_plugins')){
771 update_post_meta($postID, 'pagelayer_contact_templates', $_REQUEST['contacts']);
772 }else{
773 delete_post_meta($postID, 'pagelayer_contact_templates');
774 }
775
776 // Save copyright
777 if(isset($_REQUEST['copyright']) && current_user_can('manage_options')){
778 update_option('pagelayer-copyright', wp_unslash($_REQUEST['copyright']));
779 }
780
781 // Apply a filter
782 $post = apply_filters('pagelayer_save_content', $post);
783
784 // Update the post into the database
785 $ret = wp_update_post($post, true);
786
787 // Render the post
788 //update_post_meta($postID, 'pagelayer_rendered_post', pagelayer_get_post_content($postID));
789
790 if (is_wp_error($ret)) {
791 $errors = $ret->get_error_messages();
792 $msg['error'] = __pl('post_update_err').' : '.implode('', $errors);
793 }else{
794
795 // Get the updated post
796 $_post = get_post($postID);
797
798 // Is this a Pagelayer post
799 $data = get_post_meta($postID, 'pagelayer-data', true);
800
801 if(empty($data)){
802
803 // Convert to pagelayer accessed post
804 if(!add_post_meta($postID, 'pagelayer-data', time(), true)){
805 update_post_meta($postID, 'pagelayer-data', time());
806 }
807 }
808
809 if(!empty($pagelayer_comment_alerts)){
810 $msg['comment_alerts'] = $pagelayer_comment_alerts;
811 }
812
813 if(!empty($pagelayer_comment_errors)){
814 $msg['error'][] = 'Comment Mode errrors found !';
815 $msg['comment_errors'] = $pagelayer_comment_errors;
816 }
817
818 $msg['success'] = __pl('post_update_success');
819 }
820
821 }else{
822 $msg['error'] = __pl('post_update_err');
823 }
824
825 $msg['post_status'] = (empty($_post->post_password)) ? $_post->post_status : 'pass_protected';
826
827 // Save global widgets data
828 if(!empty($_REQUEST['global_widgets'])){
829 pagelayer_save_templ_content(true);
830 }
831
832 // Save nav menu data
833 if(!empty($_REQUEST['pagelayer_nav_items']) && current_user_can('edit_theme_options')){
834 $menu_items = (array) $_REQUEST['pagelayer_nav_items'];
835 foreach($menu_items as $items){
836 pagelayer_save_nav_menu_items($items);
837 }
838 }
839
840 // Save Customizer data
841 if(!empty($_REQUEST['pagelayer_customizer_options']) && current_user_can('edit_theme_options')){
842
843 $customizer_options = wp_unslash($_REQUEST['pagelayer_customizer_options']);
844 $customizer_options = json_decode($customizer_options, true);
845
846 // Add current post type
847 $customizer_options['pagelayer_current_post_type'] = $_post->post_type;
848
849 pagelayer_save_customizer_options($customizer_options);
850 }
851
852 pagelayer_json_output($msg);
853
854 }
855
856 // Save sections and global sections
857 add_action('wp_ajax_pagelayer_save_templ_content', 'pagelayer_save_templ_content');
858 function pagelayer_save_templ_content($echo = false){
859
860 // Some AJAX security
861 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
862
863 if ( ! current_user_can( get_post_type_object( 'pagelayer-template' )->cap->create_posts ) ) {
864 $ret['error'][$g_post_id] = __pl('no_permission');
865 pagelayer_json_output($ret);
866 return false;
867 }
868
869 // Are you allowed to edit ?
870 if(!pagelayer_user_can_edit($_REQUEST['postID'])){
871 $msg['error'][] = __pl('no_permission');
872 pagelayer_json_output($msg);
873 }
874
875 $ret = array();
876
877 // Save global widgets data
878 if(empty($_REQUEST['global_widgets'])){
879 $ret['error'][] = 'No widgets given';
880 pagelayer_json_output($ret);
881 return false;
882 }
883
884 $global_widgets = $_REQUEST['global_widgets'];
885
886 foreach($global_widgets as $key => $value){
887
888 $g_post_id = (int) $value['post_id'];
889
890 // Are you allowed to edit ?
891 if(!empty($g_post_id) && !pagelayer_user_can_edit($g_post_id)){
892 $ret['error'][$g_post_id] = __pl('no_permission').' : '.$g_post_id;
893 continue;
894 }
895
896 // Decode base64 data
897 $value['content'] = base64_decode($value['content']);
898
899 $is_xss = pagelayer_xss_content($value['content']);
900
901 if(!current_user_can('manage_options') && strlen($is_xss) > 0){
902 $ret['error'][$g_post_id] = __pl('xss_found').' - '.$is_xss;
903 pagelayer_json_output($ret);
904 }
905
906 // Add slash to save data in post
907 $value['content'] = wp_slash($value['content']);
908
909 // We need to create the post
910 if(empty($value['post_id'])){
911
912 $g_ret = wp_insert_post([
913 'post_type' => 'pagelayer-template',
914 'post_title' => $value['title'],
915 'post_content' => $value['content'],
916 'post_status' => 'publish',
917 'comment_status' => 'closed',
918 'ping_status' => 'closed'
919 ]);
920
921 $g_post_id = $g_ret;
922
923 // Save our template metas
924 update_post_meta($g_post_id, 'pagelayer_template_type', $value['type']);
925 update_post_meta($g_post_id, 'pagelayer-data', time());
926
927 }else if(!empty($value['content'])){
928
929 // Save global widget content
930 $post = array(
931 'ID' => $g_post_id,
932 'post_title' => $value['title'],
933 'post_content' => $value['content'],
934 );
935
936 wp_update_post($post);
937 }
938
939 if(is_wp_error($g_post_id)){
940 $ret['error'][$g_post_id] = __pl('template_update_err');
941 }else{
942 $ret['success'][$g_post_id] = __pl('template_update_success');
943 }
944 }
945
946 if(!$echo){
947 pagelayer_json_output($ret);
948 }else{
949 return $ret;
950 }
951 }
952
953 // Update the Site Title
954 add_action('wp_ajax_pagelayer_set_jscss_giver', 'pagelayer_set_jscss_giver');
955 function pagelayer_set_jscss_giver(){
956 global $wpdb;
957
958 // Some AJAX security
959 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
960
961 if( !current_user_can('manage_options') ){
962 $ret['error'] = __pl('no_permission');
963 pagelayer_json_output($ret);
964 }
965
966 $val = (int) @$_REQUEST['set'];
967
968 if(in_array($val, [1, -1])){
969 update_option('pagelayer_enable_giver', $val);
970 }
971
972 $ret['success'] = 1;
973 pagelayer_json_output($ret);
974 }
975
976 // Shortcodes Widget Handler
977 add_action('wp_ajax_pagelayer_do_shortcodes', 'pagelayer_do_shortcodes');
978 function pagelayer_do_shortcodes(){
979
980 // Some AJAX security
981 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
982
983 if(!current_user_can('edit_posts')){// TODO : WooCommerce
984 $ret['error'][] = __pl('no_permission');
985 pagelayer_json_output($ret);
986 }
987
988 $data = '';
989 if(isset($_REQUEST['shortcode_data'])){
990 $data = stripslashes($_REQUEST['shortcode_data']);
991 }
992
993 // Load shortcodes
994 pagelayer_load_shortcodes();
995
996 $data = pagelayer_the_content($data);
997
998 // Create the HTML object
999 $node = pagelayerQuery::parseStr($data);
1000 $node->query('.pagelayer-ele')->removeClass('pagelayer-ele');
1001 echo $node->html();
1002
1003 wp_die();
1004
1005 }
1006
1007 // Give the JS
1008 add_action('wp_ajax_pagelayer_givejs', 'pagelayer_givejs');
1009 function pagelayer_givejs(){
1010
1011 global $pagelayer;
1012
1013 // WordPress adds the Expires header in all AJAX calls. We need to remove it for cache to work
1014 header_remove("Expires");
1015 header_remove("Cache-Control");
1016
1017 // Load shortcodes
1018 pagelayer_load_shortcodes();
1019
1020 // Load font options
1021 pagelayer_load_font_options();
1022
1023 // Pagelayer Template Loading Mechanism
1024 include_once(PAGELAYER_DIR.'/js/givejs.php');
1025
1026 exit();
1027
1028 }
1029
1030 add_action('wp_ajax_pagelayer_givecss', 'pagelayer_givecss');
1031 add_action('wp_ajax_nopriv_pagelayer_givecss', 'pagelayer_givecss');
1032 function pagelayer_givecss(){
1033
1034 global $pagelayer;
1035
1036 // WordPress adds the Expires header in all AJAX calls. We need to remove it for cache to work
1037 header_remove("Expires");
1038 header_remove("Cache-Control");
1039
1040 // Pagelayer Template Loading Mechanism
1041 include_once(PAGELAYER_DIR.'/css/givecss.php');
1042
1043 exit();
1044
1045 }
1046
1047 // Shortcodes Widget Handler
1048 add_action('wp_ajax_pagelayer_get_section_shortcodes', 'pagelayer_get_section_shortcodes');
1049 function pagelayer_get_section_shortcodes(){
1050
1051 global $pagelayer;
1052
1053 // Some AJAX security
1054 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
1055
1056 if(!current_user_can('edit_posts')){
1057 $ret['error'][] = __pl('no_permission');
1058 pagelayer_json_output($ret);
1059 }
1060
1061 $data = '';
1062 if(isset($_REQUEST['pagelayer_section_id'])){
1063
1064 $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());
1065
1066 // For SitePad users
1067 if(function_exists('get_softaculous_file')){
1068 $get_url = get_softaculous_file($get_url, 1);
1069 }
1070
1071 $fetch = wp_remote_get($get_url, array('timeout' => 60));
1072
1073 if ( is_array( $fetch ) && ! is_wp_error( $fetch ) && isset( $fetch['body'] ) ) {
1074 $data = json_decode( $fetch['body'], true ); // use the content
1075 }else{
1076 $data['error'] = __pl('The response was malformed');
1077 pagelayer_json_output($data);
1078 }
1079 }
1080
1081 if(isset($_REQUEST['postID'])){
1082 $post_id = (int) $_REQUEST['postID'];
1083
1084 if(!empty($post_id)){
1085 $post = get_post( $post_id );
1086 // Need to make the reviews post global
1087 if ( !empty( $post ) ) {
1088 $GLOBALS['post'] = $post;
1089
1090 $GLOBALS['wp_query'] = new WP_Query([
1091 'post_type' => $GLOBALS['post']->post_type,
1092 'post__in' => array($post_id),
1093 ]);
1094 }
1095 }
1096 }
1097
1098 // Upload the images if any in the shortcode
1099 preg_match_all('/"'.preg_quote('{{pl_lib_images}}', '/').'([^"]*)"/is', $data['code'], $matches);
1100
1101 foreach($matches[0] as $k => $v){
1102 $image_url = trim($v, '"\'');
1103 $urls[$image_url] = $image_url;
1104 }
1105
1106 foreach($urls as $k => $image_url){
1107
1108 $file = basename($image_url);
1109 $id = 0;
1110
1111 // Upload this
1112 if(!empty($data[$file])){
1113
1114 $id = pagelayer_upload_media($file, base64_decode($data[$file]));
1115
1116 if(!empty($id)){
1117 $data['code'] = str_replace('"'.$image_url.'"', '"'.$id.'"', $data['code']);
1118 }
1119 }
1120
1121 }
1122
1123 // Load shortcodes
1124 pagelayer_load_shortcodes();
1125
1126 if(!empty($data['code'])){
1127 $data['code'] = pagelayer_the_content($data['code'], true);
1128 }
1129
1130 pagelayer_json_output($data);
1131
1132 }
1133
1134 // Shortcodes Widget Handler
1135 add_action('wp_ajax_pagelayer_get_section_blocks', 'pagelayer_get_section_blocks');
1136 function pagelayer_get_section_blocks(){
1137
1138 global $pagelayer;
1139
1140 // Some AJAX security
1141 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
1142
1143 if(!current_user_can('edit_posts')){
1144 $ret['error'][] = __pl('no_permission');
1145 pagelayer_json_output($ret);
1146 }
1147
1148 $data = '';
1149 if(isset($_REQUEST['pagelayer_section_id'])){
1150
1151 $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());
1152
1153 // For SitePad users
1154 if(function_exists('get_softaculous_file')){
1155 $get_url = get_softaculous_file($get_url, 1);
1156 }
1157
1158 $fetch = wp_remote_get($get_url, array('timeout' => 60));
1159
1160 if ( is_array( $fetch ) && ! is_wp_error( $fetch ) && isset( $fetch['body'] ) ) {
1161 $data = json_decode( $fetch['body'], true ); // use the content
1162 }else{
1163 $data['error'] = __pl('The response was malformed');
1164 pagelayer_json_output($data);
1165 }
1166 }
1167
1168 // Upload the images if any in the shortcode
1169 preg_match_all('/"'.preg_quote('{{pl_lib_images}}', '/').'([^"]*)"/is', $data['code'], $matches);
1170
1171 foreach($matches[0] as $k => $v){
1172 $image_url = trim($v, '"\'');
1173 $urls[$image_url] = $image_url;
1174 }
1175
1176 foreach($urls as $k => $image_url){
1177
1178 $file = basename($image_url);
1179 $id = 0;
1180
1181 // Upload this
1182 if(!empty($data[$file])){
1183
1184 $id = pagelayer_upload_media($file, base64_decode($data[$file]));
1185
1186 if(!empty($id)){
1187 $data['code'] = str_replace('"'.$image_url.'"', '"'.$id.'"', $data['code']);
1188 }
1189 }
1190
1191 }
1192
1193 if ( false !== strpos( $data['code'], '[pl_' ) ) {
1194 // Load shortcodes
1195 pagelayer_load_shortcodes();
1196
1197 // Load Parse Shortcodes
1198 include_once(PAGELAYER_DIR.'/main/parse-shortcodes.php');
1199
1200 $data['code'] = pagelayer_do_shortcode_to_block($data['code']);
1201 }
1202
1203 $data['code'] = pagelayer_add_tmp_atts($data['code']);
1204
1205 pagelayer_json_output($data);
1206
1207 }
1208
1209 // Get the Site Title
1210 add_action('wp_ajax_pagelayer_fetch_site_title', 'pagelayer_fetch_site_title');
1211 function pagelayer_fetch_site_title(){
1212
1213 // Some AJAX security
1214 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
1215
1216 echo get_bloginfo('name');
1217 wp_die();
1218 }
1219
1220 // Update the Site Title
1221 add_action('wp_ajax_pagelayer_update_site_title', 'pagelayer_update_site_title');
1222 function pagelayer_update_site_title(){
1223 global $wpdb;
1224
1225 // Some AJAX security
1226 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
1227
1228 $site_title = $_POST['site_title'];
1229
1230 if(!current_user_can('manage_options')){
1231 $ret['error'][] = __pl('no_permission');
1232 pagelayer_json_output($ret);
1233 }
1234
1235 update_option('blogname', $site_title);
1236
1237 wp_die();
1238 }
1239
1240 // Show the SideBars
1241 add_action('wp_ajax_pagelayer_fetch_sidebar', 'pagelayer_fetch_sidebar');
1242 function pagelayer_fetch_sidebar(){
1243
1244 global $wp_registered_sidebars;
1245
1246 // Some AJAX security
1247 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
1248
1249 // Create a list
1250 $pagelayer_wp_widgets = array();
1251
1252 foreach($wp_registered_sidebars as $v){
1253 $pagelayer_wp_widgets[$v['id']] = $v['name'];
1254 }
1255
1256 $id = @$_REQUEST['sidebar'];
1257
1258 if(function_exists('dynamic_sidebar') && !empty($pagelayer_wp_widgets[$id])) {
1259 ob_start();
1260 dynamic_sidebar($id);
1261 $result = ob_get_clean();
1262 }else{
1263 $result = __pl('no_widget_area');
1264 }
1265
1266 echo $result;
1267 wp_die();
1268
1269 }
1270
1271 // Show the primary menu !
1272 add_action('wp_ajax_pagelayer_fetch_primary_menu', 'pagelayer_fetch_primary_menu');
1273 function pagelayer_fetch_primary_menu(){
1274
1275 // Some AJAX security
1276 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
1277
1278 if(isset($_POST['nav_list'])){
1279 $_POST['nav_list'] = (int) $_POST['nav_list'];
1280
1281 // Load Pagelayer nav menu walker
1282 include_once(PAGELAYER_DIR.'/main/nav_walker.php');
1283
1284 $postID = (int) $_REQUEST['postID'];
1285
1286 // To on live mode
1287 $GLOBALS['post'] = get_post($postID);
1288 $GLOBALS['wp_query'] = new WP_Query([
1289 'post_type' => $GLOBALS['post']->post_type,
1290 'post__in' => array($postID),
1291 ]);
1292
1293 // Load short
1294 pagelayer_load_shortcodes();
1295
1296 wp_nav_menu([
1297 'menu' => wp_get_nav_menu_object($_POST['nav_list']),
1298 'menu_id' => $_POST["nav_list"],
1299 'menu_class' => 'pagelayer-wp_menu-ul',
1300 'walker' => new Pagelayer_Walker_Nav_Menu(),
1301 //'theme_location' => 'primary',
1302 'echo' => true,
1303 ]);
1304 }
1305
1306 wp_die();
1307 }
1308
1309 // Save post revision
1310 add_action('wp_ajax_pagelayer_create_post_autosave', 'pagelayer_create_post_autosave');
1311 function pagelayer_create_post_autosave(){
1312
1313 // Some AJAX security
1314 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
1315
1316 $ret = array();
1317 $postID = (int) $_GET['postID'];
1318 $content = $_REQUEST['pagelayer_post_content'];
1319
1320 // Decode base64 data
1321 $content = base64_decode($content);
1322 $content = wp_slash($content);
1323
1324 // Are you allowed to edit ?
1325 if(!pagelayer_user_can_edit($postID)){
1326 $ret['error'][] = __pl('no_permission');
1327 pagelayer_json_output($ret);
1328 }
1329
1330 if(empty($postID)){
1331 $ret['error'] = __pl('invalid_post_id');
1332 }else{
1333
1334 $post = array(
1335 'post_ID' => $postID,
1336 'post_content' => $content,
1337 );
1338
1339 $ret['id'] = wp_create_post_autosave($post);
1340 }
1341
1342 $ret['url'] = get_preview_post_link($postID);
1343
1344 pagelayer_json_output($ret);
1345
1346 }
1347
1348 // Get post revision
1349 add_action('wp_ajax_pagelayer_get_revision', 'pagelayer_get_revision');
1350 function pagelayer_get_revision(){
1351
1352 // Some AJAX security
1353 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
1354
1355 $ret = array();
1356 $postID = (int) $_GET['postID'];
1357
1358 // Are you allowed to edit ?
1359 if(!pagelayer_user_can_edit($postID)){
1360 $ret['error'][] = __pl('no_permission');
1361 pagelayer_json_output($ret);
1362 }
1363
1364 if(empty($postID)){
1365 $ret['error'] = __pl('invalid_post_id');
1366 }else{
1367 $ret = pagelayer_get_post_revision_by_id($postID);
1368 }
1369
1370 pagelayer_json_output($ret);
1371
1372 }
1373
1374 // Apply post revision
1375 add_action('wp_ajax_pagelayer_apply_revision', 'pagelayer_apply_revision');
1376 function pagelayer_apply_revision(){
1377
1378 // Some AJAX security
1379 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
1380
1381 $revisionID = (int) $_REQUEST['revisionID'];
1382 $parID = wp_get_post_parent_id($revisionID);
1383 $ret = array();
1384
1385 if(empty($parID)){
1386 $parID = $revisionID;
1387 }
1388
1389 // Are you allowed to edit ?
1390 if(!pagelayer_user_can_edit($parID)){
1391 $ret['error'][] = __pl('no_permission');
1392 pagelayer_json_output($ret);
1393 }
1394
1395 if(empty($revisionID)){
1396 $ret['error'] = __pl('invalid_post_id');
1397 }else{
1398
1399 $post = get_post( $revisionID );
1400
1401 if ( empty( $post ) ) {
1402 $ret['error'] = __pl('invalid_revision');
1403 pagelayer_json_output($ret);
1404 }
1405
1406 // Need to make the reviews post global
1407 $GLOBALS['post'] = $post;
1408 $GLOBALS['wp_query'] = new WP_Query([
1409 'post_type' => $GLOBALS['post']->post_type,
1410 'post__in' => array($parID),
1411 ]);
1412
1413 // Need to reload the shortcodes
1414 pagelayer_load_shortcodes();
1415
1416 $ret['id'] = $revisionID;
1417 $ret['content'] = pagelayer_the_content($post->post_content, true);
1418
1419 if(is_wp_error($post)) {
1420 $ret['error'] = __pl('rev_load_error');
1421 }else{
1422 $ret['success'] = __pl('rev_load_success');
1423 }
1424
1425 wp_reset_postdata();
1426 }
1427
1428 pagelayer_json_output($ret);
1429
1430 }
1431
1432 // Get post revision
1433 add_action('wp_ajax_pagelayer_delete_revision', 'pagelayer_delete_revision');
1434 function pagelayer_delete_revision() {
1435
1436 // Some AJAX security
1437 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
1438
1439 $revisionID = (int) $_REQUEST['revisionID'];
1440 $parID = wp_get_post_parent_id($revisionID);
1441 $ret = array();
1442
1443 // Are you allowed to edit ?
1444 if(!pagelayer_user_can_edit($parID)){
1445 $ret['error'][] = __pl('no_permission');
1446 pagelayer_json_output($ret);
1447 }
1448
1449 if(empty($revisionID)){
1450 $ret['error'] = __pl('invalid_post_id');
1451 }else{
1452
1453 $revision = get_post( $revisionID );
1454
1455 if ( empty( $revision ) ) {
1456 $ret['error'] = __pl('invalid_revision');
1457 }else{
1458
1459 if ( ! current_user_can( 'delete_post', $parID ) ) {
1460 $ret['error'] = __pl('access_denied');
1461 pagelayer_json_output($ret);
1462 }
1463
1464 $deleted = wp_delete_post_revision( $revision->ID );
1465
1466 if ( ! $deleted || is_wp_error( $deleted ) ) {
1467 $ret['error'] = __pl('delete_rev_error');
1468 }else{
1469 $ret['success'] = __pl('delete_rev_success');
1470 }
1471 }
1472 }
1473
1474 pagelayer_json_output($ret);
1475
1476 }
1477
1478 // Get post navigation
1479 add_action('wp_ajax_pagelayer_post_nav', 'pagelayer_post_nav');
1480 function pagelayer_post_nav() {
1481
1482 // Some AJAX security
1483 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
1484
1485 if(!isset($_REQUEST['data']) || !isset($_REQUEST['postID'])){
1486 return;
1487 }
1488
1489 $el['atts'] = $_REQUEST['data'];
1490
1491 $post = get_post($_REQUEST['postID']);
1492
1493 // Need to make this post global
1494 $GLOBALS['post'] = $post;
1495
1496 $in_same_term = false;
1497 $taxonomies = 'category';
1498 $title = '';
1499 $arrows_list = $el['atts']['arrows_list'];
1500
1501 if($el['atts']['in_same_term']){
1502 $in_same_term = true;
1503 $taxonomies = $el['atts']['taxonomies'];
1504 }
1505
1506 if($el['atts']['post_title']){
1507 $title = '<span class="pagelayer-post-nav-title">%title</span>';
1508 }
1509
1510 $next_label = '<span class="pagelayer-next-holder">
1511 <span class="pagelayer-post-nav-link"> '.$el["atts"]["next_label"].'</span>'.$title.'
1512 </span>
1513 <span class="pagelayer-post-nav-icon fa fa-'.$arrows_list.'-right"></span>';
1514
1515 $prev_label = '<span class="pagelayer-post-nav-icon fa fa-'.$arrows_list.'-left"></span>
1516 <span class="pagelayer-next-holder">
1517 <span class="pagelayer-post-nav-link"> '.$el["atts"]["prev_label"].'</span>'.$title.'
1518 </span>';
1519
1520 $el['atts']['next_link'] = get_next_post_link('%link', $next_label, $in_same_term, '', $taxonomies);
1521
1522 $el['atts']['prev_link'] = get_previous_post_link('%link', $prev_label, $in_same_term, '', $taxonomies );
1523
1524 pagelayer_json_output($el);
1525
1526 }
1527
1528 // Get post comment template
1529 add_action('wp_ajax_pagelayer_post_comment', 'pagelayer_post_comment');
1530 function pagelayer_post_comment() {
1531 global $post;
1532
1533 // Some AJAX security
1534 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
1535
1536 if(!isset($_REQUEST['postID'])){
1537 return true;
1538 }
1539
1540 $GLOBALS['post'] = get_post($_REQUEST['postID']);
1541 $GLOBALS['withcomments'] = true;
1542
1543 // Load shortcodes
1544 pagelayer_load_shortcodes();
1545
1546 $el = [];
1547 pagelayer_sc_post_comment($el);
1548
1549 echo $el['atts']['post_comment'];
1550
1551 wp_die();
1552
1553 }
1554
1555 // Get post comment template
1556 add_action('wp_ajax_pagelayer_post_info', 'pagelayer_post_info');
1557 function pagelayer_post_info() {
1558 global $post;
1559
1560 // Some AJAX security
1561 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
1562
1563 if(!isset($_REQUEST['postID']) || !isset($_REQUEST['el'])){
1564 return true;
1565 }
1566
1567 $el['atts'] = $_REQUEST['el'];
1568
1569 $GLOBALS['post'] = get_post($_REQUEST['postID']);
1570
1571 // Load shortcodes
1572 pagelayer_load_shortcodes();
1573
1574 pagelayer_sc_post_info_list($el);
1575
1576 pagelayer_json_output($el['atts']);
1577
1578 }
1579
1580 // Get the Featured Image
1581 add_action('wp_ajax_pagelayer_fetch_featured_img', 'pagelayer_fetch_featured_img');
1582 function pagelayer_fetch_featured_img(){
1583
1584 // Some AJAX security
1585 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
1586
1587 $id = get_post_thumbnail_id( (int) $_POST['post_id'] );
1588 $img = [];
1589
1590 if(empty($id)){
1591 pagelayer_json_output($img);
1592 }
1593
1594 $img = pagelayer_image($id);
1595 pagelayer_json_output($img);
1596
1597 }
1598
1599 // Get the postfolio posts
1600 add_action('wp_ajax_pagelayer_fetch_posts', 'pagelayer_fetch_posts');
1601 function pagelayer_fetch_posts(){
1602
1603 // Some AJAX security
1604 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
1605
1606 // This ajax call is only used during post/page editing
1607 if(!current_user_can('edit_posts')){
1608 echo __pl('no_permission');
1609 wp_die();
1610 }
1611
1612 $sanitized_post = pagelayer_sanitize_posts_data($_POST);
1613 echo pagelayer_widget_posts($sanitized_post);
1614
1615 wp_die();
1616 }
1617
1618 // Get the Posts
1619 add_action('wp_ajax_pagelayer_posts_data', 'pagelayer_posts_data');
1620 function pagelayer_posts_data(){
1621
1622 // Some AJAX security
1623 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
1624
1625 // This ajax call is only used during post/page editing
1626 if(!current_user_can('edit_posts')){
1627 echo __pl('no_permission');
1628 wp_die();
1629 }
1630
1631 // Load shortcodes
1632 pagelayer_load_shortcodes();
1633
1634 $sanitized_post = pagelayer_sanitize_posts_data($_POST, false);
1635 echo pagelayer_posts($sanitized_post);
1636 wp_die();
1637 }
1638
1639 // Get the Posts
1640 add_action('wp_ajax_pagelayer_archive_posts_data', 'pagelayer_archive_posts_data');
1641 function pagelayer_archive_posts_data(){
1642
1643 // Some AJAX security
1644 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
1645
1646 // Set excerpt length
1647 if(!empty($_POST['atts']['exc_length'])){
1648 $exc_length = (int) $_POST['atts']['exc_length'];
1649 add_filter( 'excerpt_length', function($length) use($exc_length){
1650 return $exc_length;
1651 }, 999 );
1652 }
1653
1654 // Load shortcodes
1655 pagelayer_load_shortcodes();
1656
1657 foreach($_POST['atts'] as $k => $v){
1658 $v = pagelayer_maybe_implode($v);
1659 $r[] = esc_html($k).'="'.pagelayer_escapeHTML($v).'"';
1660 }
1661
1662 $string = implode(' ', $r);
1663 if(preg_match('/\]/is', $string)){
1664 die('Hacking Attempt');
1665 }
1666
1667 $sc = '[pl_archive_posts '.$string.'][/pl_archive_posts]';
1668
1669 echo pagelayer_the_content($sc);
1670 wp_die();
1671 }
1672
1673 // Handle Contact Form Data
1674 add_action('wp_ajax_pagelayer_contact_submit', 'pagelayer_contact_submit');
1675 add_action('wp_ajax_nopriv_pagelayer_contact_submit', 'pagelayer_contact_submit' );
1676 function pagelayer_contact_submit(){
1677
1678 // Some AJAX security
1679 check_ajax_referer('pagelayer_global', 'pagelayer_nonce');
1680
1681 // A filter to short circuit this contact form
1682 $continue = apply_filters('pagelayer_contact_submit_start', 1);
1683 if(empty($continue)){
1684 return false;
1685 }
1686
1687 $formdata = wp_unslash($_POST);
1688 // NOTE : NEVER add anything to $formdata except $_POST vars
1689
1690 if(isset($_POST['g-recaptcha-response']) ){
1691
1692 if(!pagelayer_captcha_verify()){
1693 $wp['failed'] = get_option('pagelayer_recaptcha_failed', __pl('cap_ver_fail'));
1694 pagelayer_json_output($wp);
1695 }
1696
1697 unset($formdata['g-recaptcha-response']);
1698 }
1699
1700 // Unset the nonce
1701 unset($formdata['pagelayer_nonce']);
1702
1703 $to_mail = get_option('pagelayer_cf_to_email');
1704 $from_mail = get_option('pagelayer_cf_from_email');
1705 $subject = get_option('pagelayer_cf_subject');
1706 $additional_headers = get_option('pagelayer_cf_headers');
1707 $reply_to = '';
1708 $body = '';
1709 $headers = '';
1710 $custom_templ = array();
1711 $use_custom = false;
1712 $use_html = false;
1713 $pagelayer_id = sanitize_text_field($formdata['cfa-pagelayer-id']);
1714
1715 if(isset($formdata['cfa-custom-template']) && !empty($formdata['cfa-post-id'])){
1716 $post_id = (int) $formdata['cfa-post-id'];
1717
1718 if(!empty($post_id) && ( get_post_status( $post_id ) === 'publish' || current_user_can('publish_posts') )){
1719 $contact_array = get_post_meta($post_id, 'pagelayer_contact_templates', true);
1720
1721 if(!empty($contact_array) && !empty($contact_array[$pagelayer_id])){
1722 $custom_templ = $contact_array[$pagelayer_id];
1723 $use_custom = true;
1724 }
1725 }
1726 }
1727
1728 if($use_custom && !empty($custom_templ)){
1729
1730 if(!empty($custom_templ['to_email'])){
1731 $to_mail = $custom_templ['to_email'];
1732 }
1733
1734 if(!empty($custom_templ['from_email'])){
1735 $from_mail = $custom_templ['from_email'];
1736 }
1737
1738 if(!empty($custom_templ['cont_subject'])){
1739 $subject = $custom_templ['cont_subject'];
1740 }
1741
1742 if(!empty($custom_templ['cont_header'])){
1743 $additional_headers = $custom_templ['cont_header'];
1744 }
1745
1746 if(!empty($custom_templ['cont_body'])){
1747 $body = $custom_templ['cont_body'];
1748 }
1749
1750 if(!empty($custom_templ['cont_use_html'])){
1751 $use_html = true;
1752 $headers .= "Content-Type: text/html\n";
1753 }
1754 }
1755
1756 if(!empty($from_mail)){
1757 $headers .= "From: $from_mail\n";
1758 }
1759
1760 if ( !empty($additional_headers) ) {
1761 $headers .= $additional_headers . "\n";
1762 }
1763
1764 if ( empty($body) ) {
1765
1766 // Make the email content
1767 foreach($formdata as $k => $i){
1768
1769 $not_allow = ['cfa-pagelayer-id', 'cfa-redirect', 'cfa-post-id', 'cfa-custom-template', 'pagelayer-contact-submit'];
1770 if(in_array($k, $not_allow)){
1771 continue;
1772 }
1773
1774 $body .= sanitize_text_field($k)."\t : \t $".$k."\n";
1775
1776 }
1777
1778 $body .= "\n\n --\n This e-mail was sent from a contact form (".get_home_url().")";
1779
1780 }
1781
1782 // Add attachment
1783 if(!empty($_FILES)){
1784 add_action('phpmailer_init', 'pagelayer_cf_email_attachment', 10, 1);
1785 }
1786
1787 $sanitized_data = array();
1788
1789 // If we are using HTML, then we should escape html as well
1790 foreach($formdata as $k => $i){
1791
1792 if(is_array($i)){
1793 $i = pagelayer_flat_join($i);
1794 }
1795
1796 $i = pagelayer_esc_crlf($i);
1797
1798 if(!empty($use_html)){
1799 $i = esc_html($i);
1800 }
1801
1802 // Sanitize text field
1803 $i = sanitize_text_field($i);
1804
1805 // Record a reply to if it is to be used
1806 if(is_email($i) && empty($reply_to)){
1807 $reply_to = $i;
1808 }
1809
1810 $sanitized_data[$k] = $i;
1811 }
1812
1813 // Dow we have a reply to in the headers ?
1814 if(!preg_match('/reply\-to/is', $headers) && !empty($reply_to)){
1815 $headers .= "Reply-To: $reply_to\n";
1816 }
1817
1818 // Add Site Title as option in formdata
1819 $sanitized_data['site_title'] = get_bloginfo( 'name' );
1820
1821 // Do parse a variables
1822 $to_mail = pagelayer_replace_vars($to_mail, $sanitized_data, '$');
1823 $from_mail = pagelayer_replace_vars($from_mail, $sanitized_data, '$');
1824 $subject = pagelayer_replace_vars($subject, $sanitized_data, '$');
1825 $headers = pagelayer_replace_vars($headers, $sanitized_data, '$');
1826 $body = pagelayer_replace_vars($body, $sanitized_data, '$');
1827
1828 if ( $use_html && ! preg_match( '%<html[>\s].*</html>%is', $body ) ) {
1829 $header = '<!doctype html>
1830 <html xmlns="http://www.w3.org/1999/xhtml">
1831 <head><title>' . esc_html( $subject ) . '</title></head>
1832 <body>';
1833
1834 $footer = '</body></html>';
1835
1836 $body = $header . wpautop( $body ) . $footer;
1837 }
1838
1839 $to_mail = apply_filters('pagelayer_contact_send', $to_mail, $sanitized_data);
1840
1841 // Send the email
1842 if(!empty($to_mail)){
1843 $r = wp_mail( $to_mail, $subject, $body, $headers );
1844 }
1845
1846 if($r == TRUE){
1847 $wp['success'] = pagelayer_get_option( 'pagelayer_cf_success' );
1848 }else{
1849 $wp['failed'] = pagelayer_get_option( 'pagelayer_cf_failed' );
1850 }
1851
1852 pagelayer_json_output($wp);
1853
1854 }
1855
1856 // Handle Login Submit
1857 add_action('wp_ajax_pagelayer_login_submit', 'pagelayer_login_submit');
1858 add_action('wp_ajax_nopriv_pagelayer_login_submit', 'pagelayer_login_submit');
1859 function pagelayer_login_submit(){
1860
1861 // Some AJAX security
1862 check_ajax_referer('pagelayer_global', 'pagelayer_nonce');
1863
1864 $creds = array();
1865 $creds['user_login'] = $_REQUEST['username'];
1866 $creds['user_password'] = $_REQUEST['password'];
1867 $creds['remember'] = $_REQUEST['remember_me'];
1868
1869 // Login the user
1870 $user = wp_signon( $creds, false );
1871
1872 if ( is_wp_error($user) ){
1873 $data['error'] = $user->get_error_message();
1874 }else{
1875
1876 // If After logout URL, then save
1877 if(!empty($_REQUEST['logout_url'])){
1878 update_user_option($user->ID, 'pagelayer_logout_url', sanitize_url($_REQUEST['logout_url']));
1879 }
1880
1881 $data['redirect'] = (empty($_REQUEST['login_url']) ? '' : sanitize_url($_REQUEST['login_url']));
1882 $data['error'] = '';
1883 }
1884
1885 pagelayer_json_output($data);
1886
1887 }
1888
1889 // Get Page List for SiteMap
1890 add_action('wp_ajax_pagelayer_get_pages_list', 'pagelayer_get_pages_list');
1891 function pagelayer_get_pages_list(){
1892
1893 // Some AJAX security
1894 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
1895
1896 if(!current_user_can('edit_posts')){
1897 echo __pl('no_permission');
1898 wp_die();
1899 }
1900
1901 $args = array(
1902 'post_type' => sanitize_text_field($_POST['type']),
1903 'orderby' => sanitize_text_field($_POST['post_order']),
1904 'order' => sanitize_text_field($_POST['order']),
1905 'hierarchical' => (empty($_POST['hier']) || $_POST['hier'] == null ? '' : sanitize_text_field($_POST['hier'])),
1906 'number' => (empty($_POST['depth']) || $_POST['depth'] == null ? '' : sanitize_text_field($_POST['depth'])),
1907 'posts_per_page' => -1,
1908 );
1909
1910 $option = '<ul>';
1911 $pages = new WP_Query($args);
1912 $posts = $pages->posts;
1913 foreach ( $posts as $page ) {
1914 $option .= '<li class="pagelayer-sitemap-list-item" data-postID="'.$page->ID.'"><a class="pagelayer-ele-link" href="'.$page->guid.'">'.$page->post_name.'</a></li>';
1915 }
1916 $option .= '</ul>';
1917
1918 echo $option;
1919
1920 wp_die();
1921 }
1922
1923 // Get the data for template
1924 add_action('wp_ajax_pagelayer_search_ids', 'pagelayer_search_ids');
1925 function pagelayer_search_ids() {
1926
1927 // Some AJAX security
1928 check_ajax_referer('pagelayer_builder', 'pagelayer_nonce');
1929
1930 if ( empty( $_POST['filter_type'] ) || empty( $_POST['search'] ) ) {
1931 wp_die();
1932 }
1933
1934 $sel_opt = '';
1935
1936 switch ( $_POST['filter_type'] ) {
1937 case 'taxonomy':
1938 $query_params = [
1939 'taxonomy' => $_POST['object_type'],
1940 'search' => $_POST['search'],
1941 'hide_empty' => false,
1942 ];
1943
1944 $terms = get_terms( $query_params );
1945
1946 global $wp_taxonomies;
1947
1948 foreach ( $terms as $term ) {
1949 $sel_opt .= '<span class="pagelayer-temp-search-sel-span" value="'. $term->term_taxonomy_id .'">'. $term->name .'</span>';
1950 }
1951
1952 break;
1953
1954 case 'post':
1955 $query_params = [
1956 'post_type' => $_POST['object_type'], //$this->extract_post_type( $data ),
1957 's' => $_POST['search'],
1958 'posts_per_page' => -1,
1959 ];
1960
1961 if ( 'attachment' === $query_params['post_type'] ) {
1962 $query_params['post_status'] = 'inherit';
1963 }
1964
1965 $query = new \WP_Query( $query_params );
1966
1967 foreach ( $query->posts as $post ) {
1968 $sel_opt .= '<span class="pagelayer-temp-search-sel-span" value="'. $post->ID .'">'. $post->post_title .'</span>';
1969 }
1970 break;
1971
1972 case 'author':
1973 $query_params = [
1974 'capability' => array( 'edit_posts' ),
1975 'fields' => [
1976 'ID',
1977 'display_name',
1978 ],
1979 'search' => '*' . $_POST["search"] . '*',
1980 'search_columns' => [
1981 'user_login',
1982 'user_nicename',
1983 ],
1984 ];
1985
1986 // Capability queries were only introduced in WP 5.9.
1987 if( version_compare( $GLOBALS['wp_version'], '5.9-alpha', '<' ) ){
1988 $args['who'] = 'authors';
1989 unset( $args['capability'] );
1990 }
1991
1992 $user_query = new \WP_User_Query( $query_params );
1993
1994 foreach ( $user_query->get_results() as $author ) {
1995 $sel_opt .= '<span class="pagelayer-temp-search-sel-span" value="'. $author->ID .'">'. $author->display_name .'</span>';
1996 }
1997 break;
1998
1999 /* case 'menu':
2000
2001 $menuItems = wp_get_nav_menu_items( (int)$_POST['object_type']);
2002
2003 foreach ( $menuItems as $item ) {
2004
2005 if($item -> menu_item_parent !=0 ){
2006 continue;
2007 }
2008 $sel_opt .= '<span class="pagelayer-temp-search-sel-span" value="'. $item -> ID .'">'. $item -> title.'</span>';
2009 }
2010
2011 break; */
2012
2013 default:
2014 $sel_opt = 'Result Not Found';
2015 }
2016
2017 if(!empty($sel_opt)){
2018 echo $sel_opt;
2019 }else{
2020 echo 'Result Not Found';
2021 }
2022
2023 wp_die();
2024 }
2025
2026 // Save the post data from pagelayer setting page
2027 add_action('wp_ajax_pagelayer_save_template', 'pagelayer_save_template');
2028 function pagelayer_save_template() {
2029
2030 // Some AJAX security
2031 check_ajax_referer('pagelayer_builder', 'pagelayer_nonce');
2032
2033 $done = [];
2034
2035 $post_id = (int) $_GET['postID'];
2036
2037 // Are you allowed to edit ?
2038 if(!empty($post_id) && !pagelayer_user_can_edit($post_id)){
2039 $done['error'][] = __pl('no_permission');
2040 pagelayer_json_output($done);
2041 }
2042
2043 // We need to create the post
2044 if(empty($post_id)){
2045
2046 if (!current_user_can('edit_posts')) {
2047 $done['error'] = __pl('access_denied');
2048 pagelayer_json_output($done);
2049 }
2050
2051 // Get the template type
2052 if(empty($_POST['pagelayer_template_type'])){
2053 $done['error'] = __pl('temp_error_type');
2054 pagelayer_json_output($done);
2055 }
2056
2057 $ret = wp_insert_post([
2058 'post_title' => $_POST['pagelayer_lib_title'],
2059 'post_type' => 'pagelayer-template',
2060 'post_status' => 'publish',
2061 'comment_status' => 'closed',
2062 'ping_status' => 'closed'
2063 ]);
2064
2065 // An error occured
2066 if(is_wp_error($ret)){
2067 $done['error'] = __pl('temp_error').' : '.$ret->get_error_message();
2068 pagelayer_json_output($done);
2069 }
2070
2071 $post_id = $ret;
2072 $done['id'] = $post_id;
2073
2074 // Save our template type
2075 $ret = update_post_meta($post_id, 'pagelayer_template_type', $_POST['pagelayer_template_type']);
2076
2077 }
2078
2079 // The ID in consideration
2080 $done['id'] = $post_id;
2081
2082 // Check if the post title in not empty
2083 if(!empty($_POST['pagelayer_lib_title'])){
2084
2085 $post = array(
2086 'ID' => $post_id,
2087 'post_title' => $_POST['pagelayer_lib_title'],
2088 );
2089
2090 // Update the post into the database
2091 $ret = wp_update_post($post);
2092
2093 }
2094
2095 // Save template library display conditions
2096 $condi_array = array();
2097 $condi_len = count($_POST['pagelayer_condition_type']);
2098 if($_POST['pagelayer_template_type'] != 'section'){
2099 for( $i =0; $i < $condi_len; $i++ ){
2100 $condi_array[$i] = array(
2101 'type' => $_POST['pagelayer_condition_type'][$i],
2102 'template' => $_POST['pagelayer_condition_name'][$i],
2103 'sub_template' => $_POST['pagelayer_condition_sub_template'][$i],
2104 'id' => $_POST['pagelayer_condition_id'][$i],
2105 );
2106 }
2107 }
2108 //print_r($condi_array);
2109
2110 $ret = update_post_meta($post_id, 'pagelayer_template_conditions', $condi_array);
2111
2112 if(is_wp_error($post_id)){
2113 $done['error'] = __pl('temp_error').' : '.$ret->get_error_message();
2114 }else{
2115 $done['success'] = __pl('temp_update_success');
2116 }
2117
2118 pagelayer_json_output($done);
2119
2120 }
2121
2122 // Products Categories Handler
2123 add_action('wp_ajax_pagelayer_product_categories', 'pagelayer_product_categories');
2124 function pagelayer_product_categories(){
2125
2126 // Some AJAX security
2127 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
2128
2129 $attributes = '';
2130 $attributes .= ' number="'. $_POST['atts']['number'] .'" ';
2131 $attributes .= ' columns="'. $_POST['atts']['columns'] .'" ';
2132 $attributes .= ' hide_empty="'. (!empty($_POST['atts']['hide_empty']) ? 1 : 0) .'" ';
2133 $attributes .= ' orderby="'. $_POST['atts']['nuorderbymber'] .'" ';
2134 $attributes .= ' order="'. $_POST['atts']['order'] .'" ';
2135
2136 if ( 'by_id' === $_POST['atts']['source'] ) {
2137 $attributes .= ' ids="'. $_POST['atts']['by_id'] .'" ';
2138 } elseif ( 'by_parent' === $_POST['atts']['source'] ) {
2139 $attributes .= ' parent="'. $_POST['atts']['parent'] .'" ';
2140 } elseif ( 'current_subcategories' === $_POST['atts']['source'] ) {
2141 $attributes .= ' parent="'. get_queried_object_id() .'" ';
2142 }
2143
2144 $shortcode = '[product_categories '. $attributes .']';
2145
2146 // do_shortcode the shortcode
2147 echo pagelayer_the_content($shortcode);
2148
2149 wp_die();
2150 }
2151
2152 // Products Categories Handler
2153 add_action('wp_ajax_pagelayer_products_ajax', 'pagelayer_products_ajax');
2154 function pagelayer_products_ajax(){
2155
2156 // Some AJAX security
2157 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
2158
2159 if ( WC()->session ) {
2160 wc_print_notices();
2161 }
2162
2163 $no_found = $_POST['atts']['no_found'];
2164
2165 $attributes = '';
2166 $type = $_POST['atts']['source'];
2167 $attributes .= ' columns="'. $_POST['atts']['columns'] .'" ';
2168 $attributes .= ' rows="'. $_POST['atts']['rows'] .'" ';
2169 $attributes .= ' paginate="'. (!empty($_POST['atts']['paginate']) ? true : false) .'" ';
2170 $attributes .= ' orderby="'. $_POST['atts']['orderby'] .'" ';
2171 $attributes .= ' order="'. $_POST['atts']['order'] .'" ';
2172 $attributes .= ' cache="false" ';
2173
2174 // Hide the catalog order
2175 if( empty($_POST['atts']['allow_order']) ){
2176 remove_action( 'woocommerce_before_shop_loop', 'woocommerce_catalog_ordering', 30 );
2177 }
2178
2179 // Hide the result count
2180 if( empty($_POST['atts']['show_result']) ){
2181 remove_action( 'woocommerce_before_shop_loop', 'woocommerce_result_count', 20 );
2182 }
2183
2184 if( $type == 'by_id' ){
2185 $type = 'products';
2186 $attributes .= ' ids="'. (!empty($_POST['atts']['ids']) ? $_POST['atts']['ids'] : '') .'" ';
2187 }elseif( $type == 'pagelayer_current_query' ){
2188
2189 $atts['paginate'] = (!empty($_POST['atts']['paginate']) ? true : false);
2190 $atts['cache'] = false;
2191
2192 $type = 'pagelayer_current_query';
2193
2194 // Set the current query
2195 add_action( 'woocommerce_shortcode_products_query', 'pagelayer_shortcode_current_query', 10, 10);
2196
2197 // If product not found
2198 add_action( "woocommerce_shortcode_{$type}_loop_no_results", function ($attributes) use ($no_found){
2199 echo '<div class="pagelayer-product-no-found">'.$no_found.'</div>';
2200 } );
2201
2202 // Get the products list
2203 $shortcode = new WC_Shortcode_Products( $atts, $type );
2204
2205 echo $shortcode->get_content();
2206 return true;
2207 }
2208
2209 $shortcode = '['.$type.' '. $attributes .']';
2210
2211 $content = pagelayer_the_content($shortcode);
2212
2213 // If product not found
2214 if('<div class="woocommerce columns-'.$_POST['atts']['columns'] .' "></div>' == $content){
2215 $content = '<div class="pagelayer-product-no-found">'. $no_found .'</div>';
2216 }
2217
2218 echo $content;
2219
2220 wp_die();
2221 }
2222
2223 // Markdown Handler
2224 add_action('wp_ajax_pagelayer_handle_markdown', 'pagelayer_handle_markdown');
2225 function pagelayer_handle_markdown(){
2226
2227 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
2228
2229 if(!defined('PAGELAYER_PRO_VERSION')){
2230 wp_send_json_error(['message' => __('Markdown feature requires Pagelayer Pro.', 'pagelayer')]);
2231 return;
2232 }
2233
2234 include_once(PAGELAYER_PRO_DIR.'/main/premium_functions.php');
2235
2236 $raw_atts = isset($_POST['data']) && is_array($_POST['data']) ? wp_unslash($_POST['data']) : [];
2237 $atts = [];
2238
2239 foreach($raw_atts as $key => $value){
2240 $clean_key = sanitize_key($key);
2241
2242 // Check for invalid UTF-8 to prevent database errors
2243 if(in_array($clean_key, ['markdown_text_file', 'markdown_text_url', 'active_markdown_text'])){
2244 $atts[$clean_key] = wp_check_invalid_utf8($value);
2245 } else{
2246 $atts[$clean_key] = sanitize_text_field($value);
2247 }
2248 }
2249
2250 $fetched = pagelayer_get_markdown_content($atts);
2251 $current_text = $fetched['text'];
2252 $default_text = __pl('Select a Markdown file or enter a URL to load content.');
2253
2254 // Compile HTML
2255 $html = '';
2256 if(!empty($fetched['is_error'])){
2257 $html = '<div class="pagelayer-markdown-error">' . esc_html($current_text) . '</div>';
2258 } else if($current_text === $default_text){
2259 $html = '<div class="pagelayer-markdown-placeholder">' . $default_text . '</div>';
2260 } else if(function_exists('pagelayer_markdown_to_html')){
2261 $html = pagelayer_markdown_to_html($current_text);
2262 }
2263
2264 $wp['html'] = wp_kses_post($html);
2265 $wp['raw_text'] = $current_text;
2266 $wp['is_error'] = !empty($fetched['is_error']);
2267
2268 pagelayer_json_output($wp);
2269
2270 wp_die();
2271 }
2272
2273 // Get Taxamony List for SiteMap
2274 add_action('wp_ajax_pagelayer_get_taxonomy_list', 'pagelayer_get_taxonomy_list');
2275 function pagelayer_get_taxonomy_list(){
2276
2277 // Some AJAX security
2278 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
2279
2280 if(!current_user_can('edit_posts')){
2281 echo __pl('no_permission');
2282 wp_die();
2283 }
2284
2285 $args = array(
2286 'title_li' => 0,
2287 'orderby' => $_POST['post_order'],
2288 'order' => $_POST['order'],
2289 'style' => '',
2290 'hide_empty' => $_POST['empty'],
2291 'echo' => false,
2292 'hierarchical' => (empty($_POST['hier']) || $_POST['hier'] == null ? '' : $_POST['hier']),
2293 'taxonomy' => $_POST['type'],
2294 'depth' => (empty($_POST['depth']) || $_POST['depth'] == null ? '' : $_POST['depth']),
2295 );
2296
2297 $taxonomies = get_categories( $args );
2298
2299 $option = '<ul>';
2300 foreach ( $taxonomies as $taxonomy ) {
2301 $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>';
2302 }
2303 $option .= '</ul>';
2304
2305 echo $option;
2306 wp_die();
2307 }
2308
2309 // Export the template
2310 add_action('wp_ajax_pagelayer_export_template', 'pagelayer_export_template');
2311 function pagelayer_export_template(){
2312
2313 global $pagelayer;
2314
2315 // Some AJAX security
2316 check_ajax_referer('pagelayer_builder', 'pagelayer_nonce');
2317
2318 $done = [];
2319
2320 if(!current_user_can('edit_theme_options')){
2321 $done['error'][] = __pl('no_permission');
2322 pagelayer_json_output($done);
2323 }
2324
2325 // Load the templates
2326 pagelayer_builder_load_templates();
2327
2328 if(empty($pagelayer->templates)){
2329 $done['error'] = __pl('temp_export_empty');
2330 pagelayer_json_output($done);
2331 }
2332
2333 // Load Shortcodes
2334 pagelayer_load_shortcodes();
2335
2336 // Get the active theme
2337 $theme_dir = get_stylesheet_directory();
2338 $conf = [];
2339
2340 $pagelayer->export_mode = 1;
2341
2342 // Write the files
2343 foreach($pagelayer->templates as $k => $v){
2344
2345 // Are there specific templates to export
2346 if(!empty($_POST['templates'])){
2347 if(!isset($_POST['templates'][$v->ID])){
2348 continue;
2349 }
2350 }
2351
2352 // Only blocks allowed
2353 if(!has_blocks($v->post_content) && !empty($v->post_content)){
2354 $done['error'] = 'The pagelayer template '.$v->ID.' has Shortcodes which is not allowed for export !';
2355 pagelayer_json_output($done);
2356 }
2357
2358 $v->post_name = (empty($v->post_name) && $v->post_status == 'draft') ? sanitize_title($v->post_title).'-draft' : $v->post_name;
2359
2360 // Write the content
2361 file_put_contents($theme_dir.'/'.$v->post_name.'.pgl', pagelayer_export_content($v->post_content));
2362 $conf[$v->post_name] = [
2363 'type' => get_post_meta($v->ID, 'pagelayer_template_type', true),
2364 'title' => $v->post_title,
2365 'conditions' => get_post_meta($v->ID, 'pagelayer_template_conditions', true),
2366 ];
2367 }
2368
2369 // Write the config
2370 file_put_contents($theme_dir.'/pagelayer.conf', json_encode($conf, JSON_PRETTY_PRINT));
2371
2372 $conf = [];
2373
2374 // Load the other posts
2375 foreach($pagelayer->settings['post_types'] as $type){
2376
2377 // Anything to export for users ?
2378 if(!empty($_POST[$type]) && is_array($_POST[$type])){
2379
2380 mkdir($theme_dir.'/data/');
2381 mkdir($theme_dir.'/data/'.$type);
2382
2383 $pids = [];
2384
2385 foreach($_POST[$type] as $k => $v){
2386 $pids[] = (int) $k;
2387 }
2388
2389 // Load the type
2390 $_query = new WP_Query([
2391 'post_type' => $type,
2392 'status' => 'publish',
2393 'post__in' => $pids,
2394 'posts_per_page' => -1,
2395 ]);
2396
2397 $posts = $_query->posts;
2398
2399 // Write the files
2400 foreach($posts as $k => $v){
2401
2402 // Only blocks allowed
2403 if(!has_blocks($v->post_content) && !empty($v->post_content)){
2404 $done['error'] = 'The '.$type.' '.$v->ID.' has Shortcodes which is not allowed for export !';
2405 pagelayer_json_output($done);
2406 }
2407
2408 $v->post_name = (empty($v->post_name) && $v->post_status == 'draft') ? sanitize_title($v->post_title).'-draft' : $v->post_name;
2409
2410 file_put_contents($theme_dir.'/data/'.$type.'/'.$v->post_name, pagelayer_export_content($v->post_content));
2411 unset($v->post_content);
2412
2413 $meta = get_post_meta($v->ID);
2414 $meta = array_combine(array_keys($meta), array_column($meta, 0));
2415
2416 // Export media
2417 if(!empty($meta['_thumbnail_id'])){
2418
2419 $file = pagelayer_export_media_files($meta['_thumbnail_id'], $exp_img_url);
2420
2421 // Did it export ?
2422 if(!empty($file)){
2423 $meta['_thumbnail_id'] = $exp_img_url;
2424 }
2425
2426 }
2427
2428 // Also put the meta
2429 file_put_contents($theme_dir.'/data/'.$type.'/'.$v->post_name.'.meta', json_encode($meta, JSON_PRETTY_PRINT));
2430
2431 //Export taxonomies in post
2432 $taxonomies = get_object_taxonomies( $v->post_type, 'objects' );
2433 $post_taxonomies = wp_filter_object_list( $taxonomies, [
2434 'public' => true,
2435 'show_in_nav_menus' => true,
2436 ] );
2437
2438 foreach( $post_taxonomies as $slug => $object ){
2439
2440 if(empty($v->taxonomies) || !is_array($v->taxonomies)){
2441 $v->taxonomies = array();
2442 }
2443
2444 $tax_name = $object->name;
2445 $the_terms = get_the_terms($v->ID, $tax_name);
2446 $v->taxonomies[$tax_name] = '';
2447
2448 if(!empty($the_terms)){
2449 $v->taxonomies[$tax_name] = implode(',', array_column($the_terms, 'term_id'));
2450 }
2451 }
2452
2453 $conf[$type][$v->post_name] = $v;
2454
2455 do_action('pagelayer_'.$type.'_exported', $v, $theme_dir);
2456
2457 }
2458
2459 ksort($conf[$type]);
2460
2461 }
2462
2463 }
2464
2465 // Export menus
2466 if(!empty($pagelayer->export_menus) && is_array($pagelayer->export_menus)){
2467
2468 mkdir($theme_dir.'/data/menus');
2469
2470 foreach($pagelayer->export_menus as $k => $v){
2471
2472 $menu = (int) $k;
2473 $menu = wp_get_nav_menu_object( $menu );
2474
2475 if(empty($menu)){
2476 $done['error'] = 'Could not export menu ID - '.$k;
2477 continue;
2478 }
2479
2480 // Menu Items
2481 $menu_items = wp_get_nav_menu_items( $menu->term_id );
2482 $data = [];
2483
2484 if(is_array($menu_items) && !empty($menu_items)){
2485 foreach($menu_items as $kk => $singlenav){
2486 //$navmetas = get_post_meta($singlenav->ID);
2487 //$navmetas = array_combine(array_keys($navmetas), array_column($navmetas, 0));
2488 $data[$kk]['post'] = $singlenav;
2489 $navmetas = array();
2490
2491 $pl_content = get_post_meta($singlenav->ID, '_pagelayer_content', true);
2492 if(!empty($pl_content)){
2493 $navmetas['_pagelayer_content'] = pagelayer_export_content($pl_content);
2494 }
2495
2496 $data[$kk]['post_metas'] = $navmetas;
2497 }
2498 }
2499
2500 // Also put the meta
2501 file_put_contents($theme_dir.'/data/menus/'.$menu->slug, json_encode($data, JSON_PRETTY_PRINT));
2502
2503 $conf['menus'][$menu->slug] = $menu;
2504
2505 do_action('pagelayer_menus_exported', $v, $theme_dir);
2506
2507 }
2508
2509 }
2510
2511 // Export the settings
2512 $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'];
2513
2514 foreach($settings as $v){
2515
2516 $vv = get_option($v);
2517
2518 if($vv){
2519 $conf['conf'][$v] = $vv;
2520 }
2521
2522 }
2523
2524 // Load CSS settings
2525 foreach($pagelayer->css_settings as $k => $params){
2526 foreach($pagelayer->screens as $sk => $sv){
2527 $suffix = (!empty($sv) ? '_'.$sv : '');
2528 $setting = empty($params['key']) ? 'pagelayer_'.$k.'_css' : $params['key'];
2529 $tmp = get_option($setting.$suffix);
2530 if(!empty($tmp)){
2531 $conf['conf'][$setting.$suffix] = $tmp;
2532 }
2533 }
2534 }
2535
2536 // Export all the taxonomies
2537 $post_types = pagelayer_get_public_post_types();
2538
2539 // Export all the Post Type CSS Settings
2540 foreach ( $post_types as $pt_slug => $type ) {
2541
2542 if ( $pt_slug == 'attachment' ) {
2543 continue;
2544 }
2545
2546 foreach($pagelayer->css_settings as $k => $params){
2547 foreach($pagelayer->screens as $sk => $sv){
2548 $suffix = (!empty($sv) ? '_'.$sv : '');
2549 $setting = empty($params['key']) ? 'pagelayer_'.$k.'_css_'.$pt_slug : $params['key'].'_'.$pt_slug;
2550 $tmp = get_option($setting.$suffix);
2551
2552 if(!empty($tmp)){
2553 $conf['conf'][$setting.$suffix] = $tmp;
2554 }
2555 }
2556 }
2557 }
2558
2559 // Export all the taxonomies
2560 foreach ( $post_types as $post_type => $label ) {
2561 $type_taxonomies = get_object_taxonomies( $post_type, 'objects' );
2562 $taxonomies = wp_filter_object_list( $type_taxonomies, [
2563 'public' => true,
2564 'show_in_nav_menus' => true,
2565 ] );
2566
2567 foreach( $taxonomies as $slug => $object ){
2568
2569 $query_params = [
2570 'taxonomy' => $object->name,
2571 'hide_empty' => false,
2572 ];
2573 $terms = get_terms( $query_params );
2574
2575 foreach($terms as $term){
2576 $conf['taxonomies'][$term->term_id] = $term;
2577 }
2578 }
2579
2580 }
2581
2582 // Write the config
2583 if(!empty($conf)){
2584 file_put_contents($theme_dir.'/pagelayer-data.conf', json_encode($conf, JSON_PRETTY_PRINT));
2585 }
2586
2587 // Are we to export any media ?
2588 if(!empty($pagelayer->media_to_export)){
2589 // TODO
2590 //$done['media'] = $pagelayer->media_to_export;
2591 }
2592
2593 do_action('pagelayer_template_export_completed');
2594
2595 $done['success'] = __pl('temp_export_success');
2596
2597 // Output and die
2598 pagelayer_json_output($done);
2599
2600 }
2601
2602 add_action('wp_ajax_pagelayer_get_cat_checkboxes', 'pagelayer_get_cat_checkboxes');
2603 function pagelayer_get_cat_checkboxes(){
2604
2605 // Some AJAX security
2606 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
2607
2608 $ret = [];
2609 $cat_name = '';
2610
2611 if(!current_user_can('manage_categories')){
2612 $ret['error'] = __pl('no_permission');
2613 pagelayer_json_output($ret);
2614 }
2615
2616 if(empty($_POST['postid']) || !is_numeric($_POST['postid'])){
2617 $ret['error'] = __pl('invalid_post_id');
2618 pagelayer_json_output($ret);
2619 }
2620
2621 $post = (int) $_POST['postid'];
2622 $post = get_post($post);
2623
2624 if(empty($post) || is_wp_error($post)){
2625 $ret['error'] = __pl('invalid_post_id');
2626 pagelayer_json_output($ret);
2627 }
2628
2629 $cat_name = pagelayer_post_type_category($post->post_type);
2630
2631 if(!empty($_POST['new_cat'])){
2632 parse_str($_POST['new_cat'], $formdata);
2633 $ret['new_cat_id'] = wp_insert_category([
2634 'taxonomy' => $cat_name,
2635 'cat_name' => $formdata['category_name'],
2636 'category_parent' => (($formdata['pagelayer_cat_parent'] == 0) ? '' : $formdata['pagelayer_cat_parent'])
2637 ]);
2638 }
2639
2640 $ret += pagelayer_post_cats($post);
2641
2642 pagelayer_json_output($ret);
2643
2644 }
2645
2646 add_action('wp_ajax_pagelayer_get_post_tags', 'pagelayer_get_post_tags');
2647 function pagelayer_get_post_tags(){
2648
2649 // Some AJAX security
2650 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
2651
2652 $ret = [];
2653 $tag_name = '';
2654
2655 if(!current_user_can('manage_categories')){
2656 $ret['error'] = __pl('no_permission');
2657 pagelayer_json_output($ret);
2658 }
2659
2660 if(empty($_POST['postid']) || !is_numeric($_POST['postid']) ){
2661 pagelayer_json_output($ret);
2662 }
2663
2664 $post = (int) $_POST['postid'];
2665 $post = get_post($post);
2666
2667 if(empty($post) || is_wp_error($post)){
2668 $ret['error'] = __pl('invalid_post_id');
2669 pagelayer_json_output($ret);
2670 }
2671
2672 $tag_name = pagelayer_post_type_tag($post->post_type);
2673
2674 if(!empty($_POST['new_tag'])){
2675 $ret['tag_id'] = wp_insert_term($_POST['new_tag'], $tag_name);
2676 $ret['tag_id'] = $ret['tag_id']['term_id'];
2677 }
2678
2679 $ret += pagelayer_post_tags($post);
2680
2681 pagelayer_json_output($ret);
2682
2683 }
2684
2685 add_action('wp_ajax_pagelayer_custom_font', 'pagelayer_custom_font');
2686 function pagelayer_custom_font(){
2687
2688 // Some AJAX security
2689 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
2690
2691 $ret = [];
2692
2693 if(empty($_POST['font_name'])){
2694 pagelayer_json_output($ret);
2695 }
2696
2697 $name = preg_replace('/_plf$/is', '', pagelayer_optREQ('font_name'));
2698 //echo $name;
2699
2700 $args = [
2701 'post_type' => PAGELAYER_FONT_POST_TYPE,
2702 'status' => 'publish',
2703 'posts_per_page' => 1,
2704 'name' => $name
2705 ];
2706
2707 //var_dump($pagelayer->fonts);
2708
2709 $query = get_posts($args);
2710 //var_dump($query);
2711
2712 if(empty($query)){
2713 pagelayer_json_output($ret);
2714 }
2715
2716 $post = $query[0];
2717 $meta_box_value = get_post_meta( $post->ID, 'pagelayer_font_link', true);
2718 if(empty($meta_box_value)){
2719 pagelayer_json_output($ret);
2720 }
2721
2722 $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>';
2723
2724 pagelayer_json_output($ret);
2725
2726 }
2727
2728 add_action('wp_ajax_pagelayer_trash_post', 'pagelayer_trash_post');
2729 function pagelayer_trash_post(){
2730
2731 // Some AJAX security
2732 check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
2733
2734 $ret = [];
2735
2736 if(empty($_POST['postid']) && !is_numeric($_POST['postid'])){
2737 $ret = ['error' => __pl('invalid_post_id')];
2738 pagelayer_json_output($ret);
2739 }
2740
2741 if(!current_user_can( 'delete_post', $_POST['postid'] )){
2742 $ret = ['error' => __pl('no_permission')];
2743 pagelayer_json_output($ret);
2744 }
2745
2746 $ret['url'] = admin_url('/edit.php?post_type=') .get_post_type($_POST['postid']);
2747
2748 wp_trash_post($_POST['postid']);
2749
2750 pagelayer_json_output($ret);
2751
2752 }
2753
2754 add_action('wp_ajax_pagelayer_infinite_posts', 'pagelayer_infinite_posts');
2755 add_action('wp_ajax_nopriv_pagelayer_infinite_posts', 'pagelayer_infinite_posts');
2756 function pagelayer_infinite_posts(){
2757
2758 // Some AJAX security
2759 check_ajax_referer('pagelayer_global', 'pagelayer_nonce');
2760
2761 pagelayer_load_shortcodes();
2762
2763 $tag = 'pl_posts';
2764
2765 if(isset($_REQUEST['data']['tag']) && $_REQUEST['data']['tag'] == 'pl_archive_posts' ){
2766 $tag = 'pl_archive_posts';
2767 }
2768
2769 $content = get_comment_delimited_block_content( 'pagelayer/'.$tag, $_REQUEST['data']['atts'] , '');
2770 $wp['posts'] = pagelayer_the_content($content);
2771 pagelayer_json_output( $wp );
2772 }
2773
2774 add_action('wp_ajax_pagelayer_pro_dismiss_expired_licenses', 'pagelayer_pro_dismiss_expired_licenses');
2775 function pagelayer_pro_dismiss_expired_licenses(){
2776 check_admin_referer('pagelayer_expiry_notice', 'security');
2777
2778 if(!current_user_can('activate_plugins')){
2779 wp_send_json_error(__('You do not have required access to do this action', 'pagelayer'));
2780 }
2781
2782 update_option('softaculous_expired_licenses', time());
2783 wp_send_json_success();
2784 }
2785
2786 add_action('wp_ajax_pagelayer_close_update_notice', 'pagelayer_close_plugin_update_notice');
2787 function pagelayer_close_plugin_update_notice(){
2788 check_ajax_referer('pagelayer_promo_nonce', 'pagelayer_nonce');
2789
2790 if(!current_user_can('manage_options')){
2791 wp_send_json_error('You don\'t have privilege to close this notice!');
2792 }
2793
2794 $plugin_update_notice = get_option('softaculous_plugin_update_notice', []);
2795 $available_update_list = get_site_transient('update_plugins');
2796 $to_update_plugins = apply_filters('softaculous_plugin_update_notice', []);
2797
2798 if(empty($available_update_list) || empty($available_update_list->response)){
2799 return;
2800 }
2801
2802 foreach($to_update_plugins as $plugin_path => $plugin_name){
2803 if(isset($available_update_list->response[$plugin_path])){
2804 $plugin_update_notice[$plugin_path] = $available_update_list->response[$plugin_path]->new_version;
2805 }
2806 }
2807
2808 update_option('softaculous_plugin_update_notice', $plugin_update_notice);
2809 }