PluginProbe
Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! / 3.8.0
Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! v3.8.0
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 / REST / PackInfo.php

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

128 lines 5.1 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\REST;
4
5 use Templately\API\API;
6 use Templately\Modules\FullSiteImport\Utils\AIUtils;
7 use Templately\Modules\FullSiteImport\Utils\PackInfoFetcher;
8 use Templately\Modules\FullSiteImport\Utils\SessionData;
9 use Templately\Utils\Helper;
10 use WP_Error;
11 use WP_REST_Request;
12
13 /**
14 * REST replacement for the `wp_ajax_templately_pack_import_info` action
15 * (FR-018, specs/025-full-site-import/spec.md — the spec's ajax→REST map targets
16 * `GET /templately/v1/import/info`). Fetches a pack's import metadata (manifest,
17 * customizer settings, credit balance, business niches, and — for AI packs — the
18 * latest AI process + any already-generated preview content) from the Templately API.
19 *
20 * VERB — GET (not POST like the sibling `GlobalSettings`): `import_info()` is a pure
21 * READ. It performs zero session/option writes — every call it makes is read-only
22 * (`get_option('templately_ai_business_niches')`, `AIUtils::get_latest_ai_process_by_api_key()`,
23 * `SessionData::get_data()`, `AIUtils::read_ai_template_data()`), so GET is the
24 * REST-correct verb, it matches the spec's own mapping table, and it matches every
25 * existing frontend caller (all of which already GET). None of the fetched data feeds
26 * the later SSE import as state written here — the SSE session is created separately by
27 * `import_settings`/`create_session_and_download`, which this route does not touch.
28 *
29 * The old ajax action (`Ajax\PackInfoController::import_info()`) is kept running as a
30 * deprecated shim (see module.php) — browsers with an already-cached old JS bundle would
31 * otherwise break. The upstream fetch is shared with `GlobalSettings` + the ajax shims
32 * via `Utils\PackInfoFetcher`.
33 */
34 class PackInfo extends API {
35
36 /**
37 * The ajax path required `install_plugins` AND `install_themes` (the capability pair
38 * `FullSiteImport::add_ajax_action()` enforces for every `wp_ajax_templately_pack_*`
39 * action) plus a valid `templately_nonce`. REST requests carry their own nonce
40 * (`X-WP-Nonce`, verified by WP core before permission_callback runs), so the
41 * equivalent protection here is: the same capability pair, ON TOP OF the base API
42 * class's `permission_check()` (delete_posts + a connected/verified `api_key`) — net
43 * STRICTER than the ajax path, never weaker. Identical gate to the sibling
44 * `GlobalSettings`.
45 */
46 public function permission_check( WP_REST_Request $request ) {
47 $this->request = $request;
48
49 if ( ! current_user_can( 'install_plugins' ) || ! current_user_can( 'install_themes' ) ) {
50 return new WP_Error(
51 'rest_forbidden',
52 __( 'Sorry, you are not allowed to fetch pack import info.', 'templately' ),
53 [ 'status' => rest_authorization_required_code() ]
54 );
55 }
56
57 return parent::permission_check( $request );
58 }
59
60 public function register_routes() {
61 $this->get( 'import/info', [ $this, 'import_info' ], [
62 'id' => [
63 'required' => true,
64 ],
65 'isAi' => [
66 'required' => false,
67 ],
68 ] );
69 }
70
71 public function import_info() {
72 $id = $this->get_param( 'id', 0, 'absint' );
73 $isAi = Helper::sanitize( $this->get_param( 'isAi', false, null ), 'boolean' );
74
75 if ( empty( $id ) ) {
76 return $this->error( 'invalid_id', __( 'A valid pack id is required.', 'templately' ), 'import/info', 400 );
77 }
78
79 $data = ( new PackInfoFetcher() )->fetch( $id, $isAi );
80 if ( is_wp_error( $data ) ) {
81 return $this->error( 'api_error', $data->get_error_message(), 'import/info', 500 );
82 }
83
84 // Post-fetch enrichment — identical to Ajax\PackInfoController::import_info().
85 $business_niches = get_option( 'templately_ai_business_niches', [] );
86 $data['data']['business_niches'] = $business_niches;
87
88 if ( isset( $data['data']['manifest'] ) ) {
89 $data['data']['manifest'] = json_decode( $data['data']['manifest'], true );
90 }
91 if ( isset( $data['data']['settings'] ) ) {
92 $data['data']['settings'] = json_decode( $data['data']['settings'], true );
93 }
94
95 if ( $isAi ) {
96 // Get the latest AI process for the current API key.
97 $last_ai_process = AIUtils::get_latest_ai_process_by_api_key( $id );
98 if ( $last_ai_process ) {
99 $data['data']['ai_process'] = $last_ai_process;
100 }
101
102 if ( $last_ai_process && $id == ( $last_ai_process['pack_id'] ?? null ) ) {
103 // Read AI preview content directly from files using the common function.
104 $session_id = $last_ai_process['session_id'] ?? null;
105 $ai_page_ids = $last_ai_process['ai_page_ids'] ?? [];
106 $dir_path = null;
107
108 // Get session data to retrieve dir_path.
109 if ( $session_id ) {
110 $session_data = SessionData::get_data( $session_id );
111 $dir_path = $session_data['dir_path'] ?? null;
112 }
113
114 // Use the common function to read AI template data if we have the required data.
115 if ( $session_id && $ai_page_ids && $dir_path ) {
116 $data['data']['ai_preview_content'] = AIUtils::read_ai_template_data( $session_id, $ai_page_ids, $dir_path );
117 } else {
118 $data['data']['ai_preview_content'] = [];
119 }
120 }
121 }
122
123 // The ajax handler returned the payload raw via `wp_send_json($data)` (no
124 // success wrapper) — `success($data)` emits the same body verbatim (200 + $data).
125 return $this->success( $data );
126 }
127 }
128