PluginProbe
Elementor Website Builder – more than just a page builder / 3.35.0-dev1
Elementor Website Builder – more than just a page builder v3.35.0-dev1
4.3.0-beta3 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 All 452 releases
elementor / includes / template-library / classes / class-media-collector.php

class-media-collector.php in Elementor Website Builder – more than just a page builder 3.35.0-dev1, at includes/template-library/classes/class-media-collector.php

243 lines 6.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Elementor\TemplateLibrary\Classes;
3
4 use Elementor\Utils;
5
6 if ( ! defined( 'ABSPATH' ) ) {
7 exit; // Exit if accessed directly.
8 }
9
10 /**
11 * Elementor media collector.
12 *
13 * Collects media URLs during export and creates a media ZIP file.
14 */
15 class Media_Collector {
16
17 /**
18 * Filename for the media mapping JSON file within the ZIP.
19 */
20 private const MAPPING_FILENAME = 'media-mapping.json';
21
22 /**
23 * Collected media URLs and their metadata.
24 *
25 * @var array
26 */
27 private $collected_media = [];
28
29 /**
30 * Temporary directory for media files.
31 *
32 * @var string
33 */
34 private $temp_dir = '';
35
36 public function __construct() {
37 add_action( 'elementor/templates/collect_media_url', [ $this, 'collect_media_url' ], 10, 2 );
38 }
39
40 /**
41 * Start media collection for export (Step 1: Collect URLs).
42 */
43 public function start_collection() {
44 $this->collected_media = [];
45 }
46
47 /**
48 * Start media processing (Step 2: Download media files and create zip).
49 */
50 public function start_processing() {
51 $this->temp_dir = \Elementor\Plugin::$instance->uploads_manager->create_unique_dir();
52 }
53
54 public function collect_media_url( string $url, array $media_data = [] ) {
55 if ( ! $this->is_media_url( $url ) || isset( $this->collected_media[ $url ] ) ) {
56 return;
57 }
58
59 $this->collected_media[ $url ] = true;
60 }
61
62 /**
63 * Process a single media URL (Step 2: Download and save).
64 */
65 public function process_media_url( string $url ) {
66 if ( ! $this->is_media_url( $url ) ) {
67 return false;
68 }
69
70 $local_filename = $this->download_and_save_media( $url );
71 if ( $local_filename ) {
72 $this->collected_media[ $url ] = $local_filename;
73 return $local_filename;
74 }
75
76 return false;
77 }
78
79 private function download_and_save_media( string $url ) {
80 if ( $this->is_local_url( $url ) ) {
81 $local_file_path = $this->get_local_file_path( $url );
82 if ( $local_file_path && file_exists( $local_file_path ) ) {
83 return $this->copy_local_file( $local_file_path, $url );
84 }
85 }
86
87 return $this->download_via_http( $url );
88 }
89
90 private function is_local_url( string $url ): bool {
91 $site_url = get_site_url();
92 $home_url = get_home_url();
93
94 return strpos( $url, $site_url ) === 0 || strpos( $url, $home_url ) === 0;
95 }
96
97 private function get_local_file_path( string $url ) {
98 $site_url = get_site_url();
99 $home_url = get_home_url();
100
101 $relative_path = str_replace( [ $site_url, $home_url ], '', $url );
102 $relative_path = ltrim( $relative_path, '/' );
103
104 $upload_dir = wp_upload_dir();
105 $uploads_path = $upload_dir['basedir'];
106
107 $possible_paths = [
108 $uploads_path . '/' . $relative_path,
109 ABSPATH . $relative_path,
110 $uploads_path . '/' . basename( $url ),
111 ];
112
113 foreach ( $possible_paths as $path ) {
114 if ( file_exists( $path ) ) {
115 return $path;
116 }
117 }
118
119 return false;
120 }
121
122 private function copy_local_file( string $source_path, string $original_url ) {
123 $original_filename = basename( $original_url );
124 $extension = pathinfo( $original_filename, PATHINFO_EXTENSION );
125 $name_without_extension = pathinfo( $original_filename, PATHINFO_FILENAME );
126 $unique_filename = sanitize_file_name( $name_without_extension . '_' . uniqid() . '.' . $extension );
127
128 $destination_path = $this->temp_dir . '/' . $unique_filename;
129 $copied = copy( $source_path, $destination_path );
130
131 return $copied ? $unique_filename : false;
132 }
133
134 private function download_via_http( string $url ) {
135 $response = wp_safe_remote_get( $url, [
136 'timeout' => 30,
137 'user-agent' => 'Elementor Template Exporter',
138 ] );
139
140 if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) {
141 return false;
142 }
143
144 $file_content = wp_remote_retrieve_body( $response );
145 if ( empty( $file_content ) ) {
146 return false;
147 }
148
149 $original_filename = basename( $url );
150 $extension = pathinfo( $original_filename, PATHINFO_EXTENSION );
151 $name_without_extension = pathinfo( $original_filename, PATHINFO_FILENAME );
152 $unique_filename = sanitize_file_name( $name_without_extension . '_' . uniqid() . '.' . $extension );
153
154 $file_path = $this->temp_dir . '/' . $unique_filename;
155 $saved = file_put_contents( $file_path, $file_content );
156
157 return $saved ? $unique_filename : false;
158 }
159
160 public function get_collected_urls(): array {
161 return array_keys( $this->collected_media );
162 }
163
164 public function process_media_collection( array $media_urls ) {
165 $this->start_processing();
166
167 foreach ( $media_urls as $url ) {
168 $this->process_media_url( $url );
169 }
170
171 return $this->create_media_zip();
172 }
173
174 public function create_media_zip() {
175 if ( empty( $this->collected_media ) ) {
176 return null;
177 }
178
179 if ( ! class_exists( '\ZipArchive' ) ) {
180 return null;
181 }
182
183 $zip = new \ZipArchive();
184 $zip_filename = 'media-' . uniqid() . '.zip';
185 $zip_path = $this->temp_dir . '/' . $zip_filename;
186
187 if ( $zip->open( $zip_path, \ZipArchive::CREATE ) !== true ) {
188 return null;
189 }
190
191 $mapping = [];
192
193 foreach ( $this->collected_media as $url => $filename ) {
194 if ( is_string( $filename ) ) {
195 $file_path = $this->temp_dir . '/' . $filename;
196 if ( file_exists( $file_path ) ) {
197 $zip->addFile( $file_path, $filename );
198 $mapping[ $url ] = $filename;
199 }
200 }
201 }
202
203 if ( empty( $mapping ) ) {
204 $zip->close();
205 return null;
206 }
207
208 $mapping_json = wp_json_encode( $mapping, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES );
209 $zip->addFromString( self::MAPPING_FILENAME, $mapping_json );
210 $zip->close();
211
212 return $zip_path;
213 }
214
215 public function cleanup() {
216 if ( $this->temp_dir ) {
217 \Elementor\Plugin::$instance->uploads_manager->remove_file_or_dir( $this->temp_dir );
218 }
219 }
220
221 private function is_media_url( $url ) {
222 if ( ! is_string( $url ) || empty( $url ) ) {
223 return false;
224 }
225
226 if ( strpos( $url, 'data:' ) === 0 ) {
227 return false;
228 }
229
230 $allowed_mime_types = get_allowed_mime_types();
231 $file_extension = strtolower( pathinfo( $url, PATHINFO_EXTENSION ) );
232
233 foreach ( $allowed_mime_types as $pattern => $mime_type ) {
234 $pattern_regex = '/^(' . str_replace( '|', '|', $pattern ) . ')$/i';
235 if ( preg_match( $pattern_regex, $file_extension ) ) {
236 return true;
237 }
238 }
239
240 return false;
241 }
242 }
243