PluginProbe
Page Builder: Pagelayer – Drag and Drop website builder / 2.2.0
Page Builder: Pagelayer – Drag and Drop website builder v2.2.0
2.2.1 2.2.0 2.1.9 2.1.8 2.1.7 2.1.6 2.1.5 2.1.4 2.1.3 trunk 0.9.0 0.9.1 0.9.2 0.9.3 0.9.4 0.9.5 0.9.6 0.9.7 0.9.8 0.9.9 1.0.0 1.0.2 1.0.3 1.0.4 1.0.5 All 129 releases
← All changes | main/ajax.php +2494 -132 0.9.62.2.0 View file →
@@ -23,9 +23,446 @@
23 23 if(!defined('PAGELAYER_VERSION')) {
24 24 exit('Hacking Attempt !');
25 25 }
26 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');
27 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 +
28 465 // The ajax handler
29 466 add_action('wp_ajax_pagelayer_wp_widget', 'pagelayer_wp_widget_ajax');
30 467 function pagelayer_wp_widget_ajax(){
31 468
@@ -31,10 +468,15 @@
31 468
32 469 global $pagelayer;
33 470
34 471 // Some AJAX security
35 - check_ajax_referer('pagelayer_ajax', 'nonce');
472 + check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
36 473
474 + if(!current_user_can('edit_theme_options')){
475 + $ret['error'][] = __pl('no_permission');
476 + pagelayer_json_output($ret);
477 + }
478 +
37 479 pagelayer_load_shortcodes();
38 480
39 481 header('Content-Type: application/json');
40 482
@@ -44,14 +486,15 @@
44 486
45 487 // No tag ?
46 488 if(empty($pagelayer->shortcodes[$tag])){
47 489 $ret['error'][] = __pl('no_tag');
48 - echo json_encode($ret);
49 - wp_die();
490 + pagelayer_json_output($ret);
50 491 }
51 492
52 493 // Include the widgets
53 - include_once(ABSPATH . 'wp-admin/includes/widgets.php');
494 + $widgets = ABSPATH . 'site-admin/includes/widgets.php';
495 + $widgets = file_exists($widgets) ? $widgets : ABSPATH . 'wp-admin/includes/widgets.php';
496 + require_once($widgets);
54 497
55 498 $class = $pagelayer->shortcodes[$tag]['widget'];
56 499
57 500 // Check the widget class exists ?
@@ -56,10 +499,9 @@
56 499
57 500 // Check the widget class exists ?
58 501 if(empty($class) || !class_exists($class)){
59 502 $ret['error'][] = __pl('no_widget_class');
60 - echo json_encode($ret);
61 - wp_die();
503 + pagelayer_json_output($ret);
62 504 }
63 505
64 506 $instance = [];
65 507 $widget = new $class();
@@ -80,8 +522,15 @@
80 522 //pagelayer_print($data);die();
81 523
82 524 // Any data ?
83 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 + }
84 533
85 534 // First key is useless
86 535 $data = current($data);
87 536
@@ -94,8 +543,14 @@
94 543 }
95 544 }
96 545 }
97 546
547 + // Settings instance For Text widget
548 + if($widget->id_base == 'text'){
549 + $instance['visual'] = false;
550 + $instance['legacy'] = false;
551 + }
552 +
98 553 // Get the form
99 554 ob_start();
100 555 $widget->form($instance);
101 556 $ret['form'] = ob_get_contents();
@@ -111,78 +566,735 @@
111 566 if(!empty($instance)){
112 567 $ret['widget_data'] = $instance;
113 568 }
114 569
115 - echo json_encode($ret);
116 - wp_die();
570 + // Custom html widget form elements
571 + if(!empty($widget) && $widget->name=='Custom HTML'){
572 + $custom_html = explode('>', $ret['form']);
117 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 +
118 585 }
119 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 +
120 669 // Update Post content
121 670 add_action('wp_ajax_pagelayer_save_content', 'pagelayer_save_content');
122 671 function pagelayer_save_content(){
123 672
124 673 // Some AJAX security
125 - check_ajax_referer('pagelayer_ajax', 'nonce');
674 + check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
126 675
127 676 $content = $_POST['pagelayer_update_content'];
128 677
129 678 $postID = (int) $_GET['postID'];
130 -
679 +
131 680 if(empty($postID)){
132 - $msg['error'] = __pl('invalid_post_id');
681 + $msg['error'] = __pl('invalid_post_id');
682 + pagelayer_json_output($msg);
133 683 }
134 684
135 - // Check if the post exists
685 + $_post = get_post($postID);
136 686
137 - if(!empty($postID) && !empty($content)){
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)){
138 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 +
139 728 $post = array(
140 - 'ID' => $postID,
141 - 'post_content' => $content,
142 - );
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'];
143 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 +
144 866 // Update the post into the database
145 - wp_update_post($post);
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));
146 871
147 - if (is_wp_error($postID)) {
148 - $msg['error'] = __pl('post_update_err');
872 + if (is_wp_error($ret)) {
873 + $errors = $ret->get_error_messages();
874 + $msg['error'] = __pl('post_update_err').' : '.implode('', $errors);
149 875 }else{
150 - $msg['success'] = __pl('post_update_success');
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');
151 901 }
152 902
153 903 }else{
154 - $msg['error'] = __pl('post_update_err');
904 + $msg['error'] = __pl('post_update_err');
155 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 +}
156 937
157 - echo json_encode($msg);
158 - wp_die();
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){
159 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 + }
160 1033 }
161 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 +
162 1058 // Shortcodes Widget Handler
163 1059 add_action('wp_ajax_pagelayer_do_shortcodes', 'pagelayer_do_shortcodes');
164 1060 function pagelayer_do_shortcodes(){
165 1061
166 1062 // Some AJAX security
167 - check_ajax_referer('pagelayer_ajax', 'nonce');
1063 + check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
168 1064
1065 + if(!current_user_can('edit_posts')){// TODO : WooCommerce
1066 + $ret['error'][] = __pl('no_permission');
1067 + pagelayer_json_output($ret);
1068 + }
1069 +
169 1070 $data = '';
170 1071 if(isset($_REQUEST['shortcode_data'])){
171 1072 $data = stripslashes($_REQUEST['shortcode_data']);
172 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'])){
173 1145
174 - echo do_shortcode($data);
175 - wp_die();
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 + }
176 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 +
177 1214 }
178 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 +
179 1291 // Get the Site Title
180 1292 add_action('wp_ajax_pagelayer_fetch_site_title', 'pagelayer_fetch_site_title');
181 1293 function pagelayer_fetch_site_title(){
182 1294
183 1295 // Some AJAX security
184 - check_ajax_referer('pagelayer_ajax', 'nonce');
1296 + check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
185 1297
186 1298 echo get_bloginfo('name');
187 1299 wp_die();
188 1300 }
@@ -192,17 +1304,19 @@
192 1304 function pagelayer_update_site_title(){
193 1305 global $wpdb;
194 1306
195 1307 // Some AJAX security
196 - check_ajax_referer('pagelayer_ajax', 'nonce');
1308 + check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
197 1309
198 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 + }
199 1316
200 1317 update_option('blogname', $site_title);
201 -
202 - $wpdb->query("UPDATE `sm_sitemeta`
203 - SET meta_value = '".$site_title."'
204 - WHERE meta_key = 'site_name'");
1318 +
205 1319 wp_die();
206 1320 }
207 1321
208 1322 // Show the SideBars
@@ -211,9 +1325,9 @@
211 1325
212 1326 global $wp_registered_sidebars;
213 1327
214 1328 // Some AJAX security
215 - check_ajax_referer('pagelayer_ajax', 'nonce');
1329 + check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
216 1330
217 1331 // Create a list
218 1332 $pagelayer_wp_widgets = array();
219 1333
@@ -240,16 +1354,35 @@
240 1354 add_action('wp_ajax_pagelayer_fetch_primary_menu', 'pagelayer_fetch_primary_menu');
241 1355 function pagelayer_fetch_primary_menu(){
242 1356
243 1357 // Some AJAX security
244 - check_ajax_referer('pagelayer_ajax', 'nonce');
1358 + check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
245 1359
246 1360 if(isset($_POST['nav_list'])){
247 - echo wp_nav_menu([
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([
248 1379 'menu' => wp_get_nav_menu_object($_POST['nav_list']),
249 1380 'menu_id' => $_POST["nav_list"],
1381 + 'menu_class' => 'pagelayer-wp_menu-ul',
1382 + 'walker' => new Pagelayer_Walker_Nav_Menu(),
250 1383 //'theme_location' => 'primary',
251 - //'menu_class' => 'primary-menu',
1384 + 'echo' => true,
252 1385 ]);
253 1386 }
254 1387
255 1388 wp_die();
@@ -254,69 +1387,129 @@
254 1387
255 1388 wp_die();
256 1389 }
257 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 +
258 1430 // Get post revision
259 1431 add_action('wp_ajax_pagelayer_get_revision', 'pagelayer_get_revision');
260 1432 function pagelayer_get_revision(){
261 1433
262 1434 // Some AJAX security
263 - check_ajax_referer('pagelayer_ajax', 'nonce');
1435 + check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
264 1436
1437 + $ret = array();
265 1438 $postID = (int) $_GET['postID'];
266 - $post_revisions = array();
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 + }
267 1445
268 1446 if(empty($postID)){
269 - $post_revisions['error'] = __pl('invalid_post_id');
1447 + $ret['error'] = __pl('invalid_post_id');
270 1448 }else{
271 - $post_revisions = pagelayer_get_post_revision_by_id($postID);
1449 + $ret = pagelayer_get_post_revision_by_id($postID);
272 1450 }
273 1451
274 - echo json_encode($post_revisions);
275 - wp_die();
1452 + pagelayer_json_output($ret);
1453 +
276 1454 }
277 1455
278 -// Get post revision
1456 +// Apply post revision
279 1457 add_action('wp_ajax_pagelayer_apply_revision', 'pagelayer_apply_revision');
280 1458 function pagelayer_apply_revision(){
281 1459
282 1460 // Some AJAX security
283 - check_ajax_referer('pagelayer_ajax', 'nonce');
1461 + check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
284 1462
285 1463 $revisionID = (int) $_REQUEST['revisionID'];
286 - $post_data = array();
1464 + $parID = wp_get_post_parent_id($revisionID);
1465 + $ret = array();
287 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 +
288 1477 if(empty($revisionID)){
289 - $post_data['error'] = __pl('invalid_post_id');
1478 + $ret['error'] = __pl('invalid_post_id');
290 1479 }else{
291 1480
292 1481 $post = get_post( $revisionID );
293 1482
294 1483 if ( empty( $post ) ) {
295 - $post_data['error'] = __pl('invalid_revision');
296 - echo json_encode($post_data);
297 - return false;
1484 + $ret['error'] = __pl('invalid_revision');
1485 + pagelayer_json_output($ret);
298 1486 }
299 1487
300 1488 // Need to make the reviews post global
301 1489 $GLOBALS['post'] = $post;
1490 + $GLOBALS['wp_query'] = new WP_Query([
1491 + 'post_type' => $GLOBALS['post']->post_type,
1492 + 'post__in' => array($parID),
1493 + ]);
302 1494
303 1495 // Need to reload the shortcodes
304 1496 pagelayer_load_shortcodes();
305 1497
306 - $post_data['content'] = do_shortcode($post->post_content);
1498 + $ret['id'] = $revisionID;
1499 + $ret['content'] = pagelayer_the_content($post->post_content, true);
307 1500
308 - if (is_wp_error($postID)) {
309 - $post_data['error'] = __pl('rev_load_error');
1501 + if(is_wp_error($post)) {
1502 + $ret['error'] = __pl('rev_load_error');
310 1503 }else{
311 - $post_data['success'] = __pl('rev_load_success');
1504 + $ret['success'] = __pl('rev_load_success');
312 1505 }
313 1506
314 1507 wp_reset_postdata();
315 1508 }
316 1509
317 - echo json_encode($post_data);
318 - wp_die();
1510 + pagelayer_json_output($ret);
1511 +
319 1512 }
320 1513
321 1514 // Get post revision
322 1515 add_action('wp_ajax_pagelayer_delete_revision', 'pagelayer_delete_revision');
@@ -322,48 +1515,55 @@
322 1515 add_action('wp_ajax_pagelayer_delete_revision', 'pagelayer_delete_revision');
323 1516 function pagelayer_delete_revision() {
324 1517
325 1518 // Some AJAX security
326 - check_ajax_referer('pagelayer_ajax', 'nonce');
1519 + check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
327 1520
328 1521 $revisionID = (int) $_REQUEST['revisionID'];
1522 + $parID = wp_get_post_parent_id($revisionID);
1523 + $ret = array();
329 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 +
330 1531 if(empty($revisionID)){
331 - $post_data['error'] = __pl('invalid_post_id');
1532 + $ret['error'] = __pl('invalid_post_id');
332 1533 }else{
333 1534
334 1535 $revision = get_post( $revisionID );
335 1536
336 1537 if ( empty( $revision ) ) {
337 - $post_data['error'] = __pl('invalid_revision');
1538 + $ret['error'] = __pl('invalid_revision');
338 1539 }else{
339 1540
340 - if ( ! current_user_can( 'delete_post', $revision->ID ) ) {
341 - $post_data['error'] = __pl('access_denied');
342 - echo json_encode($post_data);
343 - return false;
1541 + if ( ! current_user_can( 'delete_post', $parID ) ) {
1542 + $ret['error'] = __pl('access_denied');
1543 + pagelayer_json_output($ret);
344 1544 }
345 1545
346 1546 $deleted = wp_delete_post_revision( $revision->ID );
347 1547
348 1548 if ( ! $deleted || is_wp_error( $deleted ) ) {
349 - $post_data['error'] = __pl('delete_rev_error');
1549 + $ret['error'] = __pl('delete_rev_error');
350 1550 }else{
351 - $post_data['success'] = __pl('delete_rev_success');
1551 + $ret['success'] = __pl('delete_rev_success');
352 1552 }
353 1553 }
354 1554 }
355 1555
356 - echo json_encode($post_data);
357 - wp_die();
1556 + pagelayer_json_output($ret);
1557 +
358 1558 }
359 1559
360 -// Get post revision
1560 +// Get post navigation
361 1561 add_action('wp_ajax_pagelayer_post_nav', 'pagelayer_post_nav');
362 1562 function pagelayer_post_nav() {
363 1563
364 1564 // Some AJAX security
365 - check_ajax_referer('pagelayer_ajax', 'nonce');
1565 + check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
366 1566
367 1567 if(!isset($_REQUEST['data']) || !isset($_REQUEST['postID'])){
368 1568 return;
369 1569 }
@@ -402,20 +1602,19 @@
402 1602 $el['atts']['next_link'] = get_next_post_link('%link', $next_label, $in_same_term, '', $taxonomies);
403 1603
404 1604 $el['atts']['prev_link'] = get_previous_post_link('%link', $prev_label, $in_same_term, '', $taxonomies );
405 1605
406 - echo json_encode($el);
407 - wp_die();
1606 + pagelayer_json_output($el);
408 1607
409 1608 }
410 1609
411 -// Get post comment template
1610 +// Get post comment template
412 1611 add_action('wp_ajax_pagelayer_post_comment', 'pagelayer_post_comment');
413 1612 function pagelayer_post_comment() {
414 1613 global $post;
415 1614
416 1615 // Some AJAX security
417 - check_ajax_referer('pagelayer_ajax', 'nonce');
1616 + check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
418 1617
419 1618 if(!isset($_REQUEST['postID'])){
420 1619 return true;
421 1620 }
@@ -422,15 +1621,16 @@
422 1621
423 1622 $GLOBALS['post'] = get_post($_REQUEST['postID']);
424 1623 $GLOBALS['withcomments'] = true;
425 1624
426 - if ( comments_open() || get_comments_number() ) {
427 - echo '<div class="pagelayer-comments-template">'.comments_template().'</div>';
428 - }else{
429 - echo '<div class="pagelayer-comments-close">
430 - <h2>Comments are closed!</h2>
431 - </div>';
432 - }
1625 + // Load shortcodes
1626 + pagelayer_load_shortcodes();
1627 +
1628 + $el = [];
1629 + pagelayer_sc_post_comment($el);
1630 +
1631 + echo $el['atts']['post_comment'];
1632 +
433 1633 wp_die();
434 1634
435 1635 }
436 1636
@@ -439,9 +1639,9 @@
439 1639 function pagelayer_post_info() {
440 1640 global $post;
441 1641
442 1642 // Some AJAX security
443 - check_ajax_referer('pagelayer_ajax', 'nonce');
1643 + check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce');
444 1644
445 1645 if(!isset($_REQUEST['postID']) || !isset($_REQUEST['el'])){
446 1646 return true;
447 1647 }
@@ -449,81 +1649,1243 @@
449 1649 $el['atts'] = $_REQUEST['el'];
450 1650
451 1651 $GLOBALS['post'] = get_post($_REQUEST['postID']);
452 1652
453 - $post_info_content ='';
454 - $link ='';
455 - $info_content ='';
456 - $avatar_url ='';
1653 + // Load shortcodes
1654 + pagelayer_load_shortcodes();
457 1655
458 - switch($el['atts']['type']){
459 - case 'author':
1656 + pagelayer_sc_post_info_list($el);
1657 +
1658 + pagelayer_json_output($el['atts']);
460 1659
461 - $link = get_author_posts_url( get_the_author_meta( 'ID' ) );
462 - $avatar_url = get_avatar_url( get_the_author_meta( 'ID' ), 96 );
463 - $post_info_content = get_the_author_meta( 'display_name', $post->post_author );
464 - break;
1660 +}
465 1661
466 - case 'date':
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']) ){
467 1773
468 - $format = [
469 - 'default' => 'F j, Y',
470 - '0' => 'F j, Y',
471 - '1' => 'Y-m-d',
472 - '2' => 'm/d/Y',
473 - '3' => 'd/m/Y',
474 - 'custom' => empty( $el['atts']['date_format_custom'] ) ? 'F j, Y' : $el['atts']['date_format_custom'],
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,
475 2024 ];
476 2025
477 - $post_info_content = get_the_time( $format[ $el['atts']['date_format'] ] );
478 - $link = get_day_link( get_post_time( 'Y' ), get_post_time( 'm' ), get_post_time( 'j' ) );
479 -
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 +
480 2034 break;
481 2035
482 - case 'time':
483 -
484 - $format = [
485 - 'default' => 'g:i a',
486 - '0' => 'g:i a',
487 - '1' => 'g:i A',
488 - '2' => 'H:i',
489 - 'custom' => empty( $el['atts']['time_format_custom'] ) ? 'F j, Y' : $el['atts']['time_format_custom'],
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,
490 2041 ];
491 - $post_info_content = get_the_time( $format[ $el['atts']['time_format'] ] );
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 + ];
492 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 + }
493 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 + }
494 2092
495 - case 'comments':
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 + }
496 2138
497 - if (comments_open()) {
498 - $post_info_content = (int) get_comments_number();
499 - $link = get_comments_link();
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;
500 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));
501 2453
502 - break;
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 + }
503 2627
504 - case 'terms':
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 + ] );
505 2648
506 - $taxonomy = $el['atts']['taxonomy'];
507 - $terms = wp_get_post_terms( get_the_ID(), $taxonomy );
508 - foreach ( $terms as $term ) {
509 - $post_info_content .= ' <a if-ext="{{info_link}}" href="'. get_term_link( $term ) .'" class="pagelayer-post-info-list-link"> '. $term->name .' </a>';
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;
510 2659 }
2660 + }
511 2661
512 - break;
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 +}
513 2683
514 - case 'custom':
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(){
515 2769
516 - $post_info_content = $el['atts']['type_custom'];
517 - $link = $el['atts']['info_custom_link'];
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 +}
518 2809
519 - break;
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);
520 2821 }
521 -
522 - $el['atts']['post_info_content'] = $post_info_content;
523 - $el['atts']['avatar_url'] = $avatar_url;
524 - $el['atts']['link'] = $link;
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']);
525 2829
526 - echo json_encode($el['atts']);
527 - wp_die();
528 -
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);
529 2891 }