/var/www/html_us/wp-content/plugins/elementor/includes/template-library/sources/remote.php


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
<?php
namespace Elementor\TemplateLibrary;

use 
Elementor\Api;
use 
Elementor\Core\Common\Modules\Connect\Module as ConnectModule;
use 
Elementor\Plugin;

if ( ! 
defined'ABSPATH' ) ) {
    exit; 
// Exit if accessed directly.
}

/**
 * Elementor template library remote source.
 *
 * Elementor template library remote source handler class is responsible for
 * handling remote templates from Elementor.com servers.
 *
 * @since 1.0.0
 */
class Source_Remote extends Source_Base {

    const 
API_TEMPLATES_URL 'https://my.elementor.com/api/connect/v1/library/templates';

    const 
TEMPLATES_DATA_TRANSIENT_KEY_PREFIX 'elementor_remote_templates_data_';

    public function 
__construct() {
        
parent::__construct();

        
$this->add_actions();
    }

    public function 
add_actions() {
        
add_action'elementor/experiments/feature-state-change/container', [ $this'clear_cache' ], 10);
    }

    
/**
     * Get remote template ID.
     *
     * Retrieve the remote template ID.
     *
     * @since 1.0.0
     * @access public
     *
     * @return string The remote template ID.
     */
    
public function get_id() {
        return 
'remote';
    }

    
/**
     * Get remote template title.
     *
     * Retrieve the remote template title.
     *
     * @since 1.0.0
     * @access public
     *
     * @return string The remote template title.
     */
    
public function get_title() {
        return 
esc_html__'Remote''elementor' );
    }

    
/**
     * Register remote template data.
     *
     * Used to register custom template data like a post type, a taxonomy or any
     * other data.
     *
     * @since 1.0.0
     * @access public
     */
    
public function register_data() {}

    
/**
     * Get remote templates.
     *
     * Retrieve remote templates from Elementor.com servers.
     *
     * @since 1.0.0
     * @access public
     *
     * @param array $args Optional. Not used in remote source.
     *
     * @return array Remote templates.
     */
    
public function get_items$args = [] ) {
        
$force_update = ! empty( $args['force_update'] ) && is_bool$args['force_update'] );

        
$templates_data $this->get_templates_data$force_update );

        
$templates = [];

        foreach ( 
$templates_data as $template_data ) {
            
$templates[] = $this->prepare_template$template_data );
        }

        return 
$templates;
    }

    
/**
     * Get remote template.
     *
     * Retrieve a single remote template from Elementor.com servers.
     *
     * @since 1.0.0
     * @access public
     *
     * @param int $template_id The template ID.
     *
     * @return array Remote template.
     */
    
public function get_item$template_id ) {
        
$templates $this->get_items();

        return 
$templates$template_id ];
    }

    
/**
     * Save remote template.
     *
     * Remote template from Elementor.com servers cannot be saved on the
     * database as they are retrieved from remote servers.
     *
     * @since 1.0.0
     * @access public
     *
     * @param array $template_data Remote template data.
     *
     * @return \WP_Error
     */
    
public function save_item$template_data ) {
        return new 
\WP_Error'invalid_request''Cannot save template to a remote source' );
    }

    
/**
     * Update remote template.
     *
     * Remote template from Elementor.com servers cannot be updated on the
     * database as they are retrieved from remote servers.
     *
     * @since 1.0.0
     * @access public
     *
     * @param array $new_data New template data.
     *
     * @return \WP_Error
     */
    
public function update_item$new_data ) {
        return new 
\WP_Error'invalid_request''Cannot update template to a remote source' );
    }

    
/**
     * Delete remote template.
     *
     * Remote template from Elementor.com servers cannot be deleted from the
     * database as they are retrieved from remote servers.
     *
     * @since 1.0.0
     * @access public
     *
     * @param int $template_id The template ID.
     *
     * @return \WP_Error
     */
    
public function delete_template$template_id ) {
        return new 
\WP_Error'invalid_request''Cannot delete template from a remote source' );
    }

    
/**
     * Export remote template.
     *
     * Remote template from Elementor.com servers cannot be exported from the
     * database as they are retrieved from remote servers.
     *
     * @since 1.0.0
     * @access public
     *
     * @param int $template_id The template ID.
     *
     * @return \WP_Error
     */
    
public function export_template$template_id ) {
        return new 
\WP_Error'invalid_request''Cannot export template from a remote source' );
    }

    
/**
     * Get remote template data.
     *
     * Retrieve the data of a single remote template from Elementor.com servers.
     *
     * @since 1.5.0
     * @access public
     *
     * @param array  $args    Custom template arguments.
     * @param string $context Optional. The context. Default is `display`.
     *
     * @return array|\WP_Error Remote Template data.
     */
    
public function get_data( array $args$context 'display' ) {
        
$data Api::get_template_content$args['template_id'] );

        if ( 
is_wp_error$data ) ) {
            return 
$data;
        }

        
// Set the Request's state as an Elementor upload request, in order to support unfiltered file uploads.
        
