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.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 3.1.10 All 111 releases
← All changes | includes/Core/Importer/FullSiteImport.php +820 -278 3.0.43.1.9 View file →
@@ -1,10 +1,12 @@
1 1 <?php
2 2
3 3 namespace Templately\Core\Importer;
4 4
5 -use EbStyleHandler;
5 +use Elementor\Plugin;
6 +use Error;
6 7 use Exception;
8 +use Templately\Core\Importer\Utils\Utils;
7 9 use Templately\Utils\Base;
8 10 use Templately\Utils\Helper;
9 11 use Templately\Utils\Installer;
10 12 use Templately\Utils\Options;
@@ -18,8 +20,9 @@
18 20
19 21 private $version = '1.0.0';
20 22
21 23 public $session_id;
24 + public $download_key;
22 25 public $dir_path;
23 26 protected $filePath;
24 27 protected $tmp_dir = null;
25 28 protected $dev_mode = false;
@@ -26,58 +29,251 @@
26 29 protected $api_key = '';
27 30 public $request_params = [];
28 31 protected $documents_data = [];
29 32 protected $dependency_data = [];
33 + private $is_import_status_handled = false;
30 34
31 35 public function __construct() {
32 - $this->dev_mode = defined( 'TEMPLATELY_DEV' ) && TEMPLATELY_DEV;
33 - $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');
34 38
35 - add_action( 'wp_ajax_templately_import_settings', [ $this, 'import_settings' ] );
36 - add_action( 'wp_ajax_templately_pack_import', [ $this, 'import' ] );
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);
37 46
38 - if ( $this->dev_mode ) {
39 - add_filter( 'http_request_host_is_external', '__return_true' );
40 - add_filter( 'http_request_args', function ( $args ) {
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')) {
51 + add_filter('wp_redirect', '__return_false', 999);
52 + }
53 +
54 + if ($this->dev_mode) {
55 + add_filter('http_request_host_is_external', '__return_true');
56 + add_filter('http_request_args', function ($args) {
41 57 $args['sslverify'] = false;
42 58
43 59 return $args;
44 - } );
60 + });
45 61 }
46 - add_action( 'eb_frontend_assets', [ $this, 'enqueue_template_assets' ], 10, 2 );
47 - add_filter( 'the_content', [$this, 'filter_content'], 10 ,1);
48 62 }
49 63
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)) {
92 + flush_rewrite_rules();
93 + delete_option('templately_flush_rewrite_rules');
94 + }
95 + }
96 +
50 97 public function import_settings() {
51 - if( ! current_user_can( 'edit_posts' ) ) {
52 - 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);
53 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);
54 147
55 - $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 + ]);
56 155
57 - // Upload the logo and add its URL to the data
58 - $logo_url = $this->upload_logo();
59 - if ($logo_url !== null) {
60 - $data['logo'] = $logo_url;
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 + ]);
168 +
169 + if (is_wp_error($response)) {
170 + wp_send_json_error($response->get_error_message());
61 171 }
62 172
63 - wp_send_json_success( update_option( self::SESSION_OPTION_KEY, $data ) );
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);
64 195 }
65 196
66 - private function update_session_data( $data ): bool {
67 - $old_data = get_option( self::SESSION_OPTION_KEY, [] );
197 + private function update_session_data($data): bool {
198 + $old_data = $this->get_session_data();
68 199
69 - 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));
70 201 }
71 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 +
72 268 public function get_session_data(): array {
73 - $data = get_option( self::SESSION_OPTION_KEY, [] );
269 + $data = get_option(self::SESSION_OPTION_KEY, []);
74 270
75 271 $options = [];
76 272
77 273 if ( is_array( $data ) && ! empty( $data ) ) {
78 274 foreach ( $data as $key => $value ) {
79 - $json = json_decode( $value, true );
275 + $json = is_string($value) ? json_decode( $value, true ) : null;
80 276 $options[ $key ] = $json !== null ? $json : $value;
81 277 }
82 278 }
83 279
@@ -83,61 +279,137 @@
83 279
84 280 return $options;
85 281 }
86 282
283 + public function initialize_props() {
284 + $data = $this->get_session_data();
285 + if (isset($data['session_id'])) {
286 + $this->session_id = $data['session_id'];
287 + }
288 + if (isset($data['dir_path'])) {
289 + $this->dir_path = $data['dir_path'];
290 + }
291 + if (isset($data['download_key'])) {
292 + $this->download_key = $data['download_key'];
293 + }
294 + if (isset($data['dependency_data'])) {
295 + $this->dependency_data = $data['dependency_data'];
296 + }
297 + }
298 +
87 299 private function clear_session_data(): bool {
88 - return delete_site_option( self::SESSION_OPTION_KEY );
300 + return delete_site_option(self::SESSION_OPTION_KEY);
89 301 }
90 302
91 - public function import() {
92 - if ( ! $this->dev_mode && ! wp_doing_ajax() ) {
93 - exit;
94 - }
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" );
95 307
96 - header( "Cache-Control: no-store, no-cache" );
97 - header( 'Content-Type: text/event-stream, charset=UTF-8' );
98 - header( "Connection: Keep-Alive" );
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);
99 311
100 - if ( $GLOBALS['is_nginx'] ) {
312 + // Time to run the import! Set no limit
313 + set_time_limit(0);
314 +
315 +
316 + if ( !empty($GLOBALS['is_nginx']) ) {
101 317 header( 'X-Accel-Buffering: no' );
102 318 header( 'Content-Encoding: none' );
103 319 }
104 320
105 - 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 + }
106 330
107 - // Ignore user aborts and allow the script
108 - // to run forever
109 - ignore_user_abort(true);
331 + public function import() {
332 + if ( ! $this->dev_mode && ! wp_doing_ajax() ) {
333 + exit;
334 + }
110 335
111 - // Time to run the import!
112 - set_time_limit( 0 );
336 + // delete_option( 'templately_fsi_log' );
113 337
114 - flush();
115 - if(!defined('TEMPLATELY_IGNORE_FLUSH_ALL') || !TEMPLATELY_IGNORE_FLUSH_ALL){
116 - wp_ob_end_flush_all();
117 - }
338 + $this->sse_message( [
339 + 'type' => 'start',
340 + 'action' => 'eventLog',
341 + 'results' => __METHOD__ . '::' . __LINE__,
342 + ] );
118 343
344 + register_shutdown_function( [ $this, 'register_shutdown' ] );
345 +
346 + $this->finishRequestHeaders();
347 +
119 348 try {
120 349 // TODO: Need to check if user is connected or not
121 350
122 351 $this->request_params = $this->get_session_data();
352 + $this->initialize_props();
353 + $this->add_revert_hooks();
354 + $progress = $this->request_params['progress'] ?? [];
123 355
124 - $_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;
125 357
126 - if ( $_id === null ) {
127 - $this->throw( __( 'Invalid Pack ID.', 'templately' ) );
358 + if ($_id === null) {
359 + $this->throw(__('Invalid Pack ID.', 'templately'));
128 360 }
129 361
130 - /**
131 - * Check Writing Permission
132 - */
133 - $this->check_writing_permission();
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 + }
134 368
135 - /**
136 - * Download the zip
137 - */
138 - $this->download_zip( $_id );
369 + /**
370 + * Check Writing Permission
371 + */
372 + $this->check_writing_permission();
139 373
374 + /**
375 + * Download the zip
376 + */
377 + $this->download_zip( $_id );
378 +
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 + }
391 +
392 +
393 + if(empty($progress['download_dependencies'])){
394 + /**
395 + * Checking & Installing Plugin Dependencies
396 + */
397 + $this->install_dependencies();
398 +
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 + }
410 +
411 +
140 412 /**
141 413 * Reading Manifest File
142 414 */
143 415 $this->read_manifest();
@@ -152,43 +424,52 @@
152 424 $this->throw( __( 'Please update the templately plugin.', 'templately' ) );
153 425 }
154 426
155 427 /**
156 - * Checking & Installing Plugin Dependencies
157 - */
158 - $this->install_dependencies();
159 -
160 - /**
161 428 * Should Revert Old Data
162 429 */
163 - $this->revert();
430 + // $this->revert();
164 431
165 432 /**
166 433 * Platform Based Templates Import
167 434 */
168 435 $this->start_content_import();
436 +
169 437 } catch ( Exception $e ) {
170 - $this->sse_message( [
438 + $this->handle_import_status('failed', $e->getMessage());
439 + $this->sse_message([
171 440 'action' => 'error',
172 441 'status' => 'error',
173 442 'type' => "error",
174 443 'title' => __("Oops!", "templately"),
175 444 'message' => $e->getMessage()
176 - ] );
445 + ]);
177 446 }
178 447
179 - // TODO: cleanup
180 - $this->clear_session_data();
448 + // if($_GET['part'] === 'import'){
449 + // TODO: cleanup
450 + $this->clear_session_data();
451 + // }
181 452 }
182 453
454 + public function import_status(){
455 + $log = get_option( 'templately_fsi_log' );
456 +
457 + if(!empty($log) && is_array($log) && isset($_GET['lastLogIndex'])){
458 + $lastLogIndex = (int) $_GET['lastLogIndex'];
459 + $log = array_slice($log, $lastLogIndex);
460 + }
461 + wp_send_json( ['count' => $log ? count($log) : 0, 'log' => $log] );
462 + }
463 +
183 464 /**
184 465 * @throws Exception
185 466 */
186 - private function throw( $message, $code = 0 ) {
187 - if ( $this->dev_mode ) {
188 - 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));
189 470 }
190 - throw new Exception( $message );
471 + throw new Exception($message);
191 472 }
192 473
193 474 /**
194 475 * @throws Exception
@@ -195,59 +476,65 @@
195 476 */
196 477 private function check_writing_permission() {
197 478 $upload_dir = wp_upload_dir();
198 479
199 - if ( ! is_writable( $upload_dir['basedir'] ) ) {
200 - $this->throw( __( 'Upload directory is not writable.', 'templately' ) );
480 + if (!is_writable($upload_dir['basedir'])) {
481 + $this->throw(__('Upload directory is not writable.', 'templately'));
201 482 }
202 483
203 - $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;
204 485
205 - if ( ! is_dir( $this->tmp_dir ) ) {
206 - wp_mkdir_p( $this->tmp_dir );
486 + if (!is_dir($this->tmp_dir)) {
487 + wp_mkdir_p($this->tmp_dir);
207 488 }
208 489
209 - $this->sse_log( 'writing_permission_check', __( 'Permission Passed', 'templately' ), 100 );
490 + $this->sse_log('writing_permission_check', __('Permission Passed', 'templately'), 100);
210 491 }
211 492
212 - private function get_api_url( $id ): string {
213 - return $this->dev_mode ? 'https://app.templately.dev/api/v1/import/pack/' . $id : 'https://app.templately.com/api/v1/import/pack/' . $id;
493 + private function get_api_url($version, $end_point): string {
494 + return $this->dev_mode ? "https://app.templately.dev/api/$version/" . $end_point : "https://app.templately.com/api/$version/" . $end_point;
214 495 }
215 496
497 + private function info_get_api_url($id): string {
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;
499 + }
500 +
216 501 /**
217 502 * @throws Exception
218 503 */
219 504 private function download_zip( $id ) {
220 - // $this->sse_log( 'download', __( 'Downloading Template Pack', 'templately' ), 1 );
221 - $response = wp_remote_get( $this->get_api_url( $id ), [
505 + $this->sse_log( 'download', __( 'Downloading Template Pack', 'templately' ), 1 );
506 + $response = wp_remote_get( $this->get_api_url( "v2", "import/pack/$id" ), [
222 507 'timeout' => 30,
223 508 'headers' => [
224 - 'Authorization' => 'Bearer ' . $this->api_key,
225 - 'x-templately-ip' => Helper::get_ip(),
226 - 'x-templately-url' => home_url( '/' )
509 + 'Content-Type' => 'application/json',
510 + 'Authorization' => 'Bearer ' . $this->api_key,
511 + 'x-templately-ip' => Helper::get_ip(),
512 + 'x-templately-url' => home_url('/'),
513 + 'x-templately-version' => TEMPLATELY_VERSION,
227 514 ]
228 - ] );
515 + ]);
229 516
230 - $response_code = wp_remote_retrieve_response_code( $response );
231 - $content_type = wp_remote_retrieve_header( $response, 'content-type' );
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');
232 520
233 - if ( is_wp_error( $response ) ) {
234 - $this->throw( __( 'Template pack download failed', 'templately' ) . $response->get_error_message() );
235 - }
236 - 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) {
237 524 if (strpos($content_type, 'application/json') !== false) {
238 525 // Retrieve Data from Response Body.
239 - $response_body = json_decode( wp_remote_retrieve_body( $response ), true );
526 + $response_body = json_decode(wp_remote_retrieve_body($response), true);
240 527
241 528 // If the response body is JSON and it contains an error, throw an exception with the error message
242 529 if (isset($response_body['status']) && $response_body['status'] === 'error') {
243 - $this->throw( $response_body['message'] );
530 + $this->throw($response_body['message']);
244 531 }
245 532 }
246 - $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);
247 534 }
248 535
249 - $this->sse_log( 'download', __( 'Template is getting ready', 'templately' ), 57 );
536 + $this->sse_log('download', __('Template is getting ready', 'templately'), 57);
250 537
251 538 $session_id = uniqid();
252 539 $this->dir_path = $this->tmp_dir . $session_id . DIRECTORY_SEPARATOR;
253 540 $this->filePath = $this->tmp_dir . "{$session_id}.zip";
@@ -252,16 +539,20 @@
252 539 $this->dir_path = $this->tmp_dir . $session_id . DIRECTORY_SEPARATOR;
253 540 $this->filePath = $this->tmp_dir . "{$session_id}.zip";
254 541 $this->session_id = $session_id;
255 542
256 - $this->update_session_data( [ 'session_id' => $this->session_id ] );
543 + $this->update_session_data([
544 + 'session_id' => $this->session_id,
545 + 'dir_path' => $this->dir_path,
546 + 'download_key' => $this->download_key,
547 + ]);
257 548
258 - if ( file_put_contents( $this->filePath, $response['body'] ) ) { // phpcs:ignore
259 - $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);
260 551
261 552 $this->unzip();
262 553 } else {
263 - $this->throw( __( 'Downloading Failed. Please try again', 'templately' ) );
554 + $this->throw(__('Downloading Failed. Please try again', 'templately'));
264 555 }
265 556 }
266 557
267 558 /**
@@ -267,25 +558,31 @@
267 558 /**
268 559 * @throws Exception
269 560 */
270 561 protected function unzip() {
271 - if ( ! WP_Filesystem() ) {
272 - $this->throw( __( 'WP_Filesystem cannot be initialized', 'templately' ) );
562 + if (!WP_Filesystem()) {
563 + $this->throw(__('WP_Filesystem cannot be initialized', 'templately'));
273 564 }
274 565
275 - if(defined('TEMPLATELY_ZIP_ARCHIVE') && TEMPLATELY_ZIP_ARCHIVE){
276 - $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);
277 569 }
278 - else{
279 - $unzip = unzip_file( $this->filePath, $this->dir_path );
280 - }
281 570
282 - if ( is_wp_error( $unzip ) ) {
283 - $this->throw( sprintf( __( 'Unzipping failed: %s', 'templately' ), $unzip->get_error_message() ) );
571 + if (is_wp_error($unzip)) {
572 + $error = $unzip->get_error_message();
573 + if (empty($error)) {
574 + // Generic error message
575 + Helper::log($unzip);
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');
577 + $this->throw($error_message);
578 + } else {
579 + $this->throw($unzip->get_error_message());
580 + }
284 581 }
285 582
286 - if ( $unzip ) {
287 - unlink( $this->filePath );
583 + if ($unzip) {
584 + unlink($this->filePath);
288 585 }
289 586 }
290 587
291 588 /**
@@ -295,18 +592,26 @@
295 592 * @param string $to Full path on the filesystem to extract archive to.
296 593 * @return true|WP_Error True on success, WP_Error on failure.
297 594 */
298 595 function unzip_file($file, $to) {
299 - $zip = new \ZipArchive;
596 + try {
597 + $zip = new \ZipArchive;
300 598
301 - $res = $zip->open($file);
302 - if ($res === TRUE) {
303 - $zip->extractTo($to);
304 - $zip->close();
599 + $res = $zip->open($file);
600 + if ($res === TRUE) {
601 + $zip->extractTo($to);
602 + $zip->close();
305 603
306 - return true;
604 + return true;
605 + }
606 + } catch (\Throwable $th) {
607 + return new \WP_Error('exception_caught', $th->getMessage());
608 + }
609 +
610 + if (isset($zip)) {
611 + return new \WP_Error('zip_error_' . $zip->status, $zip->getStatusString());
307 612 } else {
308 - return new \WP_Error('Could not unzip file: ' . $zip->getStatusString());
613 + return new \WP_Error('unknown_error', '');
309 614 }
310 615 }
311 616
312 617 /**
@@ -312,15 +617,15 @@
312 617 /**
313 618 * @throws Exception
314 619 */
315 620 private function read_manifest() {
316 - $manifest_content = file_get_contents( $this->dir_path . DIRECTORY_SEPARATOR . 'manifest.json' );
317 - if ( empty( $manifest_content ) ) {
318 - $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'));
319 624 }
320 625
321 - $this->manifest = json_decode( $manifest_content, true );
322 - $this->removeLog( 'temp' );
626 + $this->manifest = json_decode($manifest_content, true);
627 + $this->removeLog('temp');
323 628
324 629 // TODO: Read & Broadcast the LOG for waiting list
325 630 // $this->sse_log( 'plugin', 'Installing required plugins', '--', 'updateLog', 'processing' );
326 631 // // $this->sse_log( 'extra-content', 'Import Extra Contents (i.e: Forms)', '--', 'updateLog', 'processing' );
@@ -330,31 +635,38 @@
330 635 // $this->sse_log( 'finalize', 'Finalizing Your Imports', '--', 'updateLog', 'processing' );
331 636 }
332 637
333 638 private function skipped_plugin(): bool {
334 - 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']);
335 640 }
336 641
337 642 private function install_dependencies() {
338 - if ( ! empty( $this->request_params['theme'] ) && is_array( $this->request_params['theme'] ) ) {
643 + $progress = $this->request_params['progress'] ?? [];
644 +
645 + if ( empty($progress['theme_dependency']) && ! empty( $this->request_params['theme'] ) && is_array( $this->request_params['theme'] ) ) {
339 646 // activate theme
340 647 $theme = $this->request_params['theme'];
341 648
342 - $this->before_install_hook();
649 + // $this->before_install_hook();
343 650
344 651 if (isset($theme['stylesheet'])) {
345 652 // do_action('before_theme_activation', $theme); // Trigger action before theme activation
346 - $this->sse_log( 'theme', 'Installing and activating theme: ' . $theme['name'], 0 );
347 - $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 + }
348 658
659 + $plugin_status = Installer::get_instance()->install_and_activate_theme($theme['stylesheet']);
660 +
349 661 if (!$plugin_status['success']) {
350 - $this->sse_message( [
662 + $this->sse_message([
351 663 'action' => 'updateLog',
352 664 'status' => 'error',
353 665 'message' => "Failed to activate theme: " . $theme['name'],
354 666 'type' => "theme",
355 667 'progress' => 0
356 - ] );
668 + ]);
357 669 $this->dependency_data['theme'] = [
358 670 'success' => false,
359 671 'name' => $theme['name'],
360 672 'slug' => $theme['stylesheet'],
@@ -359,18 +671,21 @@
359 671 'name' => $theme['name'],
360 672 'slug' => $theme['stylesheet'],
361 673 'message' => $plugin_status['message'] ?? ''
362 674 ];
675 + $this->update_session_data( [
676 + 'dependency_data' => $this->dependency_data,
677 + ] );
363 678 } else {
364 679 // do_action('after_theme_activation', $theme); // Trigger action after theme activation
365 680
366 - $this->sse_message( [
681 + $this->sse_message([
367 682 'action' => 'updateLog',
368 683 'status' => 'complete',
369 684 'message' => "Activated theme: " . $theme['name'],
370 685 'type' => "theme",
371 686 'progress' => 100
372 - ] );
687 + ]);
373 688 $this->dependency_data['theme'] = [
374 689 'success' => true,
375 690 'name' => $theme['name'],
376 691 'slug' => $theme['stylesheet'],
@@ -375,44 +690,65 @@
375 690 'name' => $theme['name'],
376 691 'slug' => $theme['stylesheet'],
377 692 'message' => $plugin_status['message'] ?? ''
378 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 + ] );
379 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;
380 711 }
381 712
382 - $this->after_install_hook();
713 + // $this->after_install_hook();
383 714 }
384 - else {
715 + else if(empty($progress['theme_dependency'])) {
385 716 $this->removeLog( 'theme' );
386 717 }
387 718 if ( ! empty( $this->request_params['plugins'] ) && is_array( $this->request_params['plugins'] ) ) {
388 719 // $this->sse_log( 'plugin', 'Installing Plugins', 1 );
389 - $total_plugin = count( $this->request_params['plugins'] );
720 + $total_plugin = count($this->request_params['plugins']);
390 721
391 - $total_plugin_installed = $total_plugin;
392 - $_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'] ?? [];
393 725
394 - $this->before_install_hook();
726 + // $this->before_install_hook();
395 727
396 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;
397 733 $this->sse_log( 'plugin', 'Installing required plugins: ' . $dependency['name'], floor( ( 100 * $_installed_plugins / $total_plugin ) ) );
398 734
399 735 $dependency['slug'] = $dependency['plugin_original_slug'];
400 - $plugin_status = Installer::get_instance()->install( $dependency );
736 + $plugin_status = Installer::get_instance()->install($dependency);
401 737
402 - if ( ! $plugin_status['success'] ) {
403 - $this->sse_message( [
738 + if (!$plugin_status['success']) {
739 + $this->sse_message([
404 740 'position' => 'plugin',
405 741 'action' => 'updateLog',
406 742 'status' => 'error',
407 - 'message' => 'Installation Failed: ' . $dependency['name'] . ' (' . ( $plugin_status['message'] ?? '' ) . ')',
743 + 'message' => 'Installation Failed: ' . $dependency['name'] . ' (' . ($plugin_status['message'] ?? '') . ')',
408 744 'type' => "plugin_{$dependency['plugin_original_slug']}",
409 745 'progress' => 0
410 - ] );
746 + ]);
411 747
412 - if(isset($dependency['mustHave']) && $dependency['mustHave']){
413 - $this->removeLog( 'plugin' );
414 - $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'] ?? '') . ')');
415 751 }
416 752
417 753 $this->dependency_data['plugins']['failed'][] = [
418 754 'name' => $dependency['name'],
@@ -421,35 +757,60 @@
421 757 'message' => $plugin_status['message'] ?? ''
422 758 ];
423 759 } else {
424 760 $_installed_plugins++;
425 - $total_plugin_installed--;
761 + // $total_plugin_installed--;
762 +
763 + $this->dependency_data['_installed_plugins'] = $_installed_plugins;
426 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 + }
427 784 }
428 785
429 - $this->after_install_hook();
786 + // $this->after_install_hook();
430 787
431 - $this->sse_message( [
788 + $this->sse_message([
432 789 'action' => 'updateLog',
433 790 'status' => 'complete',
434 791 'message' => "Installed required plugins ($_installed_plugins/$total_plugin)",
435 792 'type' => "plugin",
436 793 'progress' => 100
437 - ] );
794 + ]);
438 795 $this->dependency_data['plugins']['total'] = $total_plugin;
439 796 $this->dependency_data['plugins']['succeed'] = $_installed_plugins;
440 797 } else {
441 - $this->removeLog( 'plugin' );
798 + $this->removeLog('plugin');
442 799 }
443 800
801 +
802 + $this->update_session_data([
803 + 'dependency_data' => json_encode($this->dependency_data),
804 + ]);
444 805 // $this->sse_log( 'plugin', 'Skipped Installing Plugins', '--', 'updateLog', 'skipped' );
445 806 }
446 807
447 808 private function before_install_hook() {
448 - remove_all_actions( 'wp_loaded' );
449 - remove_all_actions( 'after_setup_theme' );
450 - remove_all_actions( 'plugins_loaded' );
451 - remove_all_actions( 'init' );
809 + // remove_all_actions( 'wp_loaded' );
810 + // remove_all_actions( 'after_setup_theme' );
811 + // remove_all_actions( 'plugins_loaded' );
812 + // remove_all_actions( 'init' );
452 813
453 814 // making sure so that no redirection happens during plugin installation and hooks triggered bellow.
454 815 add_filter('wp_redirect', '__return_false', 999);
455 816 }
@@ -454,12 +815,12 @@
454 815 add_filter('wp_redirect', '__return_false', 999);
455 816 }
456 817
457 818 private function after_install_hook() {
458 - do_action( 'wp_loaded' );
459 - do_action( 'after_setup_theme' );
460 - do_action( 'plugins_loaded' );
461 - do_action( 'init' );
819 + // do_action( 'wp_loaded' );
820 + // do_action( 'after_setup_theme' );
821 + // do_action( 'plugins_loaded' );
822 + // do_action( 'init' );
462 823 }
463 824
464 825 /**
465 826 * @throws Exception
@@ -467,42 +828,54 @@
467 828 private function start_content_import() {
468 829 add_filter('upload_mimes', array($this, 'allow_svg_upload'));
469 830 add_filter('elementor/files/allow_unfiltered_upload', '__return_true');
470 831
471 - $import = new Import( $this );
832 + $import = new Import($this);
472 833 $imported_data = $import->run();
473 834
474 - $this->sse_message( [
835 + $import_status = $this->handle_import_status('success');
836 +
837 + update_option('templately_flush_rewrite_rules', true, false);
838 +
839 + $this->sse_message([
475 840 'type' => 'complete',
476 841 'action' => 'complete',
477 - 'results' => $this->normalize_imported_data( $imported_data )
478 - ] );
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 + }
479 852 }
480 853
481 - private function normalize_imported_data( $data ) {
482 - $templates = ! empty( $data['templates']['succeed'] ) ? count( $data['templates']['succeed'] ) : 0;
483 - $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'] : [];
484 857
485 858 $post_types = [];
486 859 $content_templates = [];
487 - if ( ! empty( $data['content'] ) && is_array( $data['content'] ) ) {
488 - foreach ( $data['content'] as $type => $type_data ) {
489 - $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;
490 863 $post_types[] = $this->get_post_type_label_by_slug($type);
491 864 }
492 865 }
493 866
494 867 $contents = [];
495 - if ( ! empty( $data['wp-content'] ) && is_array( $data['wp-content'] ) ) {
496 - foreach ( $data['wp-content'] as $type => $type_data ) {
497 - $contents[ $type ] = ! empty( $type_data['succeed'] ) ? count( $type_data['succeed'] ) : 0;
498 - 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'])) {
499 872 $post_types[] = $this->get_post_type_label_by_slug($type);
500 873 }
501 874 }
502 875 }
503 876
504 - Helper::log( $data );
877 + Helper::log($data);
505 878
506 879 return [
507 880 'templates' => $templates,
508 881 'contents' => $content_templates,
@@ -523,105 +896,17 @@
523 896 // // TODO: Implement the Revert Process.
524 897 // }
525 898 }
526 899
527 - public function redirect_for_archives( $link, $post_id ) {
528 - $archive_settings = get_option( 'templately_post_archive' );
529 - if ( ! empty( $archive_settings ) && intval( $archive_settings['post_id'] ) === intval( $post_id ) ) {
530 - $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);
531 904 }
532 905
533 906 return $link;
534 907 }
535 908
536 - public function enqueue_template_assets( $path, $url ) {
537 - $using_templately_builder = get_query_var( 'using_templately_template' );
538 - if ( $using_templately_builder && function_exists( 'templately' ) ) {
539 - $template_locations = [ 'header', 'footer', 'archive', 'single' ];
540 - foreach ( $template_locations as $location ) {
541 - $template = templately()->theme_builder::$conditions_manager->get_templates_by_location( $location );
542 - if ( empty( $template ) ) {
543 - return;
544 - }
545 - $template = array_pop( $template );
546 - if ( $template->platform == 'gutenberg' ) {
547 - $template = is_array( $template ) ? array_pop( $template ) : $template;
548 - if ( ! file_exists( $path . 'eb-style-' . $template->get_main_id() . '.min.css' ) ) {
549 - $st = EbStyleHandler::init();
550 - $post = get_post( $template->get_main_id() );
551 - $st->eb_write_css_from_content( $post, $post->ID, parse_blocks( $post->post_content ) );
552 - }
553 - wp_enqueue_style( 'templately-' . $location . '-' . $template->get_main_id(), $url . 'eb-style-' . $template->get_main_id() . '.min.css', [], substr( md5( microtime( true ) ), 0, 10 ) );
554 - }
555 - }
556 - }
557 - }
558 -
559 - public function upload_logo() {
560 - // Check if the upload file exists
561 - if (isset($_FILES['logo'])) {
562 - // Require the needed files if not already loaded
563 - if (!function_exists('wp_handle_upload')) {
564 - require_once(ABSPATH . 'wp-admin/includes/file.php');
565 - }
566 -
567 - // Manually upload the file
568 - $uploadedfile = $_FILES['logo'];
569 - $upload_overrides = array('test_form' => false);
570 - $movefile = wp_handle_upload($uploadedfile, $upload_overrides);
571 -
572 - if ($movefile && !isset($movefile['error'])) {
573 - // The file was uploaded successfully, now we need to resize it
574 - if (!function_exists('wp_get_image_editor')) {
575 - require_once(ABSPATH . 'wp-admin/includes/image.php');
576 - }
577 -
578 - $filetype = wp_check_filetype($movefile['file']);
579 -
580 - if ($filetype['ext'] == 'jpg' || $filetype['ext'] == 'jpeg' || $filetype['ext'] == 'png') {
581 - $image = wp_get_image_editor($movefile['file']);
582 - if (!is_wp_error($image)) {
583 - $size = $image->get_size();
584 - if ($size['width'] > 200 || $size['height'] > 80) {
585 - $image->resize(200, 80, false);
586 - $image->save($movefile['file']);
587 - }
588 - }
589 - }
590 -
591 - // Prepare an array of post data for the attachment
592 - $attachment = array(
593 - 'guid' => $movefile['url'],
594 - 'post_mime_type' => $movefile['type'],
595 - 'post_title' => preg_replace('/\.[^.]+$/', '', basename($movefile['file'])),
596 - 'post_content' => '',
597 - 'post_status' => 'inherit'
598 - );
599 -
600 - // Insert the attachment
601 - $attach_id = wp_insert_attachment($attachment, $movefile['file']);
602 -
603 - // Generate the metadata for the attachment and update the database record
604 - $attach_data = wp_generate_attachment_metadata($attach_id, $movefile['file']);
605 - wp_update_attachment_metadata($attach_id, $attach_data);
606 -
607 - // Return the URL of the uploaded file
608 - return json_encode( [
609 - 'id' => $attach_id,
610 - 'url' => $movefile['url']
611 - ]);
612 - } else {
613 - /**
614 - * Error generated by _wp_handle_upload()
615 - * @see _wp_handle_upload() in wp-admin/includes/file.php
616 - */
617 - // return $movefile['error'];
618 - }
619 - }
620 -
621 - return null;
622 - }
623 -
624 909 public function allow_svg_upload($mimes) {
625 910 // Allow SVG
626 911 $mimes['svg'] = 'image/svg+xml';
627 912 return $mimes;
@@ -626,13 +911,13 @@
626 911 $mimes['svg'] = 'image/svg+xml';
627 912 return $mimes;
628 913 }
629 914
630 - public function register_shutdown(){
915 + public function register_shutdown() {
631 916 $status = connection_status();
632 917 $last_error = error_get_last();
633 918 if ($status != CONNECTION_NORMAL && $last_error && $last_error['type'] === E_ERROR) {
634 - if (defined('WP_DEBUG') && WP_DEBUG && !empty($last_error['message'])) {
919 + if ((defined('WP_DEBUG') && WP_DEBUG || defined('TEMPLATELY_EVENT_LOG') && TEMPLATELY_EVENT_LOG) && !empty($last_error['message'])) {
635 920 $full_message = $last_error['message'];
636 921
637 922 // Split the message at the first newline to remove the stack trace
638 923 $message_parts = preg_split('/\n/', $full_message);
@@ -643,10 +928,12 @@
643 928 // Generic error message
644 929 $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');
645 930 }
646 931
932 +
933 + $this->handle_import_status('failed', $error_message);
647 934 // Handle the error, e.g. log it or display a message to the user
648 - $this->sse_message( [
935 + $this->sse_message([
649 936 'action' => 'error',
650 937 'status' => 'error',
651 938 'type' => "error",
652 939 'title' => __("Oops!", "templately"),
@@ -652,16 +939,65 @@
652 939 'title' => __("Oops!", "templately"),
653 940 'message' => $error_message,
654 941 // 'position' => 'plugin',
655 942 // 'progress' => '--',
656 - ] );
943 + ]);
657 944 }
658 945
659 - Helper::log( "Shutdown:....." );
660 - Helper::log( "connection_status: " . $this->getConnectionStatusText() );
661 - Helper::log( $last_error );
946 + $this->debug_log("Shutdown:.....");
947 + $this->debug_log("connection_status: " . $this->getConnectionStatusText());
948 + $this->debug_log($last_error);
662 949 }
663 950
951 + public function handle_import_status($status, $description = '') {
952 + if ($this->is_import_status_handled) {
953 + Helper::log("Import status already handled: $status");
954 + return null;
955 + }
956 + $this->is_import_status_handled = $status;
957 +
958 + $download_key = $this->download_key;
959 +
960 + $headers = [
961 + 'Content-Type' => 'application/json',
962 + 'Authorization' => 'Bearer ' . $this->api_key,
963 + 'download_key' => $download_key,
964 + 'download-key' => $download_key,
965 + 'x-templately-ip' => Helper::get_ip(),
966 + 'x-templately-url' => home_url('/'),
967 + ];
968 +
969 + $args = [
970 + 'headers' => $headers,
971 + ];
972 +
973 +
974 + if ($status === 'success') {
975 + $url = $this->get_api_url("v1", 'import/success');
976 + $args['body'] = json_encode(['type' => 'pack']);
977 + $response = wp_remote_post($url, $args);
978 + } elseif ($status === 'failed') {
979 + $url = $this->get_api_url("v1", 'import/failed');
980 + $args['body'] = json_encode(['type' => 'pack', 'description' => $description ?: "Something Went wrong....."]);
981 + $response = wp_remote_post($url, $args);
982 + }
983 +
984 + Helper::log($response);
985 +
986 + if (is_wp_error($response)) {
987 + // Handle error
988 + Helper::log($response->get_error_message());
989 + } else {
990 + // Handle success
991 + $body = wp_remote_retrieve_body($response);
992 + $data = json_decode($body, true);
993 + // Do something with $body
994 + return $data;
995 + }
996 +
997 + return null;
998 + }
999 +
664 1000 protected function getConnectionStatusText() {
665 1001 $status = connection_status();
666 1002 switch ($status) {
667 1003 case CONNECTION_NORMAL:
@@ -676,22 +1012,228 @@
676 1012 }
677 1013
678 1014 protected function get_post_type_label_by_slug($slug) {
679 1015 $post_type_obj = get_post_type_object($slug);
680 - if($post_type_obj) {
1016 + if ($post_type_obj) {
681 1017 return $post_type_obj->label;
682 1018 }
683 1019 return null;
684 1020 }
685 1021
686 - public function filter_content( $content ) {
687 - if(is_singular()){
688 - global $post;
689 - if(!empty($post) && $post->post_type === 'templately_library'){
690 - if(in_array(get_post_meta($post->ID, '_templately_template_type', true), ['header', 'footer'])){
691 - return '';
1022 + public function import_info() {
1023 +
1024 + $platform = isset($_GET['platform']) ? $_GET['platform'] : 'elementor';
1025 + $id = isset($_GET['id']) ? intval($_GET['id']) : 0;
1026 +
1027 + $response = wp_remote_get($this->info_get_api_url($id), [
1028 + 'timeout' => 30,
1029 + 'headers' => [
1030 + 'Authorization' => 'Bearer ' . $this->api_key,
1031 + 'x-templately-ip' => Helper::get_ip(),
1032 + 'x-templately-url' => home_url('/'),
1033 + 'x-templately-version' => TEMPLATELY_VERSION,
1034 + ]
1035 + ]);
1036 +
1037 + if (is_wp_error($response)) {
1038 + wp_send_json_error($response->get_error_message());
1039 + return;
1040 + }
1041 + // If the response code is not 200, return the error message
1042 + if (wp_remote_retrieve_response_code($response) != 200) {
1043 + wp_send_json_error(json_decode(wp_remote_retrieve_body($response)));
1044 + return;
1045 + }
1046 + // If the response body is JSON and it contains an error, return the error message
1047 + // Retrieve Data from Response Body.
1048 + $body = wp_remote_retrieve_body($response);
1049 + $data = json_decode($body, true);
1050 +
1051 + if (isset($data['error'])) {
1052 + wp_send_json_error($data['error']);
1053 + return;
1054 + }
1055 +
1056 + if (isset($data['data']['manifest'])) {
1057 + $data['data']['manifest'] = json_decode($data['data']['manifest'], true);
1058 + }
1059 + if (isset($data['data']['settings'])) {
1060 + $data['data']['settings'] = json_decode($data['data']['settings'], true);
1061 + }
1062 +
1063 + // Return the response body
1064 + wp_send_json($data);
1065 + }
1066 +
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);
692 1152 }
1153 + delete_option("__templately_$key");
1154 + $options_deleted = true;
693 1155 }
694 1156 }
695 - return $content;
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() ]);
696 1205 }
697 -}
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 +}