PluginProbe
Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! / trunk
Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! vtrunk
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
templately / modules / full-site-import / Runners / DownloadZip.php

DownloadZip.php in Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! trunk, at modules/full-site-import/Runners/DownloadZip.php

203 lines 7.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Templately\Modules\FullSiteImport\Runners;
4
5 use Exception;
6 use Templately\Modules\FullSiteImport\Utils\Form;
7 use Templately\Modules\FullSiteImport\Runners\BaseRunner;
8 use Templately\Modules\FullSiteImport\Utils\Utils;
9 use Templately\Modules\FullSiteImport\Utils\SessionData;
10 use Templately\Utils\Helper;
11 use Templately\Utils\Response\ResponseNormalizer;
12
13 class DownloadZip extends BaseRunner {
14 /**
15 * @var string
16 */
17 private $download_key;
18
19 /**
20 * @var string
21 */
22 private $filePath;
23
24 public function get_name(): string {
25 return 'downloadzip';
26 }
27
28 public function get_label(): string {
29 return __( 'Download Zip', 'templately' );
30 }
31
32 public function should_log(): bool {
33 return true;
34 }
35
36 public function get_action(): string {
37 return 'eventLog';
38 }
39
40 public function log_message(): string {
41 return __( 'Updating customizer settings.', 'templately' );
42 }
43
44 public function should_run( $data, $imported_data = [] ): bool {
45 $params = $this->origin->get_request_params();
46 return ! empty( $params['title'] ) || !empty( $params['slogan'] );
47 }
48
49 public function import( $data, $imported_data ): array {
50 /**
51 * Download the zip
52 */
53 $this->download_zip( $_id );
54
55 SessionData::mark_step_complete($this->session_id, 'download_zip');
56 $this->sse_message( [
57 'type' => 'continue',
58 'action' => 'continue',
59 'info' => 'download_zip',
60 'results' => __METHOD__ . '::' . __LINE__,
61 ] );
62
63 return [ 'customizer' => $customizer ];
64 }
65
66 /**
67 * @throws Exception
68 */
69 private function download_zip( $id ) {
70 $this->sse_log( 'download', __( 'Downloading Template Pack', 'templately' ), 1 );
71
72 // Forward the host platform (e.g. 'ai-builder') so the cloud scopes the
73 // pack download the same way as the REST/AJAX calls — without it this
74 // binary download bypasses Helper::make_api_request() and the cloud
75 // defaults to 'templately', re-gating AI Builder packs. Sourced from the
76 // request param to match the param-only resolution in Helper.
77 $requested_platform = isset( $_REQUEST['requested_platform'] ) // phpcs:ignore WordPress.Security.NonceVerification.Recommended
78 ? sanitize_text_field( wp_unslash( $_REQUEST['requested_platform'] ) )
79 : 'templately';
80
81 // The download used to leave NO trace: a run that stopped here showed one
82 // "Downloading Template Pack" line and nothing else — no size, no status, no
83 // timing, no indication whether the request was even made. That is the state this
84 // log exists to make readable.
85 Helper::log(
86 sprintf( 'download_zip: requesting pack %s (session=%s)', $id, $this->session_id ),
87 'download_zip',
88 'info'
89 );
90
91 // `connection_aborted()` is only truthful after output has been flushed, which the
92 // SSE stream does constantly — so a shutdown handler can tell "the browser hung up"
93 // apart from "PHP died", which is the whole question when a run ends in silence.
94 $download_started = microtime( true );
95 $session_id = $this->session_id;
96 register_shutdown_function( function () use ( $id, $session_id, $download_started ) {
97 if ( defined( 'TEMPLATELY_DOWNLOAD_ZIP_DONE' ) ) {
98 return;
99 }
100
101 Helper::log(
102 sprintf(
103 'download_zip: request ENDED before the pack was saved after %.1fs (pack=%s, session=%s, connection_aborted=%d, last_error=%s)',
104 microtime( true ) - $download_started,
105 $id,
106 $session_id,
107 connection_aborted(),
108 wp_json_encode( error_get_last() )
109 ),
110 'download_zip',
111 'error'
112 );
113 } );
114
115 $response = wp_remote_get( $this->get_api_url( "v2", "import/pack/$id" ), [
116 'timeout' => 30,
117 'headers' => [
118 'Content-Type' => 'application/json',
119 'Authorization' => 'Bearer ' . $this->api_key,
120 'x-templately-ip' => Helper::get_ip(),
121 'x-templately-url' => home_url('/'),
122 'x-templately-version' => TEMPLATELY_VERSION,
123 'x-templately-requested-platform' => $requested_platform,
124 ]
125 ]);
126
127 // The pack is a ZIP: FR-012 raw passthrough, so the body stays bytes and
128 // `download-key` stays readable off the raw response. The normalizer is
129 // used only to CLASSIFY, matching Concerns\DownloadsPack — these two carry
130 // the same download logic, and letting only one of them learn the contract
131 // is how they drift apart again.
132 $this->download_key = wp_remote_retrieve_header($response, 'download-key');
133
134 Helper::log(
135 sprintf(
136 'download_zip: pack %s answered %s in %.1fs (%s bytes, type=%s, download-key=%s)',
137 $id,
138 is_wp_error( $response ) ? 'WP_Error: ' . $response->get_error_message() : 'HTTP ' . (int) wp_remote_retrieve_response_code( $response ),
139 microtime( true ) - $download_started,
140 is_wp_error( $response ) ? '0' : strlen( (string) wp_remote_retrieve_body( $response ) ),
141 is_wp_error( $response ) ? '-' : (string) wp_remote_retrieve_header( $response, 'content-type' ),
142 $this->download_key ? 'present' : 'missing'
143 ),
144 'download_zip',
145 is_wp_error( $response ) ? 'error' : 'info'
146 );
147
148 $normalized = ResponseNormalizer::normalize($response, [
149 'raw' => true,
150 'side_effects' => false,
151 ]);
152
153 if ($normalized->is_error()) {
154 $error = $normalized->error();
155
156 if ($error->is_retryable()) {
157 $this->throw_retryable(__('Template pack download failed. ', 'templately') . $error->message());
158 }
159
160 $support_message = '';
161 if (strpos($error->message(), Helper::web_url( '', [ 'support' => 'open' ] )) === false) {
162 $support_message = sprintf(__(" Please try again or contact <a href='%s' target='_blank'>support</a>.", "templately"), Helper::web_url( '', [ 'support' => 'open' ] ));
163 }
164
165 $this->throw_non_retryable($error->message() . $support_message);
166 }
167
168 $this->sse_log('download', __('Downloading Template Pack', 'templately'), 57);
169
170 // $session_id = uniqid();
171 $this->dir_path = $this->tmp_dir . $this->session_id . DIRECTORY_SEPARATOR;
172 $this->filePath = $this->tmp_dir . "{$this->session_id}.zip";
173 // $this->session_id = $session_id;
174
175 SessionData::set($this->session_id, 'session_id', $this->session_id);
176 SessionData::set($this->session_id, 'dir_path', $this->dir_path);
177 SessionData::set($this->session_id, 'download_key', $this->download_key);
178
179 $written = file_put_contents($this->filePath, $response['body']); // phpcs:ignore
180
181 Helper::log(
182 sprintf( 'download_zip: wrote %s bytes to %s', var_export( $written, true ), $this->filePath ),
183 'download_zip',
184 false === $written ? 'error' : 'info'
185 );
186
187 if ($written) {
188 // The shutdown handler above only fires when the pack never made it to disk.
189 if ( ! defined( 'TEMPLATELY_DOWNLOAD_ZIP_DONE' ) ) {
190 define( 'TEMPLATELY_DOWNLOAD_ZIP_DONE', true );
191 }
192
193 $this->sse_log('download', __('Downloading Template Pack', 'templately'), 100);
194
195 $this->unzip();
196
197 Helper::log( sprintf( 'download_zip: unzipped into %s', $this->dir_path ), 'download_zip', 'info' );
198 } else {
199 $this->throw_retryable(__('Downloading Failed. Please try again', 'templately'));
200 }
201 }
202
203 }