PluginProbe
Elementor Website Builder – more than just a page builder / 4.0.0-dev2
Elementor Website Builder – more than just a page builder v4.0.0-dev2
4.3.0-beta2 4.3.0-beta1 4.2.4 4.2.3 4.2.2 4.2.1 4.2.0 4.1.5 4.2.0-beta2 4.2.0-dev2 4.2.0-beta1 4.1.4 4.1.3 4.1.2 4.1.1 4.1.0 4.1.0-beta3 4.1.0-dev3 4.0.9 4.1.0-beta2 4.1.0-dev2 4.0.8 4.1.0-beta1 4.1.0-dev1 4.0.7 All 451 releases
elementor / app / modules / import-export-customization / processes / export.php

export.php in Elementor Website Builder – more than just a page builder 4.0.0-dev2, at app/modules/import-export-customization/processes/export.php

392 lines 10.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Elementor\App\Modules\ImportExportCustomization\Processes;
4
5 use Elementor\App\Modules\ImportExportCustomization\Module;
6 use Elementor\App\Modules\ImportExportCustomization\Utils;
7 use Elementor\Core\Utils\Str;
8 use Elementor\Plugin;
9
10 use Elementor\App\Modules\ImportExportCustomization\Runners\Export\Elementor_Content;
11 use Elementor\App\Modules\ImportExportCustomization\Runners\Export\Export_Runner_Base;
12 use Elementor\App\Modules\ImportExportCustomization\Runners\Export\Plugins;
13 use Elementor\App\Modules\ImportExportCustomization\Runners\Export\Site_Settings;
14 use Elementor\App\Modules\ImportExportCustomization\Runners\Export\Taxonomies;
15 use Elementor\App\Modules\ImportExportCustomization\Runners\Export\Templates;
16 use Elementor\App\Modules\ImportExportCustomization\Runners\Export\Wp_Content;
17
18 class Export {
19 const ZIP_ARCHIVE_MODULE_MISSING = 'zip-archive-module-is-missing';
20
21 /**
22 * @var Export_Runner_Base[]
23 */
24 protected $runners = [];
25
26 /**
27 * Selected content types to export.
28 *
29 * @var array
30 */
31 private $settings_include;
32
33 /**
34 * The kit information. (e.g: title, description)
35 *
36 * @var array $export_data
37 */
38 private $settings_kit_info;
39
40 /**
41 * Customization settings for selective export.
42 *
43 * @var array
44 */
45 private $settings_customization;
46
47 /**
48 * Selected plugins to export.
49 * Contains the plugins essential data for export. (e.g: name, path, version, etc.)
50 *
51 * @var array
52 */
53 private $settings_selected_plugins;
54
55 /**
56 * Selected custom post types to export.
57 *
58 * @var array
59 */
60 private $settings_selected_custom_post_types;
61
62 /**
63 * The output data of the export process.
64 * Will be written into the manifest.json file.
65 *
66 * @var array
67 */
68 private $manifest_data;
69
70 /**
71 * The zip archive object.
72 *
73 * @var \ZipArchive
74 */
75 private $zip;
76
77 public function __construct( $settings = [] ) {
78 $this->settings_include = ! empty( $settings['include'] ) ? $settings['include'] : null;
79 $this->settings_kit_info = ! empty( $settings['kitInfo'] ) ? $settings['kitInfo'] : null;
80 $this->settings_customization = isset( $settings['customization'] ) ? $settings['customization'] : null;
81 $this->settings_selected_plugins = isset( $settings['plugins'] ) ? $settings['plugins'] : null;
82 $this->settings_selected_custom_post_types = isset( $settings['customization']['content']['customPostTypes'] ) ? $settings['customization']['content']['customPostTypes'] : null;
83 }
84
85 /**
86 * Register a runner.
87 *
88 * @param Export_Runner_Base $runner_instance
89 */
90 public function register( Export_Runner_Base $runner_instance ) {
91 $this->runners[ $runner_instance::get_name() ] = $runner_instance;
92 }
93
94 public function register_default_runners() {
95 $this->register( new Site_Settings() );
96 $this->register( new Plugins() );
97 $this->register( new Templates() );
98 $this->register( new Taxonomies() );
99 $this->register( new Elementor_Content() );
100 $this->register( new Wp_Content() );
101 }
102
103 /**
104 * Execute the export process.
105 *
106 * @return array The export data output.
107 *
108 * @throws \Exception If no export runners have been specified.
109 */
110 public function run() {
111 if ( empty( $this->runners ) ) {
112 throw new \Exception( 'Couldn’t execute the export process because no export runners have been specified. Try again by specifying export runners.' );
113 }
114
115 $this->set_default_settings();
116
117 $this->init_zip_archive();
118 $this->init_manifest_data();
119
120 $data = [
121 'include' => $this->settings_include,
122 'customization' => $this->settings_customization,
123 'selected_plugins' => $this->settings_selected_plugins,
124 'selected_custom_post_types' => $this->settings_selected_custom_post_types,
125 ];
126
127 $media_collector = null;
128 if ( $this->should_collect_media( $data ) ) {
129 $media_collector = new \Elementor\TemplateLibrary\Classes\Media_Collector();
130 $media_collector->start_collection();
131 }
132
133 foreach ( $this->runners as $runner ) {
134 if ( $runner->should_export( $data ) ) {
135 $export_result = $runner->export( $data );
136 $this->handle_export_result( $export_result );
137 }
138 }
139
140 $media_urls = null;
141 if ( $media_collector ) {
142 $media_urls = $media_collector->get_collected_urls();
143 }
144
145 $this->add_json_file( 'manifest', $this->manifest_data );
146
147 $zip_file_name = $this->zip->filename;
148 $this->zip->close();
149
150 return [
151 'manifest' => $this->manifest_data,
152 'file_name' => $zip_file_name,
153 'media_urls' => $media_urls,
154 ];
155 }
156
157 /**
158 * Set default settings for the export.
159 */
160 private function set_default_settings() {
161 if ( ! is_array( $this->get_settings_include() ) ) {
162 $this->settings_include( $this->get_default_settings_include() );
163 }
164
165 if ( ! is_array( $this->get_settings_kit_info() ) ) {
166 $this->settings_kit_info( $this->get_default_settings_kit_info() );
167 }
168
169 if ( ! is_array( $this->get_settings_selected_custom_post_types() ) && in_array( 'content', $this->settings_include, true ) ) {
170 $this->settings_selected_custom_post_types( $this->get_default_settings_custom_post_types() );
171 }
172
173 if ( ! is_array( $this->get_settings_selected_plugins() ) && in_array( 'plugins', $this->settings_include, true ) ) {
174 $this->settings_selected_plugins( $this->get_default_settings_selected_plugins() );
175 }
176
177 if ( ! is_array( $this->get_settings_customization() ) ) {
178 $this->settings_customization( $this->get_default_settings_customization() );
179 }
180 }
181
182 public function settings_include( $settings_include ) {
183 $this->settings_include = $settings_include;
184 }
185
186 public function get_settings_include() {
187 return $this->settings_include;
188 }
189
190 private function settings_kit_info( $kit_info ) {
191 $this->settings_kit_info = $kit_info;
192 }
193
194 private function get_settings_kit_info() {
195 return $this->settings_kit_info;
196 }
197
198 public function settings_customization( $customization ) {
199 $this->settings_customization = $customization;
200 }
201
202 public function get_settings_customization() {
203 return $this->settings_customization;
204 }
205
206 public function settings_selected_custom_post_types( $selected_custom_post_types ) {
207 $this->settings_selected_custom_post_types = $selected_custom_post_types;
208 }
209
210 public function get_settings_selected_custom_post_types() {
211 return $this->settings_selected_custom_post_types;
212 }
213
214 public function settings_selected_plugins( $plugins ) {
215 $this->settings_selected_plugins = $plugins;
216 }
217
218 public function get_settings_selected_plugins() {
219 return $this->settings_selected_plugins;
220 }
221
222 /**
223 * Get the default settings of which content types should be exported.
224 *
225 * @return array
226 */
227 private function get_default_settings_include() {
228 return [ 'templates', 'content', 'settings', 'plugins' ];
229 }
230
231 /**
232 * Get the default settings of the kit info.
233 *
234 * @return array
235 */
236 private function get_default_settings_kit_info() {
237 return [
238 'title' => 'kit',
239 'description' => '',
240 ];
241 }
242
243 /**
244 * Get the default settings of the plugins that should be exported.
245 *
246 * @return array{name: string, plugin:string, pluginUri: string, version: string}
247 */
248 private function get_default_settings_selected_plugins() {
249 $installed_plugins = Plugin::$instance->wp->get_plugins();
250
251 $result = [];
252 foreach ( $installed_plugins->all() as $key => $item ) {
253 $plugin_key = str_replace( '.php', '', $key ); // Inconsistency between get_plugins() and WP Rest API's key format.
254
255 $result[ $plugin_key ] = [
256 'name' => $item['Name'],
257 'plugin' => $plugin_key,
258 'pluginUri' => $item['PluginURI'],
259 'version' => $item['Version'],
260 ];
261 }
262 return $result;
263 }
264
265 private function get_default_settings_customization() {
266 return [
267 'settings' => null,
268 'templates' => null,
269 'content' => [
270 'mediaFormat' => 'link',
271 ],
272 'plugins' => null,
273 ];
274 }
275
276 /**
277 * Get the default settings of all the custom post types that should be exported.
278 * Should be all the custom post types that are not built in to WordPress and not part of Elementor.
279 *
280 * @return array
281 */
282 private function get_default_settings_custom_post_types() {
283 return Utils::get_registered_cpt_names();
284 }
285
286 /**
287 * Init the zip archive.
288 *
289 * @throws \Error If export process fails, file creation errors occur, or data serialization fails.
290 */
291 private function init_zip_archive() {
292 if ( ! class_exists( '\ZipArchive' ) ) {
293 throw new \Error( static::ZIP_ARCHIVE_MODULE_MISSING ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
294 }
295
296 $zip = new \ZipArchive();
297
298 $temp_dir = Plugin::$instance->uploads_manager->create_unique_dir();
299
300 $zip_file_name = $temp_dir . sanitize_title( $this->settings_kit_info['title'] ) . '.zip';
301
302 $zip->open( $zip_file_name, \ZipArchive::CREATE | \ZipArchive::OVERWRITE );
303
304 $this->zip = $zip;
305 }
306
307 /**
308 * Init the manifest data and add some basic info to it.
309 */
310 private function init_manifest_data() {
311 $kit_post = Plugin::$instance->kits_manager->get_active_kit()->get_post();
312
313 $manifest_data = [
314 'name' => sanitize_title( $this->settings_kit_info['title'] ),
315 'title' => $this->settings_kit_info['title'],
316 'description' => $this->settings_kit_info['description'],
317 'author' => get_the_author_meta( 'display_name', $kit_post->post_author ),
318 'version' => Module::FORMAT_VERSION,
319 'elementor_version' => ELEMENTOR_VERSION,
320 'created' => gmdate( 'Y-m-d H:i:s' ),
321 'thumbnail' => get_the_post_thumbnail_url( $kit_post ),
322 'site' => get_site_url(),
323 ];
324
325 $this->manifest_data = $manifest_data;
326 }
327
328 /**
329 * Handle the export process output.
330 * Add the manifest data from the runner to the manifest.json file.
331 * Create files according to the files array that should be exported by the runner.
332 *
333 * @param array $export_result
334 */
335 private function handle_export_result( $export_result ) {
336 foreach ( $export_result['manifest'] as $data ) {
337 $this->manifest_data += $data;
338 }
339
340 if ( isset( $export_result['files']['path'] ) ) {
341 $export_result['files'] = [ $export_result['files'] ];
342 }
343
344 foreach ( $export_result['files'] as $file ) {
345 $file_extension = pathinfo( $file['path'], PATHINFO_EXTENSION );
346 if ( empty( $file_extension ) ) {
347 $this->add_json_file(
348 $file['path'],
349 $file['data']
350 );
351 } else {
352 $this->add_file(
353 $file['path'],
354 $file['data']
355 );
356 }
357 }
358 }
359
360 /**
361 * Add json file to the zip archive.
362 *
363 * @param string $path The relative path to the file.
364 * @param array $content The content of the file.
365 * @param int $json_flags
366 */
367 private function add_json_file( $path, array $content, $json_flags = 0 ) {
368 if ( ! Str::ends_with( $path, '.json' ) ) {
369 $path .= '.json';
370 }
371
372 $this->add_file( $path, wp_json_encode( $content, $json_flags ) );
373 }
374
375 /**
376 * Add file to the zip archive.
377 *
378 * @param string $file
379 * @param string $content The content of the file.
380 */
381 private function add_file( $file, $content ) {
382 $this->zip->addFromString( $file, $content );
383 }
384
385 private function should_collect_media( $data ) {
386 return (
387 isset( $data['customization']['content']['mediaFormat'] ) &&
388 'cloud' === $data['customization']['content']['mediaFormat']
389 );
390 }
391 }
392