PluginProbe
Post Grid Gutenberg Blocks – PostX / 5.0.39
Post Grid Gutenberg Blocks – PostX v5.0.39
5.0.39 5.0.38 5.0.37 5.0.36 5.0.35 5.0.34 5.0.33 5.0.32 5.0.31 5.0.30 5.0.29 5.0.28 5.0.27 5.0.26 5.0.25 5.0.23 5.0.24 5.0.22 5.0.21 5.0.20 5.0.19 5.0.18 5.0.17 2.1.1 2.1.2 All 237 releases
ultimate-post / classes / Importer.php

Importer.php in Post Grid Gutenberg Blocks – PostX 5.0.39, at classes/Importer.php

938 lines 30.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Importer System
5 *
6 * @package ULTP\Importer
7 * @since 4.0.0
8 */
9
10 namespace ULTP;
11
12 use ULTP\Includes\Durbin\DurbinClient;
13 use ULTP\Includes\Durbin\Xpo;
14
15 defined( 'ABSPATH' ) || exit;
16
17 /**
18 * Importer class.
19 *
20 * Handles starter site import, plugin installation, and REST API endpoints for Ultimate Post.
21 *
22 * @package ULTP\Importer
23 * @since 4.0.0
24 */
25 class Importer {
26 /**
27 * Setup class.
28 *
29 * @since 4.0.0
30 * @return NULL No return value.
31 */
32 public function __construct() {
33 add_action( 'wp_ajax_install_required_plugin', array( $this, 'install_required_plugin_callback' ) );
34 add_action( 'rest_api_init', array( $this, 'get_starter_rest_endpoint_callback' ) );
35 }
36
37 /**
38 * Register REST API endpoints for starter import and related actions.
39 *
40 * @since 4.0.0
41 * @return void No return value.
42 */
43 public function get_starter_rest_endpoint_callback() {
44 register_rest_route(
45 'ultp/v3',
46 '/single_page_import/',
47 array(
48 array(
49 'methods' => 'POST',
50 'callback' => array( $this, 'single_page_import' ),
51 'permission_callback' => function () {
52 return current_user_can( 'edit_others_posts' );
53 },
54 'args' => array(),
55 ),
56 )
57 );
58 register_rest_route(
59 'ultp/v3',
60 '/deletepost_getnewsletters/',
61 array(
62 array(
63 'methods' => 'POST',
64 'callback' => array( $this, 'deletepost_getnewsletters' ),
65 'permission_callback' => function () {
66 return current_user_can( 'manage_options' );
67 },
68 'args' => array(),
69 ),
70 )
71 );
72 register_rest_route(
73 'ultp/v3',
74 '/starter_import_content/',
75 array(
76 array(
77 'methods' => 'POST',
78 'callback' => array( $this, 'starter_import_content_callback' ),
79 'permission_callback' => function () {
80 return current_user_can( 'manage_options' );
81 },
82 'args' => array(),
83 ),
84 )
85 );
86 register_rest_route(
87 'ultp/v3',
88 '/starter_dummy_post/',
89 array(
90 array(
91 'methods' => 'POST',
92 'callback' => array( $this, 'starter_dummy_post_callback' ),
93 'permission_callback' => function () {
94 return current_user_can( 'manage_options' );
95 },
96 'args' => array(),
97 ),
98 )
99 );
100 }
101
102 /**
103 * Handle plugin installation via AJAX.
104 *
105 * @since 4.0.0
106 * @return void No return value.
107 */
108 public function install_required_plugin_callback() {
109 if ( ! current_user_can( 'install_plugins' ) ) {
110 return wp_send_json_success( 'You are not allowed to install plugin' );
111 }
112 if ( ! wp_verify_nonce( sanitize_key( wp_unslash( $_REQUEST['wpnonce'] ) ), 'ultp-nonce' ) ) {
113 return '';
114 }
115 if ( ! current_user_can( 'install_plugins' ) ) {
116 return wp_send_json_success( 'You are not allowed to install plugin' );
117 }
118
119 if ( ! function_exists( 'get_plugins' ) ) {
120 require_once ABSPATH . 'wp-admin/includes/plugin.php';
121 }
122 if ( ! function_exists( 'plugins_api' ) ) {
123 require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
124 }
125 if ( ! class_exists( 'WP_Upgrader' ) ) {
126 require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
127 }
128
129 $msg = '';
130
131 $all_plugins = get_plugins();
132 $plugin = ultimate_post()->ultp_rest_sanitize_params( json_decode( stripslashes( $_POST['plugin'] ) ) );
133
134 if ( $plugin && isset( $all_plugins ) && is_array( $all_plugins ) && array_key_exists( $plugin->path, $all_plugins ) ) {
135 $activated_plugins = apply_filters( 'active_plugins', get_option( 'active_plugins' ) );
136 if ( is_array( $activated_plugins ) && in_array( $plugin->path, $activated_plugins ) ) {
137 $msg = '_already_installed_activated';
138 } else {
139 $activate = activate_plugin( $plugin->path, '', false );
140 $msg = is_wp_error( $activate ) ? '_only_activated_error' : '_only_activated_success';
141 }
142 } else {
143 $upgrader = new \Plugin_Upgrader( new \WP_Ajax_Upgrader_Skin() );
144 if ( isset( $plugin->download ) ) {
145 // Download.
146 $link = $api->download;
147 } else {
148 // From Org.
149 $api = plugins_api(
150 'plugin_information',
151 array(
152 'slug' => explode( '/', $plugin->path )[0],
153 'fields' => array(
154 'short_description' => false,
155 'sections' => false,
156 'requires' => false,
157 'rating' => false,
158 'ratings' => false,
159 'downloaded' => false,
160 'last_updated' => false,
161 'added' => false,
162 'tags' => false,
163 'compatibility' => false,
164 'homepage' => false,
165 'donate_link' => false,
166 ),
167 )
168 );
169 $link = $api->download_link;
170 }
171 $installed = $upgrader->install( $link );
172 $activate = activate_plugin( $plugin->path, '', false );
173
174 $msg = is_wp_error( $activate ) ? $link : '_download_activation_success';
175 }
176
177 if ( $msg == '_download_activation_error' || $msg == '_only_activated_error' ) {
178 wp_send_json_error( $msg );
179 } else {
180 wp_send_json_success( $msg );
181 }
182 }
183
184 /**
185 * Starter dummy post callback.
186 *
187 * @since 4.0.0
188 *
189 * @param \WP_REST_Request $server The REST request object.
190 */
191 function starter_dummy_post_callback( $server ) {
192 $post = $server->get_params();
193 $api_endpoint = isset( $post['api_endpoint'] ) ? sanitize_text_field( $post['api_endpoint'] ) : '';
194 $import_dummy = isset( $post['importDummy'] ) ? sanitize_text_field( $post['importDummy'] ) : '';
195
196 // SSRF protection: Validate API endpoint
197 if ( ! $this->is_allowed_api_endpoint( $api_endpoint ) ) {
198 return rest_ensure_response(
199 array(
200 'success' => false,
201 'message' => __( 'Invalid API endpoint. Only trusted domains are allowed.', 'ultimate-post' ),
202 )
203 );
204 }
205
206 $response = wp_safe_remote_post(
207 $api_endpoint . '/wp-json/importer/site_all_posts',
208 array(
209 'method' => 'POST',
210 'timeout' => 120,
211 'body' => array(
212 'type' => 'site_posts',
213 'license' => Xpo::get_lc_key(),
214 'ultp_ver' => ULTP_VER,
215 ),
216 )
217 );
218 if ( is_wp_error( $response ) ) {
219 return rest_ensure_response(
220 array(
221 'success' => false,
222 'response_data' => $response,
223 )
224 );
225 }
226 $response_data = json_decode( $response['body'] );
227 if ( ! $response_data->success ) {
228 return rest_ensure_response(
229 array(
230 'success' => false,
231 'returns' => $response_data,
232 )
233 );
234 }
235
236 // Dummy Post and Taxonomy creation.
237 $importable_posts = $response_data->posts;
238 $created_posts = $import_dummy != 'no' ? $this->starter_pack_dummy_post_creation( $importable_posts ) : array();
239 return rest_ensure_response(
240 array(
241 'success' => true,
242 'created_posts' => $created_posts,
243 )
244 );
245 }
246
247
248 function starter_import_content_callback( $server ) {
249 $post = $server->get_params();
250 $api_endpoint = isset( $post['api_endpoint'] ) ? sanitize_text_field( $post['api_endpoint'] ) : '';
251 $installed_plugin = isset( $post['installPlugin'] ) ? sanitize_text_field( $post['installPlugin'] ) : '';
252
253 if ( ! $this->is_allowed_api_endpoint( $api_endpoint ) ) {
254 return rest_ensure_response(
255 array(
256 'success' => false,
257 'message' => __( 'Invalid API endpoint. Only trusted domains are allowed.', 'ultimate-post' ),
258 )
259 );
260 }
261
262 // draft existing builder template.
263 $builder_parsed_args = array(
264 'post_type' => 'ultp_builder',
265 'post_status' => 'publish',
266 'posts_per_page' => -1,
267 );
268 $builder_posts = new \WP_Query( $builder_parsed_args );
269 if ( is_array( $builder_posts->posts ) && ! empty( $builder_posts->posts ) ) {
270 foreach ( $builder_posts->posts as $post ) {
271 wp_update_post(
272 array(
273 'ID' => $post->ID,
274 'post_status' => 'draft',
275 )
276 );
277 }
278 }
279
280 $response = wp_safe_remote_post(
281 $api_endpoint . '/wp-json/importer/single',
282 array(
283 'method' => 'POST',
284 'timeout' => 120,
285 'body' => array(
286 'license' => Xpo::get_lc_key(),
287 'ultp_ver' => ULTP_VER,
288 ),
289 )
290 );
291
292 if ( is_wp_error( $response ) ) {
293 return rest_ensure_response(
294 array(
295 'success' => false,
296 'response_data' => $response,
297 )
298 );
299 }
300 $response_data = json_decode( $response['body'] );
301 if ( ! $response_data->success ) {
302 return rest_ensure_response(
303 array(
304 'success' => false,
305 'response_data' => $response_data,
306 )
307 );
308 }
309
310 // site logo handle.
311 if ( ! get_option( 'site_logo', '' ) && isset( $response_data->site_logo ) && $response_data->site_logo ) {
312 update_option( 'site_logo', $this->upload_post_cat_media( $response_data->site_logo, '', 'Site Logo' ) );
313
314 if ( isset( $response_data->dark_logo ) && $response_data->dark_logo ) {
315 $dark_logo = $this->upload_post_cat_media( $response_data->dark_logo, '', 'Site Dark Logo' );
316 update_option( 'ultp_site_dark_logo', wp_get_attachment_url( $dark_logo ) );
317 }
318 }
319
320 // Templates Insertion.
321 $inserted_meta = array();
322 $inserted_pages = array();
323 $inserted_header_footer = array();
324 $importable_pages = $response_data->content;
325
326 $exclude_post_type = is_object( $post ) ? ( $post->excludepages ?? null ) : ( $post['excludepages'] ?? null );
327 $excludepages = json_decode( ultimate_post()->ultp_rest_sanitize_params( stripslashes( $exclude_post_type ) ), true );
328
329 if ( ! empty( $importable_pages ) ) {
330 foreach ( $importable_pages as $key => $val ) {
331 $title = $val->name;
332 if ( is_array( $excludepages ) && ! in_array( $title, $excludepages ) ) {
333 $post_type = $val->type;
334 $p_content = str_replace( array( 'u0022', 'u002d' ), array( '\u0022', '\u002d' ), $val->content );
335 $p_content = str_replace( array( 'u003c', 'u003e', 'currentPostId' ), array( '<', '>', 'current_PostId' ), $p_content );
336 $post_id = wp_insert_post(
337 array(
338 'post_title' => $title,
339 'post_type' => $post_type,
340 'post_status' => 'publish',
341 'post_content' => $p_content,
342 )
343 );
344 if ( $post_id ) {
345 update_post_meta( $post_id, '__ultp_starter_pack_post', true );
346 $inserted_pages[ $post_id ] = $title;
347
348 if ( isset( $val->ultp_template ) && $val->ultp_template === 'ultp_page_template' ) {
349 update_post_meta( $post_id, '_wp_page_template', 'ultp_page_template' );
350 }
351 if ( isset( $val->home_page ) && $val->home_page == 'home_page' ) {
352 if ( get_option( 'show_on_front', true ) != 'page' ) {
353 update_option( 'show_on_front', 'page' );
354 }
355 update_option( 'page_on_front', $post_id );
356 $inserted_header_footer['home_page'] = $post_id;
357 }
358 if ( isset( $val->ultp_builder_type ) && ( $val->ultp_builder_type == 'header' || $val->ultp_builder_type == 'footer' ) ) {
359 $inserted_header_footer[] = $post_id;
360 }
361 if ( $post_type == 'ultp_builder' && $val->ultp_builder_type ) {
362 $conditions_settings = get_option( 'ultp_builder_conditions', array() );
363 $conditions = $response_data->conditions;
364 $ultp_builder_type = $val->ultp_builder_type;
365 $ultp_builder_id = $val->id;
366 $ultp_builder_conditions = $conditions->$ultp_builder_type;
367 $ultp_builder_conditions = $ultp_builder_conditions->$ultp_builder_id;
368 $conditions_settings[ $ultp_builder_type ][ $post_id ] = $ultp_builder_conditions;
369
370 update_post_meta( $post_id, '__ultp_builder_type', $val->ultp_builder_type );
371 update_option( 'ultp_builder_conditions', $conditions_settings );
372 }
373 if ( isset( $val->meta ) && is_array( $val->meta ) ) {
374 foreach ( $val->meta as $k => $v ) {
375 update_post_meta( $post_id, $k, str_replace( array( 'u0022', 'u002d' ), array( '\u0022', '\u002d' ), $v ) );
376 }
377 }
378 if ( isset( $val->_ultp_css ) ) {
379 $this->save_post_block_css( $post_id, str_replace( array( 'u0022', 'u002d' ), array( '\u0022', '\u002d' ), $val->_ultp_css ), '' );
380 }
381 $inserted_meta[ $post_id ] = $val->_ultp_css;
382 }
383 }
384 }
385 }
386
387 // Menu Creation.
388 $menuCreated = array();
389 $menu_item_parent = array();
390 $response_menu = $response_data->menu;
391 if ( ! empty( $response_menu ) && is_array( $response_menu ) ) {
392 foreach ( $response_menu as $key => $menu ) {
393 $menu_exists = wp_get_nav_menu_object( $menu->title );
394 if ( $menu_exists ) {
395 wp_delete_term( $menu_exists->term_id, $menu_exists->taxonomy );
396 }
397 $menu_id = wp_create_nav_menu( $menu->title );
398 if ( isset( $menu->items ) && $menu_id && ! empty( $menu->items ) ) {
399 foreach ( $menu->items as $key => $v ) {
400 $inserted = array_search( $v->title, $inserted_pages );
401 if ( $inserted || $v->type == 'custom' || $v->type == 'category' ) {
402 if (
403 ( $v->type == 'category' && get_term_by( 'name', $v->title, 'category' ) )
404 || $v->type != 'category'
405 ) {
406 $item = array(
407 'menu-item-title' => $v->title,
408 'menu-item-status' => 'publish',
409 );
410 $item['menu-item-object'] = $v->type;
411 $item['menu-item-type'] = $v->post_type;
412 if ( isset( $v->menu_item_parent ) && $v->menu_item_parent ) {
413 $parent_id = $this->find_parent_nav_item( wp_get_nav_menu_items( $menu_id ), $v->menu_item_parent );
414 $menu_item_parent[ $v->title ] = $parent_id;
415 $item['menu-item-parent-id'] = $parent_id;
416 }
417 if ( $v->type == 'custom' ) {
418 $item['menu-item-url'] = $v->url ? $v->url : home_url( '/' );
419 } elseif ( $v->type == 'category' ) {
420 $fetched_term = get_term_by( 'name', $v->title, 'category' );
421 if ( $fetched_term ) {
422 $item['menu-item-object-id'] = $fetched_term->term_id;
423 }
424 } else {
425 $item['menu-item-object-id'] = $inserted;
426 }
427 wp_update_nav_menu_item( $menu_id, 0, $item );
428 }
429 }
430 }
431 update_term_meta( $menu_id, '__ultp_starter_pack_term', 'postx_term' );
432 $menuCreated[ $menu_id ] = $item;
433 }
434 }
435 }
436
437 // Navigation Creation for Header Footer Builder.
438 $navCreated = array();
439 $navigation = $response_data->navigation; // returned from importer site.
440 if ( ! empty( $inserted_header_footer ) && ! empty( $navigation ) ) {
441 foreach ( $inserted_header_footer as $key => $builderID ) {
442 $builder_post = get_post( $builderID );
443 $builder_post_content = $builder_post->post_content;
444 foreach ( $navigation as $key => $v ) {
445 $site_navID = $v->id;
446 if ( strpos( $builder_post_content, 'wp:navigation' ) > -1 && ( strpos( $builder_post_content, '{"ref":' . $site_navID . ',' ) > -1 || strpos( $builder_post_content, '{"ref":' . $site_navID . '}' ) > -1 ) ) {
447
448 $current_parsed_args = array(
449 'post_type' => 'wp_navigation',
450 'post_status' => 'publish',
451 'orderby' => 'date',
452 'order' => 'ASC',
453 'posts_per_page' => -1,
454 );
455 $navigation_current_posts = new \WP_Query( $current_parsed_args );
456 $navigation_current_posts = $navigation_current_posts->posts;
457
458 // check for currently same navigation exist or not.
459 $new_navID = '';
460 if ( ! $new_navID ) {
461 $menu_exists = wp_get_nav_menu_object( $v->post_title );
462 if ( $menu_exists ) {
463 $menu_blocks = \WP_Classic_To_Block_Menu_Converter::convert( $menu_exists );
464 $new_navID = wp_insert_post(
465 array(
466 'post_content' => $menu_blocks,
467 'post_title' => $menu_exists->name,
468 'post_name' => $menu_exists->slug,
469 'post_status' => 'publish',
470 'post_type' => 'wp_navigation',
471 )
472 );
473 update_post_meta( $new_navID, '__ultp_starter_pack_post', true );
474 }
475 }
476 if ( strpos( $builder_post_content, '{"ref":' . $site_navID . ',' ) > -1 ) {
477 $builder_post_content = str_replace( '{"ref":' . $site_navID . ',', '{"ref":' . $new_navID . ',', $builder_post_content );
478 } elseif ( strpos( $builder_post_content, '{"ref":' . $site_navID . '}' ) ) {
479 $builder_post_content = str_replace( '{"ref":' . $site_navID . '}', '{"ref":' . $new_navID . '}', $builder_post_content );
480 }
481
482 wp_update_post(
483 array(
484 'ID' => $builderID,
485 'post_content' => str_replace( array( 'u0022', 'u002d' ), array( '\u0022', '\u002d' ), $builder_post_content ),
486 )
487 );
488 $navCreated[] = $new_navID;
489 }
490 }
491 }
492 }
493
494 // Other Plugin Content creation.
495 $other_plugin_content = $response_data->other_plugin_content;
496 $contact_forms = $other_plugin_content->contact_form7;
497 $mc4wp = $other_plugin_content->mc4wp;
498 $wow_optin_template_id = isset( $other_plugin_content->wow_optin->id ) ? $other_plugin_content->wow_optin->id : 0;
499
500 // contact form 7 post create.
501 if ( is_array( $contact_forms ) && ! empty( $contact_forms ) ) {
502 foreach ( $contact_forms as $post ) {
503 $post_id = wp_insert_post(
504 array(
505 'post_title' => $post->post_title,
506 'post_type' => 'wpcf7_contact_form',
507 'post_status' => 'publish',
508 'post_content' => str_replace( array( 'u002d', '<wordpress@postxkit.wpxpo.com>' ), array( '\u002d', '' ), $post->post_content ),
509 )
510 );
511 update_post_meta( $post_id, '_form', $post->_form );
512 update_post_meta( $post_id, '_hash', $post->_hash );
513 update_post_meta( $post_id, '__ultp_starter_pack_post', true );
514 }
515 }
516
517 // mailchimp post create.
518 if ( ! empty( $inserted_pages ) && ! empty( $mc4wp ) ) {
519 foreach ( $inserted_pages as $id => $p_t ) {
520 $current_post = get_post( $id );
521 $current_post_content = $current_post->post_content;
522 foreach ( $mc4wp as $key => $v ) {
523 $parsed_args = array(
524 'post_type' => 'mc4wp-form',
525 'post_status' => 'publish',
526 'posts_per_page' => -1,
527 );
528 $mc4wp_forms_data = new \WP_Query( $parsed_args );
529 $mc4wp_forms_current_posts = $mc4wp_forms_data->posts;
530
531 $site_ID = $v->id;
532 if ( strpos( $current_post_content, '[mc4wp_form id=' . $site_ID . ']' ) > -1 ) {
533 $new_ID = '';
534 // check for same mailchimp post.
535 if ( ! empty( $mc4wp_forms_current_posts ) ) {
536 foreach ( $mc4wp_forms_current_posts as $key => $val ) {
537 if ( $val->post_title == $v->post_title ) {
538 $new_ID = $val->ID;
539 }
540 }
541 }
542 if ( ! $new_ID ) {
543 $new_ID = wp_insert_post(
544 array(
545 'post_title' => $v->post_title,
546 'post_type' => 'mc4wp-form',
547 'post_status' => 'publish',
548 'post_content' => $v->post_content,
549 )
550 );
551 update_post_meta( $new_ID, '__ultp_starter_pack_post', true );
552 }
553
554 $current_post_content = str_replace( '[mc4wp_form id=' . $site_ID . ']', '[mc4wp_form id=' . $new_ID . ']', $current_post_content );
555 wp_update_post(
556 array(
557 'ID' => $id,
558 'post_content' => str_replace( array( 'u0022', 'u002d' ), array( '\u0022', '\u002d' ), $current_post_content ),
559 )
560 );
561 }
562 }
563 }
564 }
565 $wow_optin_template_import_status = 'successfully working';
566
567 $activated_plugins = $installed_plugin == 'yes' ? apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) : array();
568 if ( in_array( 'optin/optin.php', $activated_plugins ) && $wow_optin_template_id && $installed_plugin == 'yes' ) {
569 try {
570 if ( class_exists( '\OPTN\Includes\Db', true ) && method_exists( '\OPTN\Includes\Db', 'get_instance' ) ) {
571 $db_instance = \OPTN\Includes\Db::get_instance();
572 if ( is_object( $db_instance ) && is_callable( array( $db_instance, 'activate_recipe' ) ) ) {
573 $db_instance->activate_recipe(
574 $wow_optin_template_id,
575 array(
576 'disable_others' => true,
577 )
578 );
579 }
580 }
581 } catch ( \Throwable $e ) {
582 $wow_optin_template_import_status = 'have any problem to import Optin template.';
583 }
584 }
585 // $wow_optin_template_import_status
586 return rest_ensure_response(
587 array(
588 'success' => true,
589 'inserted_pages' => $inserted_pages,
590 'inserted_meta' => $inserted_meta,
591 'navCreated' => $navCreated,
592 'menuCreated' => $menuCreated,
593 'menu_item_parent' => $menu_item_parent,
594 'inserted_header_footer' => $inserted_header_footer,
595 'wow_optin_status' => $installed_plugin,
596 )
597 );
598 }
599
600
601 /**
602 * Find Menu Parent item
603 *
604 * @since 4.0.0
605 *
606 * @param array $menu_items Array of menu items.
607 * @param string $title Title of the parent menu item to find.
608 */
609 public function find_parent_nav_item( $menu_items, $title ) {
610 if ( $menu_items ) {
611 foreach ( $menu_items as $menu_item ) {
612 if ( $menu_item->title == $title ) {
613 return $menu_item->ID;
614 }
615 }
616 }
617 return 0;
618 }
619
620 /**
621 * Save CSS of pages
622 *
623 * Saves the provided CSS content for a specific post ID. Depending on the operation type,
624 * it can also handle deletion of the CSS.
625 *
626 * @since 4.0.0
627 *
628 * @param int $id The post ID.
629 * @param string $css The CSS content to save.
630 * @param string $type The operation type (e.g., 'delete').
631 * @throws Exception If the CSS cannot be saved or deleted.
632 */
633 public function save_post_block_css( $id, $css = '', $type = '' ) {
634 try {
635 global $wp_filesystem;
636 if ( ! $wp_filesystem ) {
637 require_once ABSPATH . 'wp-admin/includes/file.php';
638 }
639
640 $upload_dir_url = wp_upload_dir();
641 $dir = trailingslashit( $upload_dir_url['basedir'] ) . 'ultimate-post/';
642
643 $post_id = (int) $id;
644 $filename = "ultp-css-{$post_id}.css";
645 $ultp_block_css = $css;
646
647 if ( $ultp_block_css ) {
648 // Set Saving ID for Clean Cache.
649 ultimate_post()->set_setting( 'save_version', wp_rand( 1, 1000 ) );
650
651 update_post_meta( $post_id, '_ultp_active', 'yes' );
652
653 WP_Filesystem( false, $upload_dir_url['basedir'], true );
654 if ( ! $wp_filesystem->is_dir( $dir ) ) {
655 $wp_filesystem->mkdir( $dir );
656 }
657 if ( ! $wp_filesystem->put_contents( $dir . $filename, $ultp_block_css ) ) {
658 throw new Exception(__('CSS can not be saved due to permission!!!', 'ultimate-post')); //phpcs:ignore
659 }
660 update_post_meta( $post_id, '_ultp_css', $ultp_block_css );
661 return array(
662 'success' => true,
663 'message' => __( 'PostX css file has been updated.', 'ultimate-post' ),
664 );
665 }
666 if ( $type == 'delete' && file_exists( $dir . $filename ) ) {
667 wp_delete_file( $dir . $filename );
668 }
669 } catch ( Exception $e ) {
670 return array(
671 'success' => false,
672 'message' => $e->getMessage(),
673 );
674 }
675 }
676
677 /**
678 * Delete previos site import post/pages
679 *
680 * @since 4.0.0
681 *
682 * @param \WP_REST_Request $server The REST request object.
683 */
684 public function deletepost_getnewsletters( $server ) {
685 $post = $server->get_params();
686 $deletePrevious = isset( $post['deletePrevious'] ) ? sanitize_text_field( $post['deletePrevious'] ) : '';
687 $get_newsletter = isset( $post['get_newsletter'] ) ? sanitize_text_field( $post['get_newsletter'] ) : '';
688 $deleted_terms = array();
689 $deleted_posts = array();
690 if ( $deletePrevious == 'yes' ) {
691 $site_logo = get_option( 'site_logo', '' );
692 global $wpdb;
693 $post_ids = $wpdb->get_col( $wpdb->prepare( "SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key='__ultp_starter_pack_post'" ) );
694 $terms = $wpdb->get_col( $wpdb->prepare( "SELECT term_id FROM {$wpdb->termmeta} WHERE meta_key='__ultp_starter_pack_term'" ) );
695
696 if ( isset( $post_ids ) && is_array( $post_ids ) ) {
697 foreach ( $post_ids as $post_id ) {
698 if ( get_post_type( $post_id ) == 'ultp_builder' ) {
699 $conditions = get_option( 'ultp_builder_conditions', array() );
700 $builder_type = get_post_meta( $post_id, '__ultp_builder_type', true );
701 if ( isset( $conditions[ $builder_type ][ $post_id ] ) ) {
702 unset( $conditions[ $builder_type ][ $post_id ] );
703 update_option( 'ultp_builder_conditions', $conditions );
704 }
705 }
706 if ( $site_logo == $post_id ) {
707 update_option( 'site_logo', '' );
708 }
709 $deleted_posts[] = $post_id;
710 wp_delete_post( $post_id, true );
711 $this->save_post_block_css( $post_id, '', 'delete' );
712 }
713 }
714 if ( isset( $terms ) && is_array( $terms ) ) {
715 foreach ( $terms as $term_id ) {
716 $deleted_terms[] = $term_id;
717 $term = get_term( $term_id );
718 wp_delete_term( $term_id, $term->taxonomy );
719 }
720 }
721 }
722 if ( $get_newsletter == 'yes' ) {
723 DurbinClient::send( DurbinClient::ACTIVATE_ACTION );
724 }
725
726 return rest_ensure_response(
727 array(
728 'success' => true,
729 'term' => $deleted_terms,
730 'posts' => $deleted_posts,
731 )
732 );
733 }
734
735 /**
736 * Import Single Template
737 *
738 * @since 4.0.0
739 *
740 * @param \WP_REST_Request $server The REST request object.
741 */
742 public function single_page_import( $server ) {
743 $post = $server->get_params();
744 $id = isset( $post['ID'] ) ? sanitize_text_field( $post['ID'] ) : '';
745 $api_endpoint = isset( $post['api_endpoint'] ) ? sanitize_text_field( $post['api_endpoint'] ) : '';
746
747 if ( $id && $api_endpoint ) {
748 // SSRF protection: Validate API endpoint
749 if ( ! $this->is_allowed_api_endpoint( $api_endpoint ) ) {
750 return rest_ensure_response(
751 array(
752 'success' => false,
753 'message' => __( 'Invalid API endpoint. Only trusted domains are allowed.', 'ultimate-post' ),
754 )
755 );
756 }
757 $import_single = array(
758 'id' => $id,
759 'type' => 'single',
760 'license' => Xpo::get_lc_key(),
761 'ultp_ver' => ULTP_VER,
762 );
763 $response = wp_safe_remote_post(
764 $api_endpoint . '/wp-json/importer/single',
765 array(
766 'method' => 'POST',
767 'timeout' => 120,
768 'body' => $import_single,
769 )
770 );
771 $response_data = json_decode( $response['body'] );
772 if ( ! $response_data->success ) {
773 wp_send_json(
774 array(
775 'success' => false,
776 )
777 );
778 }
779 $content = $response_data->content[0];
780 return rest_ensure_response(
781 array(
782 'success' => true,
783 'content' => $content,
784 )
785 );
786 }
787 }
788
789 /**
790 * Create dummy posts
791 *
792 * @since 4.0.0
793 *
794 * @param array $importable_posts Array of importable post objects.
795 */
796 public function starter_pack_dummy_post_creation( $importable_posts ) {
797 $added_posts = array();
798 if ( is_array( $importable_posts ) && ! empty( $importable_posts ) ) {
799 foreach ( $importable_posts as $post ) {
800 $post_id = wp_insert_post(
801 array(
802 'post_title' => $post->post_title,
803 'post_type' => 'post',
804 'post_status' => 'publish',
805 'post_content' => str_replace( 'u002d', '\u002d', $post->post_content ),
806 )
807 );
808 $image_id = $this->upload_post_cat_media( $post->img_src, $post_id, $post->post_title );
809 set_post_thumbnail( $post_id, $image_id );
810
811 update_post_meta( $post_id, '__ultp_starter_pack_post', true );
812 if ( isset( $post->_ultp_css ) && $post->_ultp_css ) {
813 $this->save_post_block_css( $post_id, str_replace( array( 'u0022', 'u002d' ), array( '\u0022', '\u002d' ), $post->_ultp_css ), '' );
814 }
815 $post_category = $post->post_category;
816 $k = 0;
817 $cat_ids = array();
818 if ( is_array( $post_category ) && ! empty( $post_category ) ) {
819 foreach ( $post_category as $i => $cat ) {
820 $cat_id = $this->starter_pack_dummy_taxonomy_creation( $cat->name, $cat->slug, $cat->img_src, 'category' );
821 wp_set_post_terms( $post_id, $cat_id, 'category', $k == 0 ? false : true );
822 ++$k;
823 $cat_ids[] = $cat_id;
824 }
825 }
826 $post_tags = $post->post_tags;
827 $tag_ids = array();
828 $j = 0;
829 if ( is_array( $post_tags ) && ! empty( $post_tags ) ) {
830 foreach ( $post_tags as $i => $tag ) {
831 $tag_id = wp_set_post_terms( $post_id, $tag->slug, 'post_tag', $j == 0 ? false : true );
832 if ( ! is_wp_error( $tag_id ) && is_array( $tag_id ) && isset( $tag_id[0] ) ) {
833 update_term_meta( $tag_id[0], '__ultp_starter_pack_term', 'postx_term' );
834 $tag_ids[] = $tag_id[0];
835 }
836 ++$j;
837 }
838 }
839 $added_posts[ $post_id ] = array(
840 'title' => $post->post_title,
841 'cat_id' => $cat_ids,
842 'tag_ids' => $tag_ids,
843 );
844 }
845 }
846 return $added_posts;
847 }
848
849 /**
850 * Create dummy category of posts
851 *
852 * @since 4.0.0
853 *
854 * @param STRING $name The name of the taxonomy term.
855 * @param STRING $slug The slug for the taxonomy term.
856 * @param STRING $img_src (Optional) The image source URL for the taxonomy term.
857 * @param STRING $taxonomy (Optional) The taxonomy type.
858 */
859 public function starter_pack_dummy_taxonomy_creation( $name, $slug, $img_src = '', $taxonomy = '' ) {
860 $new_taxonomy = get_term_by( 'slug', $slug, $taxonomy );
861 if ( ! $new_taxonomy ) {
862 $new_term = wp_insert_term(
863 $name,
864 $taxonomy,
865 array(
866 'slug' => $slug,
867 )
868 );
869 if ( $new_term ) {
870 if ( $img_src ) {
871 $image_id = $this->upload_post_cat_media( $img_src, '', $name );
872 update_term_meta( $new_term['term_id'], 'ultp_category_image', $image_id );
873 }
874 update_term_meta( $new_term['term_id'], '__ultp_starter_pack_term', 'postx_term' );
875
876 return $new_term['term_id'];
877 }
878 } else {
879 return $new_taxonomy->term_id;
880 }
881 }
882
883 /**
884 * Upload image for post/category
885 *
886 * @since 4.0.0
887 *
888 * @param STRING $src The source URL of the image.
889 * @param INT $post_id The post ID to attach the image to.
890 * @param STRING $title The title for the image.
891 */
892 public function upload_post_cat_media( $src, $post_id, $title ) {
893 if ( ! $src ) {
894 return 0;
895 }
896
897 require_once ABSPATH . 'wp-admin/includes/media.php';
898 require_once ABSPATH . 'wp-admin/includes/file.php';
899 require_once ABSPATH . 'wp-admin/includes/image.php';
900
901 $image_id = media_sideload_image( $src, $post_id, $title, 'id' );
902 update_post_meta( $image_id, '__ultp_starter_pack_post', true );
903 return $image_id;
904 }
905
906 /**
907 * Validate if the API endpoint is from an allowed domain (SSRF protection).
908 *
909 * @since 5.0.6
910 * @param string $url The URL to validate.
911 * @return bool True if allowed, false otherwise.
912 */
913 private function is_allowed_api_endpoint( $url ) {
914 $allowed_domains = array(
915 'starter.postx.io',
916 'postxkit.wpxpo.com',
917 );
918
919 $parsed_url = wp_parse_url( $url );
920 if ( ! $parsed_url || empty( $parsed_url['host'] ) ) {
921 return false;
922 }
923
924 $host = strtolower( $parsed_url['host'] );
925
926 foreach ( $allowed_domains as $domain ) {
927 $domain = strtolower( $domain );
928
929 // Exact match OR valid subdomain
930 if ( $host === $domain || substr( $host, - ( strlen( $domain ) + 1 ) ) === '.' . $domain ) {
931 return true;
932 }
933 }
934
935 return false;
936 }
937 }
938