PluginProbe
Elementor Website Builder – more than just a page builder / 4.0.5
Elementor Website Builder – more than just a page builder v4.0.5
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 / includes / template-library / classes / class-import-images.php

class-import-images.php in Elementor Website Builder – more than just a page builder 4.0.5, at includes/template-library/classes/class-import-images.php

282 lines 7.1 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\Core\Common\Modules\Ajax\Module as Ajax;
5 use Elementor\Core\Files\Uploads_Manager;
6 use Elementor\Plugin;
7 use Elementor\Utils;
8
9 if ( ! defined( 'ABSPATH' ) ) {
10 exit; // Exit if accessed directly.
11 }
12
13 /**
14 * Elementor template library import images.
15 *
16 * Elementor template library import images handler class is responsible for
17 * importing remote images used by the template library.
18 *
19 * @since 1.0.0
20 */
21 class Import_Images {
22
23 /**
24 * Replaced images IDs.
25 *
26 * The IDs of all the new imported images. An array containing the old
27 * attachment ID and the new attachment ID generated after the import.
28 *
29 * @since 1.0.0
30 * @access private
31 *
32 * @var array
33 */
34 private $_replace_image_ids = [];
35
36 /**
37 * Get image hash.
38 *
39 * Retrieve the sha1 hash of the image URL.
40 *
41 * @since 2.0.0
42 * @access private
43 *
44 * @param string $attachment_url The attachment URL.
45 *
46 * @return string Image hash.
47 */
48 private function get_hash_image( $attachment_url ) {
49 return sha1( $attachment_url );
50 }
51
52 /**
53 * Get saved image.
54 *
55 * Retrieve new image ID, if the image has a new ID after the import.
56 *
57 * @since 2.0.0
58 * @access private
59 *
60 * @param array $attachment The attachment.
61 *
62 * @return false|array New image ID or false.
63 */
64 private function get_saved_image( $attachment ) {
65 global $wpdb;
66
67 if ( isset( $this->_replace_image_ids[ $attachment['id'] ] ) ) {
68 return $this->_replace_image_ids[ $attachment['id'] ];
69 }
70
71 $post_id = $wpdb->get_var(
72 $wpdb->prepare(
73 'SELECT `post_id` FROM `' . $wpdb->postmeta . '`
74 WHERE `meta_key` = \'_elementor_source_image_hash\'
75 AND `meta_value` = %s
76 ;',
77 $this->get_hash_image( $attachment['url'] )
78 )
79 );
80
81 if ( $post_id ) {
82 $new_attachment = [
83 'id' => $post_id,
84 'url' => wp_get_attachment_url( $post_id ),
85 ];
86 $this->_replace_image_ids[ $attachment['id'] ] = $new_attachment;
87
88 return $new_attachment;
89 }
90
91 return false;
92 }
93
94 /**
95 * Import image.
96 *
97 * Import a single image from a remote server, upload the image WordPress
98 * uploads folder, create a new attachment in the database and updates the
99 * attachment metadata.
100 *
101 * @since 1.0.0
102 * @since 3.2.0 New `$parent_post_id` option added
103 * @access public
104 *
105 * @param array $attachment The attachment.
106 * @param int $parent_post_id Optional.
107 *
108 * @return false|array Imported image data, or false.
109 */
110 public function import( $attachment, $parent_post_id = null ) {
111 if ( isset( $attachment['tmp_name'] ) ) {
112 // Used when called to import a directly-uploaded file.
113 $filename = $attachment['name'];
114 $file_content = false;
115
116 // security validation in case the tmp_name has been tampered with
117 if ( is_uploaded_file( $attachment['tmp_name'] ) ) {
118 $file_content = Utils::file_get_contents( $attachment['tmp_name'] );
119 }
120 } else {
121 // Used when attachment information is passed to this method.
122 if ( ! empty( $attachment['id'] ) ) {
123 $saved_image = $this->get_saved_image( $attachment );
124
125 if ( $saved_image ) {
126 return $saved_image;
127 }
128 }
129
130 // Extract the file name and extension from the url.
131 $filename = basename( $attachment['url'] );
132
133 $request = wp_safe_remote_get( $attachment['url'] );
134
135 // Make sure the request returns a valid result.
136 if ( is_wp_error( $request ) || ( ! empty( $request['response']['code'] ) && 200 !== (int) $request['response']['code'] ) ) {
137 return false;
138 }
139
140 $file_content = wp_remote_retrieve_body( $request );
141 }
142
143 if ( empty( $file_content ) ) {
144 return false;
145 }
146
147 $filetype = wp_check_filetype( $filename );
148
149 // If the file type is not recognized by WordPress, exit here to avoid creation of an empty attachment document.
150 if ( ! $filetype['ext'] ) {
151 return false;
152 }
153
154 if ( 'svg' === $filetype['ext'] ) {
155 // In case that unfiltered-files upload is not enabled, SVG images should not be imported.
156 if ( ! Uploads_Manager::are_unfiltered_uploads_enabled() ) {
157 return false;
158 }
159
160 $svg_handler = Plugin::$instance->uploads_manager->get_file_type_handlers( 'svg' );
161
162 $file_content = $svg_handler->sanitizer( $file_content );
163 }
164
165 $upload = wp_upload_bits(
166 $filename,
167 null,
168 $file_content
169 );
170
171 $post = [
172 'post_title' => $filename,
173 'guid' => $upload['url'],
174 ];
175
176 $info = wp_check_filetype( $upload['file'] );
177
178 if ( $info ) {
179 $post['post_mime_type'] = $info['type'];
180 } else {
181 // For now just return the origin attachment
182 return $attachment;
183 // return new \WP_Error( 'attachment_processing_error', esc_html__( 'Invalid file type.', 'elementor' ) );
184 }
185
186 $post_id = wp_insert_attachment( $post, $upload['file'], $parent_post_id );
187
188 apply_filters( 'elementor/template_library/import_images/new_attachment', $post_id );
189
190 // On REST requests.
191 if ( ! function_exists( 'wp_generate_attachment_metadata' ) ) {
192 require_once ABSPATH . '/wp-admin/includes/image.php';
193 }
194
195 if ( ! function_exists( 'wp_read_video_metadata' ) ) {
196 require_once ABSPATH . '/wp-admin/includes/media.php';
197 }
198
199 wp_update_attachment_metadata(
200 $post_id,
201 wp_generate_attachment_metadata( $post_id, $upload['file'] )
202 );
203 update_post_meta( $post_id, '_elementor_source_image_hash', $this->get_hash_image( $attachment['url'] ) );
204
205 $new_attachment = [
206 'id' => $post_id,
207 'url' => $upload['url'],
208 ];
209
210 if ( ! empty( $attachment['id'] ) ) {
211 $this->_replace_image_ids[ $attachment['id'] ] = $new_attachment;
212 }
213
214 return $new_attachment;
215 }
216
217 /**
218 * Import local file.
219 *
220 * Import a local file directly to WordPress media library.
221 * Used for importing files that are already downloaded locally (e.g., from extracted ZIP).
222 *
223 * @since 3.33.0
224 * @access public
225 *
226 * @param string $local_file_path The local file path.
227 * @param int $parent_post_id Optional. Parent post ID.
228 *
229 * @return false|array Imported image data, or false on failure.
230 */
231 public function import_local_file( $local_file_path, $parent_post_id = null ) {
232 global $wp_filesystem;
233
234 if ( ! $wp_filesystem->exists( $local_file_path ) ) {
235 return false;
236 }
237
238 if ( ! function_exists( 'media_handle_sideload' ) ) {
239 require_once ABSPATH . 'wp-admin/includes/media.php';
240 }
241
242 if ( ! function_exists( 'wp_generate_attachment_metadata' ) ) {
243 require_once ABSPATH . 'wp-admin/includes/image.php';
244 }
245
246 $file_array = [
247 'name' => basename( $local_file_path ),
248 'tmp_name' => $local_file_path,
249 ];
250
251 $attachment_id = media_handle_sideload( $file_array, $parent_post_id );
252
253 if ( is_wp_error( $attachment_id ) ) {
254 return false;
255 }
256
257 apply_filters( 'elementor/template_library/import_images/new_attachment', $attachment_id );
258
259 return [
260 'id' => $attachment_id,
261 'url' => wp_get_attachment_url( $attachment_id ),
262 ];
263 }
264
265 /**
266 * Template library import images constructor.
267 *
268 * Initializing the images import class used by the template library through
269 * the WordPress Filesystem API.
270 *
271 * @since 1.0.0
272 * @access public
273 */
274 public function __construct() {
275 if ( ! function_exists( 'WP_Filesystem' ) ) {
276 require_once ABSPATH . 'wp-admin/includes/file.php';
277 }
278
279 WP_Filesystem();
280 }
281 }
282