Plugin::$instance->uploads_manager->set_elementor_upload_statetrue );

        
// BC.
        
$data = (array) $data;

        
$data['content'] = $this->replace_elements_ids$data['content'] );
        
$data['content'] = $this->process_export_import_content$data['content'], 'on_import' );

        
$post_id $args['editor_post_id'];
        
$document Plugin::$instance->documents->get$post_id );
        if ( 
$document ) {
            
$data['content'] = $document->get_elements_raw_data$data['content'], true );
        }

        
// After the upload complete, set the elementor upload state back to false
        
Plugin::$instance->uploads_manager->set_elementor_upload_statefalse );

        return 
$data;
    }

    
/**
     * Get templates data from a transient or from a remote request.
     * In any of the following 2 conditions, the remote request will be triggered:
     * 1. Force update - "$force_update = true" parameter was passed.
     * 2. The data saved in the transient is empty or not exist.
     *
     * @param bool $force_update
     * @return array
     */
    
protected function get_templates_databool $force_update ) : array {
        
$templates_data_cache_key = static::TEMPLATES_DATA_TRANSIENT_KEY_PREFIX ELEMENTOR_VERSION;

        
$experiments_manager Plugin::$instance->experiments;
        
$editor_layout_type $experiments_manager->is_feature_active'container' ) ? 'container_flexbox' '';

        if ( 
$force_update ) {
            return 
$this->get_templates$editor_layout_type );
        }

        
$templates_data get_transient$templates_data_cache_key );

        if ( empty( 
$templates_data ) ) {
            return 
$this->get_templates$editor_layout_type );
        }

        return 
$templates_data;
    }

    
/**
     * Get the templates from a remote server and set a transient.
     *
     * @param string $editor_layout_type
     * @return array
     */
    
protected function get_templatesstring $editor_layout_type ): array {
        
$templates_data_cache_key = static::TEMPLATES_DATA_TRANSIENT_KEY_PREFIX ELEMENTOR_VERSION;

        
$templates_data $this->get_templates_remotely$editor_layout_type );

        if ( empty( 
$templates_data ) ) {
            return [];
        }

        
set_transient$templates_data_cache_key$templates_data12 HOUR_IN_SECONDS );

        return 
$templates_data;
    }

    
/**
     * Fetch templates from the remote server.
     *
     * @param string $editor_layout_type
     * @return array|false
     */
    
protected function get_templates_remotelystring $editor_layout_type ) {
        
$response wp_remote_get( static::API_TEMPLATES_URL, [
            
'body' => $this->get_templates_body_args$editor_layout_type ),
        ] );

        if ( 
is_wp_error$response ) || 200 !== (int) wp_remote_retrieve_response_code$response ) ) {
            return 
false;
        }

        
$templates_data json_decodewp_remote_retrieve_body$response ), true );

        if ( empty( 
$templates_data ) || ! is_array$templates_data ) ) {
            return [];
        }

        return 
$templates_data;
    }

    
/**
     * Prepare the body arguments for the remote request.
     * @param string $editor_layout_type
     *
     * @return array
     */
    
protected function get_templates_body_argsstring $editor_layout_type ): array {
        return [
            
'plugin_version' => ELEMENTOR_VERSION,
            
'editor_layout_type' => $editor_layout_type,
        ];
    }

    
/**
     * @since 2.2.0
     * @access private
     */
    
protected function prepare_template( array $template_data ) {
        
$favorite_templates $this->get_user_meta'favorites' );

        
// BC: Support legacy APIs that don't have access tiers.
        
if ( isset( $template_data['access_tier'] ) ) {
            
$access_tier $template_data['access_tier'];
        } else {
            
$access_tier === $template_data['access_level']
                ? 
ConnectModule::ACCESS_TIER_FREE
                
ConnectModule::ACCESS_TIER_ESSENTIAL;
        }

        return [
            
'template_id' => $template_data['id'],
            
'source' => $this->get_id(),
            
'type' => $template_data['type'],
            
'subtype' => $template_data['subtype'],
            
'title' => $template_data['title'],
            
'thumbnail' => $template_data['thumbnail'],
            
'date' => $template_data['tmpl_created'],
            
'author' => $template_data['author'],
            
'tags' => json_decode$template_data['tags'] ),
            
'isPro' => ( '1' === $template_data['is_pro'] ),
            
'accessLevel' => $template_data['access_level'],
            
'accessTier' => $access_tier,
            
'popularityIndex' => (int) $template_data['popularity_index'],
            
'trendIndex' => (int) $template_data['trend_index'],
            
'hasPageSettings' => ( '1' === $template_data['has_page_settings'] ),
            
'url' => $template_data['url'],
            
'favorite' => ! empty( $favorite_templates$template_data['id'] ] ),
        ];
    }

    public function 
clear_cache() {
        
delete_transient( static::TEMPLATES_DATA_TRANSIENT_KEY_PREFIX ELEMENTOR_VERSION );
    }
}