PluginProbe
Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! / 3.1.9
Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! v3.1.9
3.8.0 3.7.5 3.7.4 3.7.3 3.7.2 1-final 3.7.1 3.7.0 3.6.8 3.6.7 3.6.6 3.6.5 3.6.4 3.6.3 3.6.2 3.6.1 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.1 All 112 releases
← All changes | includes/Core/Importer/FullSiteImport.php +681 -259 3.1.13.1.9 View file →
@@ -1,9 +1,12 @@
1 1 <?php
2 2
3 3 namespace Templately\Core\Importer;
4 4
5 +use Elementor\Plugin;
6 +use Error;
5 7 use Exception;
8 +use Templately\Core\Importer\Utils\Utils;
6 9 use Templately\Utils\Base;
7 10 use Templately\Utils\Helper;
8 11 use Templately\Utils\Installer;
9 12 use Templately\Utils\Options;
@@ -29,33 +32,64 @@
29 32 protected $dependency_data = [];
30 33 private $is_import_status_handled = false;
31 34
32 35 public function __construct() {
33 - $this->dev_mode = defined( 'TEMPLATELY_DEV' ) && TEMPLATELY_DEV;
34 - $this->api_key = Options::get_instance()->get( 'api_key' );
36 + $this->dev_mode = defined('TEMPLATELY_DEV') && TEMPLATELY_DEV;
37 + $this->api_key = Options::get_instance()->get('api_key');
35 38
36 - add_action( 'wp_ajax_templately_import_settings', [ $this, 'import_settings' ] );
37 - add_action( 'wp_ajax_templately_pack_import_status', [ $this, 'import_status' ] );
38 - add_action( 'wp_ajax_templately_pack_import', [ $this, 'import' ] );
39 - add_action( 'wp_ajax_templately_pack_import_info', [ $this, 'import_info' ] );
40 - add_action( 'admin_init', [ $this, 'admin_init' ] );
39 + $this->add_ajax_action('import_settings', $this);
40 + $this->add_ajax_action('import_status', $this);
41 + $this->add_ajax_action('import', $this);
42 + $this->add_ajax_action('import_revert', $this);
43 + $this->add_ajax_action('import_info', $this);
44 + $this->add_ajax_action('import_close_feedback_modal', $this);
45 + $this->add_ajax_action('feedback_form', $this);
41 46
42 - if(isset($_GET['action']) && $_GET['action'] == 'templately_pack_import') {
47 + add_action('admin_init', [$this, 'admin_init']);
48 + // add_action('admin_notices', [$this, 'add_revert_button']);
49 +
50 + if(isset($_GET['action']) && ($_GET['action'] == 'templately_pack_import' || $_GET['action'] == 'templately_pack_import_status')) {
43 51 add_filter('wp_redirect', '__return_false', 999);
44 52 }
45 53
46 - if ( $this->dev_mode ) {
47 - add_filter( 'http_request_host_is_external', '__return_true' );
48 - add_filter( 'http_request_args', function ( $args ) {
54 + if ($this->dev_mode) {
55 + add_filter('http_request_host_is_external', '__return_true');
56 + add_filter('http_request_args', function ($args) {
49 57 $args['sslverify'] = false;
50 58
51 59 return $args;
52 - } );
60 + });
53 61 }
54 62 }
55 63
56 - public function admin_init(){
57 - if(get_option('templately_flush_rewrite_rules', false)){
64 + public function add_ajax_action($action, $object) {
65 + add_action("wp_ajax_templately_pack_$action", function() use ($action, $object) {
66 + // Check nonce
67 + $nonce = null;
68 + if(isset($_POST['nonce'])){
69 + $nonce = $_POST['nonce'];
70 + }
71 + if(isset($_GET['nonce'])){
72 + $nonce = $_GET['nonce'];
73 + }
74 + if (!$nonce || !wp_verify_nonce($nonce, 'templately_nonce')) {
75 + wp_send_json_error(['message' => __('Invalid nonce', 'templately')]);
76 + wp_die();
77 + }
78 +
79 + // Check user capability
80 + if (!current_user_can('install_plugins') || !current_user_can('install_themes')) {
81 + wp_send_json_error(['message' => __('Insufficient permissions', 'templately')]);
82 + wp_die();
83 + }
84 +
85 + // Call the actual handler method
86 + call_user_func([$object, $action]);
87 + });
88 + }
89 +
90 + public function admin_init() {
91 + if (get_option('templately_flush_rewrite_rules', false)) {
58 92 flush_rewrite_rules();
59 93 delete_option('templately_flush_rewrite_rules');
60 94 }
61 95 }
@@ -60,38 +94,186 @@
60 94 }
61 95 }
62 96
63 97 public function import_settings() {
64 - if( ! current_user_can( 'edit_posts' ) ) {
65 - // @todo show error in ui. Currently getting stack.
66 - wp_send_json_error( __( 'Unauthorized action.', 'templately' ) );
98 + $data = wp_unslash($_POST);
99 +
100 + update_option(self::SESSION_OPTION_KEY, $data);
101 +
102 + delete_option('templately_fsi_imported_list');
103 + delete_option('templately_fsi_log');
104 +
105 + wp_send_json_success([
106 + 'is_lightspeed' => !Helper::should_flush(),
107 + ]);
108 + }
109 +
110 + public function import_close_feedback_modal() {
111 + $return = null;
112 + if(isset($_GET['closeAction']) && $_GET['closeAction']){
113 + $review_email = isset($_POST['review-email']) ? sanitize_email($_POST['review-email']) : '';
114 + $pack_id = get_user_meta(get_current_user_id(), 'templately_fsi_pack_id', true);
115 +
116 + // Prepare the body of the request
117 + $body = json_encode([
118 + 'action' => $_GET['closeAction'],
119 + 'email' => $review_email,
120 + 'pack_id' => (int) $pack_id,
121 + ]);
122 +
123 + // Send the request to the API
124 + $response = wp_remote_post($this->get_api_url('v2', 'feedback/close'), [
125 + 'timeout' => 30,
126 + 'headers' => [
127 + 'Content-Type' => 'application/json',
128 + 'Authorization' => 'Bearer ' . $this->api_key,
129 + 'x-templately-ip' => Helper::get_ip(),
130 + 'x-templately-url' => home_url('/'),
131 + 'x-templately-version' => TEMPLATELY_VERSION,
132 + ],
133 + 'body' => $body,
134 + ]);
135 + $body = wp_remote_retrieve_body($response);
136 + $return = json_decode($body, true);
67 137 }
138 + update_user_meta(get_current_user_id(), 'templately_fsi_complete', 'done');
139 + wp_send_json_success($return);
140 + }
141 + public function feedback_form() {
142 + // Get data from $_POST
143 + $review_description = isset($_POST['review-description']) ? sanitize_textarea_field($_POST['review-description']) : '';
144 + $review_email = isset($_POST['review-email']) ? sanitize_email($_POST['review-email']) : '';
145 + $rating = isset($_POST['rating']) ? sanitize_text_field($_POST['rating']) : '';
146 + $pack_id = get_user_meta(get_current_user_id(), 'templately_fsi_pack_id', true);
68 147
69 - $data = wp_unslash( $_POST );
148 + // Prepare the body of the request
149 + $body = json_encode([
150 + 'description' => $review_description,
151 + 'email' => $review_email,
152 + 'rating' => (int) $rating,
153 + 'pack_id' => (int) $pack_id,
154 + ]);
70 155
71 - update_option( self::SESSION_OPTION_KEY, $data );
156 + // Send the request to the API
157 + $response = wp_remote_post($this->get_api_url('v2', 'feedback/store'), [
158 + 'timeout' => 30,
159 + 'headers' => [
160 + 'Content-Type' => 'application/json',
161 + 'Authorization' => 'Bearer ' . $this->api_key,
162 + 'x-templately-ip' => Helper::get_ip(),
163 + 'x-templately-url' => home_url('/'),
164 + 'x-templately-version' => TEMPLATELY_VERSION,
165 + ],
166 + 'body' => $body,
167 + ]);
72 168
73 - delete_transient('templately_fsi_log');
169 + if (is_wp_error($response)) {
170 + wp_send_json_error($response->get_error_message());
171 + }
74 172
75 - wp_send_json_success( [
76 - 'is_lightspeed' => !Helper::should_flush(),
77 - ] );
173 + $body = wp_remote_retrieve_body($response);
174 + $data = json_decode($body, true);
175 +
176 + if (wp_remote_retrieve_response_code($response) != 200 && wp_remote_retrieve_response_code($response) != 201) {
177 + if (isset($data['status'], $data['message']) && $data['status'] === 'error') {
178 + wp_send_json_error($data['message']);
179 + }
180 +
181 + wp_send_json_error('API request failed with response code ' . wp_remote_retrieve_response_code($response));
182 + }
183 +
184 + if (!isset($data['status']) || $data['status'] !== 'success') {
185 + wp_send_json_error('API response indicates failure.');
186 + }
187 +
188 + if (!isset($data['message'])) {
189 + wp_send_json_error('API response missing data.');
190 + }
191 +
192 + $result = $data['message'];
193 +
194 + wp_send_json_success($result);
78 195 }
79 196
80 - private function update_session_data( $data ): bool {
81 - $old_data = get_option( self::SESSION_OPTION_KEY, [] );
197 + private function update_session_data($data): bool {
198 + $old_data = $this->get_session_data();
82 199
83 - return update_option( self::SESSION_OPTION_KEY, wp_parse_args( $data, $old_data ) );
200 + return update_option(self::SESSION_OPTION_KEY, wp_parse_args($data, $old_data));
84 201 }
85 202
203 + protected function CallingFunctionName($id = null) {
204 + $return = 'unknown';
205 + $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3);
206 +
207 + // Check if the trace has at least three elements
208 + if (isset($trace[2])) {
209 + $final_call = $trace[2];
210 +
211 + // Check if 'class' and 'function' indexes exist
212 + if (isset($final_call['class']) && isset($final_call['function'])) {
213 + $return = "{$final_call['class']}::{$final_call['function']}";
214 + }
215 + else if(isset($final_call['function'])){
216 + $return = $final_call['function'];
217 + }
218 + if(!empty($id)){
219 + $return .= "::$id";
220 + }
221 + }
222 +
223 + // Return a default value if 'class' or 'function' index does not exist, or if the trace doesn't have at least three elements
224 + return $return;
225 + }
226 +
227 +
228 + public function get_progress($defaults = [], $unique_id = null) {
229 + $calling_class = $this->CallingFunctionName($unique_id);
230 + if(isset($this->request_params['progress'][$calling_class])){
231 + return $this->request_params['progress'][$calling_class];
232 + }
233 + return $defaults;
234 + }
235 +
236 +
237 + public function update_progress( $progress, $imported_data = null, $unique_id = null ): bool {
238 + $calling_class = $this->CallingFunctionName($unique_id);
239 + $old_data = $this->get_session_data();
240 +
241 + $new_data = [];
242 +
243 + if($progress !== null){
244 + $new_data['progress'] = [$calling_class => $progress];
245 + }
246 + if($imported_data !== null){
247 + $new_data['imported_data'] = $imported_data;
248 + }
249 +
250 + $this->request_params = $this->recursive_wp_parse_args( $new_data, $old_data );
251 + return update_option( self::SESSION_OPTION_KEY, $this->request_params );
252 + }
253 +
254 + public function recursive_wp_parse_args( $args, $defaults ) {
255 + $args = (array) $args;
256 + $defaults = (array) $defaults;
257 + $r = $defaults;
258 + foreach ( $args as $key => $value ) {
259 + if ( is_array( $value ) && isset( $r[ $key ] ) ) {
260 + $r[ $key ] = $this->recursive_wp_parse_args( $value, $r[ $key ] );
261 + } else {
262 + $r[ $key ] = $value;
263 + }
264 + }
265 + return $r;
266 + }
267 +
86 268 public function get_session_data(): array {
87 - $data = get_option( self::SESSION_OPTION_KEY, [] );
269 + $data = get_option(self::SESSION_OPTION_KEY, []);
88 270
89 271 $options = [];
90 272
91 273 if ( is_array( $data ) && ! empty( $data ) ) {
92 274 foreach ( $data as $key => $value ) {
93 - $json = json_decode( $value, true );
275 + $json = is_string($value) ? json_decode( $value, true ) : null;
94 276 $options[ $key ] = $json !== null ? $json : $value;
95 277 }
96 278 }
97 279
@@ -99,184 +281,195 @@
99 281 }
100 282
101 283 public function initialize_props() {
102 284 $data = $this->get_session_data();
103 - if(isset($data['session_id'])){
285 + if (isset($data['session_id'])) {
104 286 $this->session_id = $data['session_id'];
105 287 }
106 - if(isset($data['dir_path'])){
288 + if (isset($data['dir_path'])) {
107 289 $this->dir_path = $data['dir_path'];
108 290 }
109 - if(isset($data['download_key'])){
291 + if (isset($data['download_key'])) {
110 292 $this->download_key = $data['download_key'];
111 293 }
112 - if(isset($data['dependency_data'])){
294 + if (isset($data['dependency_data'])) {
113 295 $this->dependency_data = $data['dependency_data'];
114 296 }
115 -
116 297 }
117 298
118 299 private function clear_session_data(): bool {
119 - return delete_site_option( self::SESSION_OPTION_KEY );
300 + return delete_site_option(self::SESSION_OPTION_KEY);
120 301 }
121 302
122 - public function import() {
123 - if ( ! $this->dev_mode && ! wp_doing_ajax() ) {
124 - exit;
125 - }
303 + private function finishRequestHeaders() {
304 + header( "Cache-Control: no-store, no-cache" );
305 + // header( 'Content-Type: text/event-stream, charset=UTF-8' );
306 + // header( "Connection: Keep-Alive" );
126 307
127 - delete_transient( 'templately_fsi_log' );
308 + // Ignore user aborts and allow the script to run forever
309 + // (Use with caution, consider progress updates or timeouts)
310 + ignore_user_abort(true);
128 311
129 - if(Helper::should_flush()){
130 - header( "Cache-Control: no-store, no-cache" );
131 - header( 'Content-Type: text/event-stream, charset=UTF-8' );
132 - header( "Connection: Keep-Alive" );
133 - }
312 + // Time to run the import! Set no limit
313 + set_time_limit(0);
134 314
135 - if ( $GLOBALS['is_nginx'] ) {
315 +
316 + if ( !empty($GLOBALS['is_nginx']) ) {
136 317 header( 'X-Accel-Buffering: no' );
137 318 header( 'Content-Encoding: none' );
138 319 }
139 320
140 - register_shutdown_function( [ $this, 'register_shutdown' ] );
321 + // Send output as soon as possible during long-running process
322 + if (function_exists('fastcgi_finish_request')) {
323 + fastcgi_finish_request();
324 + } elseif (function_exists('litespeed_finish_request')) {
325 + litespeed_finish_request();
326 + } else {
327 + wp_ob_end_flush_all();
328 + }
329 + }
141 330
142 - // Ignore user aborts and allow the script
143 - // to run forever
144 - ignore_user_abort(true);
331 + public function import() {
332 + if ( ! $this->dev_mode && ! wp_doing_ajax() ) {
333 + exit;
334 + }
145 335
146 - // Time to run the import!
147 - set_time_limit( 0 );
336 + // delete_option( 'templately_fsi_log' );
148 337
338 + $this->sse_message( [
339 + 'type' => 'start',
340 + 'action' => 'eventLog',
341 + 'results' => __METHOD__ . '::' . __LINE__,
342 + ] );
149 343
344 + register_shutdown_function( [ $this, 'register_shutdown' ] );
150 345
151 - // // Don't run cron until the request finishes, if possible.
152 - // if ( PHP_VERSION_ID >= 70016 && function_exists( 'fastcgi_finish_request' ) ) {
153 - // fastcgi_finish_request();
154 - // } elseif ( function_exists( 'litespeed_finish_request' ) ) {
155 - // litespeed_finish_request();
156 - // }
157 - if(Helper::should_flush()){
158 - flush();
159 - wp_ob_end_flush_all();
160 - }
346 + $this->finishRequestHeaders();
161 347
162 348 try {
163 349 // TODO: Need to check if user is connected or not
164 350
165 351 $this->request_params = $this->get_session_data();
352 + $this->initialize_props();
353 + $this->add_revert_hooks();
354 + $progress = $this->request_params['progress'] ?? [];
166 355
167 - $_id = isset( $this->request_params['id'] ) ? (int) $this->request_params['id'] : null;
356 + $_id = isset($this->request_params['id']) ? (int) $this->request_params['id'] : null;
168 357
169 - if ( $_id === null ) {
170 - $this->throw( __( 'Invalid Pack ID.', 'templately' ) );
358 + if ($_id === null) {
359 + $this->throw(__('Invalid Pack ID.', 'templately'));
171 360 }
172 361
173 - if(!isset($_GET['part'])){
174 - $this->throw( __( 'Invalid request.', 'templately' ) );
175 - }
362 + if(empty($progress['download_zip'])){
363 + //clear previous revert backup
364 + $options = Utils::get_backup_options();
365 + foreach ($options as $key => $value) {
366 + delete_option("__templately_$key");
367 + }
176 368
177 - switch ($_GET['part']) {
178 - case 'download':
179 - /**
180 - * Check Writing Permission
181 - */
182 - $this->check_writing_permission();
369 + /**
370 + * Check Writing Permission
371 + */
372 + $this->check_writing_permission();
183 373
184 - /**
185 - * Download the zip
186 - */
187 - $this->download_zip( $_id );
374 + /**
375 + * Download the zip
376 + */
377 + $this->download_zip( $_id );
188 378
189 - /**
190 - * Reading Manifest File
191 - */
192 - $this->read_manifest();
379 + $progress['download_zip'] = true;
380 + $this->update_session_data( [
381 + 'progress' => $progress,
382 + ] );
383 + $this->sse_message( [
384 + 'type' => 'continue',
385 + 'action' => 'continue',
386 + 'info' => 'download_zip',
387 + 'results' => __METHOD__ . '::' . __LINE__,
388 + ] );
389 + exit;
390 + }
193 391
194 - /**
195 - * Version Check
196 - */
197 - if ( ! empty( $this->manifest['version'] ) && version_compare( $this->manifest['version'], $this->version, '>' ) ) {
198 - /**
199 - * FIXME: The message should be re-written (by content/support team).
200 - */
201 - $this->throw( __( 'Please update the templately plugin.', 'templately' ) );
202 - }
203 392
204 - /**
205 - * Checking & Installing Plugin Dependencies
206 - */
207 - $this->install_dependencies();
393 + if(empty($progress['download_dependencies'])){
394 + /**
395 + * Checking & Installing Plugin Dependencies
396 + */
397 + $this->install_dependencies();
208 398
209 - $this->sse_message( [
210 - 'type' => 'complete',
211 - 'action' => 'downloadComplete',
212 - 'results' => '',
213 - ] );
214 - break;
215 - case 'import':
216 - /**
217 - * Should Revert Old Data
218 - */
219 - $this->revert();
399 + $progress['download_dependencies'] = true;
400 + $this->update_session_data( [
401 + 'progress' => $progress,
402 + ] );
403 + $this->sse_message( [
404 + 'type' => 'continue',
405 + 'action' => 'continue',
406 + 'results' => 'download_dependencies',
407 + ] );
408 + exit;
409 + }
220 410
221 411
222 - $this->initialize_props();
412 + /**
413 + * Reading Manifest File
414 + */
415 + $this->read_manifest();
223 416
224 - /**
225 - * Reading Manifest File
226 - */
227 - $this->read_manifest();
417 + /**
418 + * Version Check
419 + */
420 + if ( ! empty( $this->manifest['version'] ) && version_compare( $this->manifest['version'], $this->version, '>' ) ) {
421 + /**
422 + * FIXME: The message should be re-written (by content/support team).
423 + */
424 + $this->throw( __( 'Please update the templately plugin.', 'templately' ) );
425 + }
228 426
229 - /**
230 - * Platform Based Templates Import
231 - */
232 - $this->start_content_import();
233 - break;
234 - default:
235 - $this->throw( __( 'Invalid request.', 'templately' ) );
236 - break;
237 - }
427 + /**
428 + * Should Revert Old Data
429 + */
430 + // $this->revert();
238 431
432 + /**
433 + * Platform Based Templates Import
434 + */
435 + $this->start_content_import();
436 +
239 437 } catch ( Exception $e ) {
240 438 $this->handle_import_status('failed', $e->getMessage());
241 - $this->sse_message( [
439 + $this->sse_message([
242 440 'action' => 'error',
243 441 'status' => 'error',
244 442 'type' => "error",
245 443 'title' => __("Oops!", "templately"),
246 444 'message' => $e->getMessage()
247 - ] );
445 + ]);
248 446 }
249 447
250 - if($_GET['part'] === 'import'){
448 + // if($_GET['part'] === 'import'){
251 449 // TODO: cleanup
252 450 $this->clear_session_data();
253 - }
451 + // }
254 452 }
255 453
256 454 public function import_status(){
257 - $log = get_transient( 'templately_fsi_log' );
258 - if(!empty($log) && is_array($log)){
259 - $lastLogIndex = isset($_GET['lastLogIndex']) ? (int) $_GET['lastLogIndex'] : 0;
455 + $log = get_option( 'templately_fsi_log' );
456 +
457 + if(!empty($log) && is_array($log) && isset($_GET['lastLogIndex'])){
458 + $lastLogIndex = (int) $_GET['lastLogIndex'];
260 459 $log = array_slice($log, $lastLogIndex);
261 -
262 - // delete log after complete
263 - $data = end($log);
264 - if(isset($data, $data['action']) && ($data['action'] === 'complete' || $data['action'] === 'downloadComplete' || $data['action'] === 'error')){
265 - delete_transient( 'templately_fsi_log' );
266 - }
267 460 }
268 - wp_send_json( ['log' => $log] );
461 + wp_send_json( ['count' => $log ? count($log) : 0, 'log' => $log] );
269 462 }
270 463
271 464 /**
272 465 * @throws Exception
273 466 */
274 - private function throw( $message, $code = 0 ) {
275 - if ( $this->dev_mode ) {
276 - error_log( print_r( $message, 1 ) );
467 + private function throw($message, $code = 0) {
468 + if ($this->dev_mode) {
469 + error_log(print_r($message, 1));
277 470 }
278 - throw new Exception( $message );
471 + throw new Exception($message);
279 472 }
280 473
281 474 /**
282 475 * @throws Exception
@@ -283,26 +476,26 @@
283 476 */
284 477 private function check_writing_permission() {
285 478 $upload_dir = wp_upload_dir();
286 479
287 - if ( ! is_writable( $upload_dir['basedir'] ) ) {
288 - $this->throw( __( 'Upload directory is not writable.', 'templately' ) );
480 + if (!is_writable($upload_dir['basedir'])) {
481 + $this->throw(__('Upload directory is not writable.', 'templately'));
289 482 }
290 483
291 - $this->tmp_dir = trailingslashit( $upload_dir['basedir'] ) . 'templately' . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR;
484 + $this->tmp_dir = trailingslashit($upload_dir['basedir']) . 'templately' . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR;
292 485
293 - if ( ! is_dir( $this->tmp_dir ) ) {
294 - wp_mkdir_p( $this->tmp_dir );
486 + if (!is_dir($this->tmp_dir)) {
487 + wp_mkdir_p($this->tmp_dir);
295 488 }
296 489
297 - $this->sse_log( 'writing_permission_check', __( 'Permission Passed', 'templately' ), 100 );
490 + $this->sse_log('writing_permission_check', __('Permission Passed', 'templately'), 100);
298 491 }
299 492
300 - private function get_api_url( $version, $end_point ): string {
493 + private function get_api_url($version, $end_point): string {
301 494 return $this->dev_mode ? "https://app.templately.dev/api/$version/" . $end_point : "https://app.templately.com/api/$version/" . $end_point;
302 495 }
303 496
304 - private function info_get_api_url( $id ): string {
497 + private function info_get_api_url($id): string {
305 498 return $this->dev_mode ? 'https://app.templately.dev/api/v1/import/info/pack/' . $id : 'https://app.templately.com/api/v1/import/info/pack/' . $id;
306 499 }
307 500
308 501 /**
@@ -308,9 +501,9 @@
308 501 /**
309 502 * @throws Exception
310 503 */
311 504 private function download_zip( $id ) {
312 - // $this->sse_log( 'download', __( 'Downloading Template Pack', 'templately' ), 1 );
505 + $this->sse_log( 'download', __( 'Downloading Template Pack', 'templately' ), 1 );
313 506 $response = wp_remote_get( $this->get_api_url( "v2", "import/pack/$id" ), [
314 507 'timeout' => 30,
315 508 'headers' => [
316 509 'Content-Type' => 'application/json',
@@ -315,34 +508,33 @@
315 508 'headers' => [
316 509 'Content-Type' => 'application/json',
317 510 'Authorization' => 'Bearer ' . $this->api_key,
318 511 'x-templately-ip' => Helper::get_ip(),
319 - 'x-templately-url' => home_url( '/' ),
512 + 'x-templately-url' => home_url('/'),
320 513 'x-templately-version' => TEMPLATELY_VERSION,
321 514 ]
322 - ] );
515 + ]);
323 516
324 - $response_code = wp_remote_retrieve_response_code( $response );
325 - $content_type = wp_remote_retrieve_header( $response, 'content-type' );
326 - $this->download_key = wp_remote_retrieve_header( $response, 'download-key' );
517 + $response_code = wp_remote_retrieve_response_code($response);
518 + $content_type = wp_remote_retrieve_header($response, 'content-type');
519 + $this->download_key = wp_remote_retrieve_header($response, 'download-key');
327 520
328 - if ( is_wp_error( $response ) ) {
329 - $this->throw( __( 'Template pack download failed', 'templately' ) . $response->get_error_message() );
330 - }
331 - else if ($response_code != 200) {
521 + if (is_wp_error($response)) {
522 + $this->throw(__('Template pack download failed', 'templately') . $response->get_error_message());
523 + } else if ($response_code != 200) {
332 524 if (strpos($content_type, 'application/json') !== false) {
333 525 // Retrieve Data from Response Body.
334 - $response_body = json_decode( wp_remote_retrieve_body( $response ), true );
526 + $response_body = json_decode(wp_remote_retrieve_body($response), true);
335 527
336 528 // If the response body is JSON and it contains an error, throw an exception with the error message
337 529 if (isset($response_body['status']) && $response_body['status'] === 'error') {
338 - $this->throw( $response_body['message'] );
530 + $this->throw($response_body['message']);
339 531 }
340 532 }
341 - $this->throw( __( 'Template pack download failed with response code: ', 'templately' ) . $response_code );
533 + $this->throw(__('Template pack download failed with response code: ', 'templately') . $response_code);
342 534 }
343 535
344 - $this->sse_log( 'download', __( 'Template is getting ready', 'templately' ), 57 );
536 + $this->sse_log('download', __('Template is getting ready', 'templately'), 57);
345 537
346 538 $session_id = uniqid();
347 539 $this->dir_path = $this->tmp_dir . $session_id . DIRECTORY_SEPARATOR;
348 540 $this->filePath = $this->tmp_dir . "{$session_id}.zip";
@@ -347,20 +539,20 @@
347 539 $this->dir_path = $this->tmp_dir . $session_id . DIRECTORY_SEPARATOR;
348 540 $this->filePath = $this->tmp_dir . "{$session_id}.zip";
349 541 $this->session_id = $session_id;
350 542
351 - $this->update_session_data( [
543 + $this->update_session_data([
352 544 'session_id' => $this->session_id,
353 545 'dir_path' => $this->dir_path,
354 546 'download_key' => $this->download_key,
355 - ] );
547 + ]);
356 548
357 - if ( file_put_contents( $this->filePath, $response['body'] ) ) { // phpcs:ignore
358 - $this->sse_log( 'download', __( 'Template is getting ready', 'templately' ), 100 );
549 + if (file_put_contents($this->filePath, $response['body'])) { // phpcs:ignore
550 + $this->sse_log('download', __('Template is getting ready', 'templately'), 100);
359 551
360 552 $this->unzip();
361 553 } else {
362 - $this->throw( __( 'Downloading Failed. Please try again', 'templately' ) );
554 + $this->throw(__('Downloading Failed. Please try again', 'templately'));
363 555 }
364 556 }
365 557
366 558 /**
@@ -366,32 +558,31 @@
366 558 /**
367 559 * @throws Exception
368 560 */
369 561 protected function unzip() {
370 - if ( ! WP_Filesystem() ) {
371 - $this->throw( __( 'WP_Filesystem cannot be initialized', 'templately' ) );
562 + if (!WP_Filesystem()) {
563 + $this->throw(__('WP_Filesystem cannot be initialized', 'templately'));
372 564 }
373 565
374 - $unzip = unzip_file( $this->filePath, $this->dir_path );
375 - if ( is_wp_error( $unzip ) ) {
376 - $unzip = $this->unzip_file( $this->filePath, $this->dir_path );
566 + $unzip = unzip_file($this->filePath, $this->dir_path);
567 + if (is_wp_error($unzip)) {
568 + $unzip = $this->unzip_file($this->filePath, $this->dir_path);
377 569 }
378 570
379 - if ( is_wp_error( $unzip ) ) {
571 + if (is_wp_error($unzip)) {
380 572 $error = $unzip->get_error_message();
381 - if(empty($error)){
573 + if (empty($error)) {
382 574 // Generic error message
383 - Helper::log( $unzip );
575 + Helper::log($unzip);
384 576 $error_message = sprintf(__("It seems we're experiencing technical difficulties. Please try again or contact <a href='%s' target='_blank'>support</a>.", "templately"), 'https://wpdeveloper.com/support');
385 - $this->throw( $error_message );
577 + $this->throw($error_message);
578 + } else {
579 + $this->throw($unzip->get_error_message());
386 580 }
387 - else{
388 - $this->throw( $unzip->get_error_message() );
389 - }
390 581 }
391 582
392 - if ( $unzip ) {
393 - unlink( $this->filePath );
583 + if ($unzip) {
584 + unlink($this->filePath);
394 585 }
395 586 }
396 587
397 588 /**
@@ -426,15 +617,15 @@
426 617 /**
427 618 * @throws Exception
428 619 */
429 620 private function read_manifest() {
430 - $manifest_content = file_get_contents( $this->dir_path . DIRECTORY_SEPARATOR . 'manifest.json' );
431 - if ( empty( $manifest_content ) ) {
432 - $this->throw( __( 'Cannot be imported, as the manifest file is corrupted', 'templately' ) );
621 + $manifest_content = file_get_contents($this->dir_path . DIRECTORY_SEPARATOR . 'manifest.json');
622 + if (empty($manifest_content)) {
623 + $this->throw(__('Cannot be imported, as the manifest file is corrupted', 'templately'));
433 624 }
434 625
435 - $this->manifest = json_decode( $manifest_content, true );
436 - $this->removeLog( 'temp' );
626 + $this->manifest = json_decode($manifest_content, true);
627 + $this->removeLog('temp');
437 628
438 629 // TODO: Read & Broadcast the LOG for waiting list
439 630 // $this->sse_log( 'plugin', 'Installing required plugins', '--', 'updateLog', 'processing' );
440 631 // // $this->sse_log( 'extra-content', 'Import Extra Contents (i.e: Forms)', '--', 'updateLog', 'processing' );
@@ -444,33 +635,38 @@
444 635 // $this->sse_log( 'finalize', 'Finalizing Your Imports', '--', 'updateLog', 'processing' );
445 636 }
446 637
447 638 private function skipped_plugin(): bool {
448 - return empty( $this->request_params['plugins'] ) || ! is_array( $this->request_params['plugins'] );
639 + return empty($this->request_params['plugins']) || !is_array($this->request_params['plugins']);
449 640 }
450 641
451 642 private function install_dependencies() {
452 - $allowed_themes = ['hello-elementor', 'twentytwentyfour'];
643 + $progress = $this->request_params['progress'] ?? [];
453 644
454 - if ( ! empty( $this->request_params['theme'] ) && is_array( $this->request_params['theme'] ) ) {
645 + if ( empty($progress['theme_dependency']) && ! empty( $this->request_params['theme'] ) && is_array( $this->request_params['theme'] ) ) {
455 646 // activate theme
456 647 $theme = $this->request_params['theme'];
457 648
458 - $this->before_install_hook();
649 + // $this->before_install_hook();
459 650
460 - if (isset($theme['stylesheet']) && in_array($theme['stylesheet'], $allowed_themes)) {
651 + if (isset($theme['stylesheet'])) {
461 652 // do_action('before_theme_activation', $theme); // Trigger action before theme activation
462 - $this->sse_log( 'theme', 'Installing and activating theme: ' . $theme['name'], 0 );
463 - $plugin_status = Installer::get_instance()->install_and_activate_theme( $theme['stylesheet'] );
653 + $this->sse_log('theme', 'Installing and activating theme: ' . $theme['name'], 0);
654 + if (!get_option("__templately_stylesheet")) {
655 + $stylesheet = get_option('stylesheet');
656 + add_option("__templately_stylesheet", $stylesheet, '', 'no');
657 + }
464 658
659 + $plugin_status = Installer::get_instance()->install_and_activate_theme($theme['stylesheet']);
660 +
465 661 if (!$plugin_status['success']) {
466 - $this->sse_message( [
662 + $this->sse_message([
467 663 'action' => 'updateLog',
468 664 'status' => 'error',
469 665 'message' => "Failed to activate theme: " . $theme['name'],
470 666 'type' => "theme",
471 667 'progress' => 0
472 - ] );
668 + ]);
473 669 $this->dependency_data['theme'] = [
474 670 'success' => false,
475 671 'name' => $theme['name'],
476 672 'slug' => $theme['stylesheet'],
@@ -475,18 +671,21 @@
475 671 'name' => $theme['name'],
476 672 'slug' => $theme['stylesheet'],
477 673 'message' => $plugin_status['message'] ?? ''
478 674 ];
675 + $this->update_session_data( [
676 + 'dependency_data' => $this->dependency_data,
677 + ] );
479 678 } else {
480 679 // do_action('after_theme_activation', $theme); // Trigger action after theme activation
481 680
482 - $this->sse_message( [
681 + $this->sse_message([
483 682 'action' => 'updateLog',
484 683 'status' => 'complete',
485 684 'message' => "Activated theme: " . $theme['name'],
486 685 'type' => "theme",
487 686 'progress' => 100
488 - ] );
687 + ]);
489 688 $this->dependency_data['theme'] = [
490 689 'success' => true,
491 690 'name' => $theme['name'],
492 691 'slug' => $theme['stylesheet'],
@@ -491,44 +690,65 @@
491 690 'name' => $theme['name'],
492 691 'slug' => $theme['stylesheet'],
493 692 'message' => $plugin_status['message'] ?? ''
494 693 ];
694 + $this->update_session_data( [
695 + 'dependency_data' => $this->dependency_data,
696 + ] );
697 +
698 + $progress['theme_dependency'] = true;
699 + $this->update_session_data( [
700 + 'progress' => $progress,
701 + ] );
495 702 }
703 +
704 + // If it's not the last item, send the SSE message and exit
705 + $this->sse_message( [
706 + 'type' => 'continue',
707 + 'action' => 'continue',
708 + 'results' => __METHOD__ . '::' . __LINE__,
709 + ] );
710 + exit;
496 711 }
497 712
498 - $this->after_install_hook();
713 + // $this->after_install_hook();
499 714 }
500 - else {
715 + else if(empty($progress['theme_dependency'])) {
501 716 $this->removeLog( 'theme' );
502 717 }
503 718 if ( ! empty( $this->request_params['plugins'] ) && is_array( $this->request_params['plugins'] ) ) {
504 719 // $this->sse_log( 'plugin', 'Installing Plugins', 1 );
505 - $total_plugin = count( $this->request_params['plugins'] );
720 + $total_plugin = count($this->request_params['plugins']);
506 721
507 - $total_plugin_installed = $total_plugin;
508 - $_installed_plugins = 0;
722 + // $total_plugin_installed = $total_plugin;
723 + $_installed_plugins = $this->dependency_data['_installed_plugins'] ?? 0;
724 + $progress['plugin_dependency'] = $progress['plugin_dependency'] ?? [];
509 725
510 - $this->before_install_hook();
726 + // $this->before_install_hook();
511 727
512 728 foreach ( $this->request_params['plugins'] as $dependency ) {
729 + if(in_array($dependency['plugin_original_slug'], $progress['plugin_dependency'])){
730 + continue;
731 + }
732 + $_dependency = $dependency;
513 733 $this->sse_log( 'plugin', 'Installing required plugins: ' . $dependency['name'], floor( ( 100 * $_installed_plugins / $total_plugin ) ) );
514 734
515 735 $dependency['slug'] = $dependency['plugin_original_slug'];
516 - $plugin_status = Installer::get_instance()->install( $dependency );
736 + $plugin_status = Installer::get_instance()->install($dependency);
517 737
518 - if ( ! $plugin_status['success'] ) {
519 - $this->sse_message( [
738 + if (!$plugin_status['success']) {
739 + $this->sse_message([
520 740 'position' => 'plugin',
521 741 'action' => 'updateLog',
522 742 'status' => 'error',
523 - 'message' => 'Installation Failed: ' . $dependency['name'] . ' (' . ( $plugin_status['message'] ?? '' ) . ')',
743 + 'message' => 'Installation Failed: ' . $dependency['name'] . ' (' . ($plugin_status['message'] ?? '') . ')',
524 744 'type' => "plugin_{$dependency['plugin_original_slug']}",
525 745 'progress' => 0
526 - ] );
746 + ]);
527 747
528 - if(isset($dependency['mustHave']) && $dependency['mustHave']){
529 - $this->removeLog( 'plugin' );
530 - $this->throw( 'Installation Failed: ' . $dependency['name'] . ' (' . ( $plugin_status['message'] ?? '' ) . ')' );
748 + if (isset($dependency['mustHave']) && $dependency['mustHave']) {
749 + $this->removeLog('plugin');
750 + $this->throw('Installation Failed: ' . $dependency['name'] . ' (' . ($plugin_status['message'] ?? '') . ')');
531 751 }
532 752
533 753 $this->dependency_data['plugins']['failed'][] = [
534 754 'name' => $dependency['name'],
@@ -537,31 +757,52 @@
537 757 'message' => $plugin_status['message'] ?? ''
538 758 ];
539 759 } else {
540 760 $_installed_plugins++;
541 - $total_plugin_installed--;
761 + // $total_plugin_installed--;
762 +
763 + $this->dependency_data['_installed_plugins'] = $_installed_plugins;
542 764 }
765 +
766 + $this->update_session_data( [
767 + 'dependency_data' => $this->dependency_data,
768 + ] );
769 +
770 + $progress['plugin_dependency'][] = $dependency['slug'];
771 + $this->update_session_data( [
772 + 'progress' => $progress,
773 + ] );
774 +
775 + // If it's not the last item, send the SSE message and exit
776 + if( end($this->request_params['plugins']) !== $_dependency ) {
777 + $this->sse_message( [
778 + 'type' => 'continue',
779 + 'action' => 'continue',
780 + 'results' => __METHOD__ . '::' . __LINE__,
781 + ] );
782 + exit;
783 + }
543 784 }
544 785
545 - $this->after_install_hook();
786 + // $this->after_install_hook();
546 787
547 - $this->sse_message( [
788 + $this->sse_message([
548 789 'action' => 'updateLog',
549 790 'status' => 'complete',
550 791 'message' => "Installed required plugins ($_installed_plugins/$total_plugin)",
551 792 'type' => "plugin",
552 793 'progress' => 100
553 - ] );
794 + ]);
554 795 $this->dependency_data['plugins']['total'] = $total_plugin;
555 796 $this->dependency_data['plugins']['succeed'] = $_installed_plugins;
556 797 } else {
557 - $this->removeLog( 'plugin' );
798 + $this->removeLog('plugin');
558 799 }
559 800
560 801
561 - $this->update_session_data( [
802 + $this->update_session_data([
562 803 'dependency_data' => json_encode($this->dependency_data),
563 - ] );
804 + ]);
564 805 // $this->sse_log( 'plugin', 'Skipped Installing Plugins', '--', 'updateLog', 'skipped' );
565 806 }
566 807
567 808 private function before_install_hook() {
@@ -587,46 +828,54 @@
587 828 private function start_content_import() {
588 829 add_filter('upload_mimes', array($this, 'allow_svg_upload'));
589 830 add_filter('elementor/files/allow_unfiltered_upload', '__return_true');
590 831
591 - $import = new Import( $this );
832 + $import = new Import($this);
592 833 $imported_data = $import->run();
593 834
594 - $this->handle_import_status('success');
835 + $import_status = $this->handle_import_status('success');
595 836
596 837 update_option('templately_flush_rewrite_rules', true, false);
597 838
598 - $this->sse_message( [
839 + $this->sse_message([
599 840 'type' => 'complete',
600 841 'action' => 'complete',
601 - 'results' => $this->normalize_imported_data( $imported_data )
602 - ] );
842 + 'results' => $this->normalize_imported_data($imported_data)
843 + ]);
844 +
845 + update_user_meta(get_current_user_id(), 'templately_fsi_pack_id', $this->request_params["id"]);
846 + if(!empty($import_status['hasFeedback'])){
847 + update_user_meta(get_current_user_id(), 'templately_fsi_complete', 'done');
848 + }
849 + else{
850 + update_user_meta(get_current_user_id(), 'templately_fsi_complete', true);
851 + }
603 852 }
604 853
605 - private function normalize_imported_data( $data ) {
606 - $templates = ! empty( $data['templates']['succeed'] ) ? count( $data['templates']['succeed'] ) : 0;
607 - $template_types = ! empty( $data['templates']['template_types'] ) ? $data['templates']['template_types'] : [];
854 + private function normalize_imported_data($data) {
855 + $templates = !empty($data['templates']['succeed']) ? count($data['templates']['succeed']) : 0;
856 + $template_types = !empty($data['templates']['template_types']) ? $data['templates']['template_types'] : [];
608 857
609 858 $post_types = [];
610 859 $content_templates = [];
611 - if ( ! empty( $data['content'] ) && is_array( $data['content'] ) ) {
612 - foreach ( $data['content'] as $type => $type_data ) {
613 - $content_templates[ $type ] = ! empty( $type_data['succeed'] ) ? count( $type_data['succeed'] ) : 0;
860 + if (!empty($data['content']) && is_array($data['content'])) {
861 + foreach ($data['content'] as $type => $type_data) {
862 + $content_templates[$type] = !empty($type_data['succeed']) ? count($type_data['succeed']) : 0;
614 863 $post_types[] = $this->get_post_type_label_by_slug($type);
615 864 }
616 865 }
617 866
618 867 $contents = [];
619 - if ( ! empty( $data['wp-content'] ) && is_array( $data['wp-content'] ) ) {
620 - foreach ( $data['wp-content'] as $type => $type_data ) {
621 - $contents[ $type ] = ! empty( $type_data['succeed'] ) ? count( $type_data['succeed'] ) : 0;
622 - if(!in_array($type, ['wp_navigation', 'nav_menu_item'])){
868 + if (!empty($data['wp-content']) && is_array($data['wp-content'])) {
869 + foreach ($data['wp-content'] as $type => $type_data) {
870 + $contents[$type] = !empty($type_data['succeed']) ? count($type_data['succeed']) : 0;
871 + if (!in_array($type, ['wp_navigation', 'nav_menu_item'])) {
623 872 $post_types[] = $this->get_post_type_label_by_slug($type);
624 873 }
625 874 }
626 875 }
627 876
628 - Helper::log( $data );
877 + Helper::log($data);
629 878
630 879 return [
631 880 'templates' => $templates,
632 881 'contents' => $content_templates,
@@ -647,12 +896,12 @@
647 896 // // TODO: Implement the Revert Process.
648 897 // }
649 898 }
650 899
651 - public function redirect_for_archives( $link, $post_id ) {
652 - $archive_settings = get_option( 'templately_post_archive' );
653 - if ( ! empty( $archive_settings ) && intval( $archive_settings['post_id'] ) === intval( $post_id ) ) {
654 - $link = str_replace( $post_id, $archive_settings['archive_id'], $link );
900 + public function redirect_for_archives($link, $post_id) {
901 + $archive_settings = get_option('templately_post_archive');
902 + if (!empty($archive_settings) && intval($archive_settings['post_id']) === intval($post_id)) {
903 + $link = str_replace($post_id, $archive_settings['archive_id'], $link);
655 904 }
656 905
657 906 return $link;
658 907 }
@@ -662,9 +911,9 @@
662 911 $mimes['svg'] = 'image/svg+xml';
663 912 return $mimes;
664 913 }
665 914
666 - public function register_shutdown(){
915 + public function register_shutdown() {
667 916 $status = connection_status();
668 917 $last_error = error_get_last();
669 918 if ($status != CONNECTION_NORMAL && $last_error && $last_error['type'] === E_ERROR) {
670 919 if ((defined('WP_DEBUG') && WP_DEBUG || defined('TEMPLATELY_EVENT_LOG') && TEMPLATELY_EVENT_LOG) && !empty($last_error['message'])) {
@@ -682,9 +931,9 @@
682 931
683 932
684 933 $this->handle_import_status('failed', $error_message);
685 934 // Handle the error, e.g. log it or display a message to the user
686 - $this->sse_message( [
935 + $this->sse_message([
687 936 'action' => 'error',
688 937 'status' => 'error',
689 938 'type' => "error",
690 939 'title' => __("Oops!", "templately"),
@@ -690,14 +939,14 @@
690 939 'title' => __("Oops!", "templately"),
691 940 'message' => $error_message,
692 941 // 'position' => 'plugin',
693 942 // 'progress' => '--',
694 - ] );
943 + ]);
695 944 }
696 945
697 - $this->debug_log( "Shutdown:....." );
698 - $this->debug_log( "connection_status: " . $this->getConnectionStatusText() );
699 - $this->debug_log( $last_error );
946 + $this->debug_log("Shutdown:.....");
947 + $this->debug_log("connection_status: " . $this->getConnectionStatusText());
948 + $this->debug_log($last_error);
700 949 }
701 950
702 951 public function handle_import_status($status, $description = '') {
703 952 if ($this->is_import_status_handled) {
@@ -708,14 +957,14 @@
708 957
709 958 $download_key = $this->download_key;
710 959
711 960 $headers = [
712 - 'Content-Type' => 'application/json',
961 + 'Content-Type' => 'application/json',
713 962 'Authorization' => 'Bearer ' . $this->api_key,
714 963 'download_key' => $download_key,
715 964 'download-key' => $download_key,
716 965 'x-templately-ip' => Helper::get_ip(),
717 - 'x-templately-url' => home_url( '/' ),
966 + 'x-templately-url' => home_url('/'),
718 967 ];
719 968
720 969 $args = [
721 970 'headers' => $headers,
@@ -722,13 +971,13 @@
722 971 ];
723 972
724 973
725 974 if ($status === 'success') {
726 - $url = $this->get_api_url( "v1", 'import/success');
975 + $url = $this->get_api_url("v1", 'import/success');
727 976 $args['body'] = json_encode(['type' => 'pack']);
728 977 $response = wp_remote_post($url, $args);
729 978 } elseif ($status === 'failed') {
730 - $url = $this->get_api_url( "v1", 'import/failed');
979 + $url = $this->get_api_url("v1", 'import/failed');
731 980 $args['body'] = json_encode(['type' => 'pack', 'description' => $description ?: "Something Went wrong....."]);
732 981 $response = wp_remote_post($url, $args);
733 982 }
734 983
@@ -739,10 +988,11 @@
739 988 Helper::log($response->get_error_message());
740 989 } else {
741 990 // Handle success
742 991 $body = wp_remote_retrieve_body($response);
992 + $data = json_decode($body, true);
743 993 // Do something with $body
744 - return $body;
994 + return $data;
745 995 }
746 996
747 997 return null;
748 998 }
@@ -762,41 +1012,41 @@
762 1012 }
763 1013
764 1014 protected function get_post_type_label_by_slug($slug) {
765 1015 $post_type_obj = get_post_type_object($slug);
766 - if($post_type_obj) {
1016 + if ($post_type_obj) {
767 1017 return $post_type_obj->label;
768 1018 }
769 1019 return null;
770 1020 }
771 1021
772 - public function import_info(){
1022 + public function import_info() {
773 1023
774 1024 $platform = isset($_GET['platform']) ? $_GET['platform'] : 'elementor';
775 1025 $id = isset($_GET['id']) ? intval($_GET['id']) : 0;
776 1026
777 - $response = wp_remote_get( $this->info_get_api_url($id), [
1027 + $response = wp_remote_get($this->info_get_api_url($id), [
778 1028 'timeout' => 30,
779 1029 'headers' => [
780 1030 'Authorization' => 'Bearer ' . $this->api_key,
781 1031 'x-templately-ip' => Helper::get_ip(),
782 - 'x-templately-url' => home_url( '/' ),
1032 + 'x-templately-url' => home_url('/'),
783 1033 'x-templately-version' => TEMPLATELY_VERSION,
784 1034 ]
785 - ] );
1035 + ]);
786 1036
787 - if( is_wp_error( $response ) ){
788 - wp_send_json_error( $response->get_error_message() );
1037 + if (is_wp_error($response)) {
1038 + wp_send_json_error($response->get_error_message());
789 1039 return;
790 1040 }
791 1041 // If the response code is not 200, return the error message
792 - if( wp_remote_retrieve_response_code( $response ) != 200 ){
793 - wp_send_json_error( json_decode(wp_remote_retrieve_body( $response )) );
1042 + if (wp_remote_retrieve_response_code($response) != 200) {
1043 + wp_send_json_error(json_decode(wp_remote_retrieve_body($response)));
794 1044 return;
795 1045 }
796 1046 // If the response body is JSON and it contains an error, return the error message
797 1047 // Retrieve Data from Response Body.
798 - $body = wp_remote_retrieve_body( $response );
1048 + $body = wp_remote_retrieve_body($response);
799 1049 $data = json_decode($body, true);
800 1050
801 1051 if (isset($data['error'])) {
802 1052 wp_send_json_error($data['error']);
@@ -802,12 +1052,12 @@
802 1052 wp_send_json_error($data['error']);
803 1053 return;
804 1054 }
805 1055
806 - if(isset($data['data']['manifest'])){
1056 + if (isset($data['data']['manifest'])) {
807 1057 $data['data']['manifest'] = json_decode($data['data']['manifest'], true);
808 1058 }
809 - if(isset($data['data']['settings'])){
1059 + if (isset($data['data']['settings'])) {
810 1060 $data['data']['settings'] = json_decode($data['data']['settings'], true);
811 1061 }
812 1062
813 1063 // Return the response body
@@ -813,5 +1063,177 @@
813 1063 // Return the response body
814 1064 wp_send_json($data);
815 1065 }
816 1066
817 -}
1067 + public function update_imported_list($type, $id) {
1068 + $imported_list = get_option('templately_fsi_imported_list', []);
1069 + $imported_list[$type][] = $id;
1070 + update_option('templately_fsi_imported_list', $imported_list);
1071 + }
1072 +
1073 + /**
1074 + *
1075 + *
1076 + * @return void
1077 + */
1078 + protected function add_revert_hooks() {
1079 + add_action('wp_insert_post', function ($post_id) {
1080 + $this->update_imported_list('posts', $post_id);
1081 + });
1082 + add_action('add_attachment', function ($post_id) {
1083 + $this->update_imported_list('attachment', $post_id);
1084 + });
1085 + add_action('created_term', function ($term_id, $tt_id, $taxonomy, $args) {
1086 + $this->update_imported_list('term', [$term_id, $taxonomy]);
1087 + }, 10, 4);
1088 + add_action('registered_taxonomy', function ($taxonomy, $object_type, $taxonomy_object) {
1089 + $this->update_imported_list('taxonomy', $taxonomy);
1090 + }, 10, 3);
1091 + add_action('fluentform/form_imported', function ($formId){
1092 + $this->update_imported_list('fluentform', $formId);
1093 + }, 10, 1);
1094 + }
1095 +
1096 + public static function has_revert(){
1097 + $options = Utils::get_backup_options();
1098 + $imported_list = get_option('templately_fsi_imported_list', []);
1099 + if(!empty($options) || !empty($imported_list)){
1100 + return true;
1101 + }
1102 + return false;
1103 + }
1104 +
1105 + public function import_revert() {
1106 +
1107 + // // Get the nonce value from the request (usually from $_POST or $_GET)
1108 + // $received_nonce = isset($_REQUEST['_wpnonce']) ? $_REQUEST['_wpnonce'] : '';
1109 +
1110 + // // Verify the nonce using wp_verify_nonce()
1111 + // $verified = wp_verify_nonce($received_nonce, 'templately_pack_import_revert_nonce');
1112 +
1113 + // if (!$verified) {
1114 + // wp_send_json_error("Nonce not verified.");
1115 + // }
1116 +
1117 + $option_active = null;
1118 + $options_deleted = false;
1119 + $imported_list_deleted = false;
1120 + $options = Utils::get_backup_options();
1121 + $status_args = [ 'post_type' => 'templately_library' ];
1122 + $all_post_url = admin_url(add_query_arg( $status_args, 'edit.php' ));
1123 + // wp_send_json_success([$options]);
1124 +
1125 + if(class_exists('Elementor\Plugin')){
1126 + $kits_manager = Plugin::$instance->kits_manager;
1127 + $option_active = $kits_manager::OPTION_ACTIVE;
1128 + $kit = $kits_manager->get_active_kit();
1129 +
1130 + if ( ! $kit->get_id() ) {
1131 + $kit = $kits_manager->create_default();
1132 + update_option( $kits_manager::OPTION_ACTIVE, $kit );
1133 + }
1134 + }
1135 +
1136 +
1137 + if (!empty($options) && is_array($options)) {
1138 + foreach ($options as $key => $value) {
1139 + if ('stylesheet' === $key) {
1140 + if (get_option('stylesheet') !== $value) {
1141 + switch_theme($value);
1142 + }
1143 + } else if($option_active === $key && class_exists('Elementor\Plugin')) {
1144 + $kits_manager->revert( (int) $kits_manager->get_active_id(), (int) $value, 0 );
1145 + $kit = $kits_manager->get_active_kit();
1146 + $settings = $kit->get_data('settings');
1147 + if ( isset( $settings['site_logo'] ) ) {
1148 + set_theme_mod( 'custom_logo', $settings['site_logo']['id'] );
1149 + }
1150 + } else {
1151 + update_option($key, $value);
1152 + }
1153 + delete_option("__templately_$key");
1154 + $options_deleted = true;
1155 + }
1156 + }
1157 +
1158 + $imported_list = get_option('templately_fsi_imported_list', []);
1159 + if (!empty($imported_list) && is_array($imported_list)) {
1160 + $_GET['force_delete_kit'] = 1; // Fallback GET Ready!
1161 + foreach ($imported_list as $type => $list) {
1162 + if (empty($list) || !is_array($list)) {
1163 + continue;
1164 + }
1165 + // Loop through each item ID and delete it
1166 + foreach ($list as $key => $item_id) {
1167 + switch ($type) {
1168 + case 'posts':
1169 + // making sure default kit don't get deleted.
1170 + if($option_active && isset($options[$option_active]) && $options[$option_active] == $item_id){
1171 + break;
1172 + }
1173 + wp_delete_post($item_id, true); // Set true for permanent deletion
1174 + break;
1175 + case 'attachment':
1176 + wp_delete_attachment($item_id, true); // Set true for permanent deletion
1177 + break;
1178 + case 'term':
1179 + list($term_id, $taxonomy) = $item_id;
1180 + wp_delete_term($term_id, $taxonomy); // Use corresponding taxonomy
1181 + break;
1182 + case 'taxonomy':
1183 + // Taxonomies cannot be directly deleted. Consider de-registering it.
1184 + break;
1185 + case 'fluentform':
1186 + if(class_exists('\FluentForm\App\Models\Form')){
1187 + \FluentForm\App\Models\Form::remove($item_id);
1188 + }
1189 + break;
1190 + }
1191 + }
1192 + }
1193 +
1194 + $imported_list_deleted = true;
1195 + delete_option('templately_fsi_imported_list');
1196 + }
1197 +
1198 +
1199 + if($options_deleted || $imported_list_deleted){
1200 + sleep(5);
1201 + wp_send_json_success([ 'options' => $options_deleted, 'imported_list' => $imported_list_deleted, 'site_url' => home_url(), 'redirect' => $all_post_url ]);
1202 + }
1203 +
1204 + wp_send_json_error([ 'options' => $options_deleted, 'imported_list' => $imported_list_deleted, 'site_url' => home_url() ]);
1205 + }
1206 +
1207 + /**
1208 + * Adds "Import" button on module list page
1209 + */
1210 + public function add_revert_button() {
1211 + $screen = get_current_screen();
1212 + // Not our post type, exit earlier
1213 + // You can remove this if condition if you don't have any specific post type to restrict to.
1214 + if ('templately_library' != $screen->post_type) {
1215 + return;
1216 + }
1217 +
1218 + // Generate a nonce with a unique action name for security
1219 + $revert_nonce = wp_create_nonce('templately_pack_import_revert_nonce');
1220 +
1221 + // Build the URL with the nonce
1222 + $revert_url = add_query_arg('action', 'templately_pack_import_revert', admin_url('admin-ajax.php'));
1223 + $revert_url = add_query_arg('_wpnonce', $revert_nonce, $revert_url);
1224 + ?>
1225 +
1226 + <div class="templately-fsi-revert-wrapper clearfix" style="clear: both; background: #fff; padding: 20px; display: none;">
1227 + <div class="templately-fsi-revert-notice__content">
1228 + <h3>Revert to previous website</h3>
1229 +
1230 + <p>This usually takes a few moments. Please don’t close the window until the process in finished.</p>
1231 +
1232 + <div class="templately-fsi-revert-notice__actions">
1233 + <a href="<?php echo $revert_url;?>" class="button"><span>Revert Now</span></a>
1234 + </div>
1235 + </div>
1236 + </div>
1237 + <?php
1238 + }
1239 +}