Skip to content

Commit 7b36131

Browse files
committed
side load images
1 parent cdb2c1f commit 7b36131

File tree

1 file changed

+172
-0
lines changed

1 file changed

+172
-0
lines changed

includes/Services/SiteGenService.php

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
use NewfoldLabs\WP\Module\Onboarding\Data\Services\SitePagesService;
66
use NewfoldLabs\WP\Module\Onboarding\Data\Services\SiteGenService as LegacySiteGenService;
7+
use NewfoldLabs\WP\Module\Onboarding\Data\Services\ThemeGeneratorService;
8+
use NewfoldLabs\WP\Module\Onboarding\Services\ReduxStateService;
79

810
class SiteGenService {
911

@@ -64,6 +66,17 @@ public function publish_homepage( string $selected_sitegen_homepage ): int | \WP
6466
);
6567
}
6668

69+
// Process images by extracting URLs from img tags in the content and update the post
70+
$updated_content = self::sideload_images_and_replace_grammar( $content, $post_id );
71+
if ( $updated_content !== $content ) {
72+
wp_update_post(
73+
array(
74+
'ID' => $post_id,
75+
'post_content' => $updated_content,
76+
)
77+
);
78+
}
79+
6780
// Add the homepage to the site navigation.
6881
$this->add_page_to_navigation( $post_id, $title, get_permalink( $post_id ) );
6982

@@ -161,4 +174,163 @@ public function get_site_type(): string {
161174
public function get_locale(): string {
162175
return ! empty( $this->input_data['locale'] ) ? $this->input_data['locale'] : 'en_US';
163176
}
177+
178+
/**
179+
* Uploads images to the WordPress media library as attachments.
180+
*
181+
* This function takes an array of image URLs, downloads them, and
182+
* uploads them to the WordPress media library, returning the URLs
183+
* of the newly uploaded images.
184+
*
185+
* @param array $image_urls An array of image URLs to upload.
186+
* @param int $post_id The post ID to attach the images to.
187+
* @return array|false An array of WordPress attachment URLs on success, false on failure.
188+
* @throws Exception If there is an error during the upload process.
189+
*/
190+
public static function upload_images_to_wp_media_library( $image_urls, $post_id ) {
191+
require_once ABSPATH . 'wp-admin/includes/media.php';
192+
require_once ABSPATH . 'wp-admin/includes/image.php';
193+
194+
global $wp_filesystem;
195+
ThemeGeneratorService::connect_to_filesystem();
196+
197+
$uploaded_image_urls = array();
198+
try {
199+
foreach ( $image_urls as $image_url ) {
200+
// Check if the URL is valid.
201+
if ( ! filter_var( $image_url, FILTER_VALIDATE_URL ) ) {
202+
continue;
203+
}
204+
205+
// Fetch the image via remote get with timeout and a retry attempt.
206+
$attempt = 0;
207+
$max_attempts = 2;
208+
while ( $attempt < $max_attempts ) {
209+
$response = wp_remote_get( $image_url, array( 'timeout' => 15 ) );
210+
if ( ! is_wp_error( $response ) && 200 === wp_remote_retrieve_response_code( $response ) ) {
211+
break;
212+
}
213+
++$attempt;
214+
}
215+
if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) {
216+
continue;
217+
}
218+
// Reading the headers from the image url to determine.
219+
$headers = wp_remote_retrieve_headers( $response );
220+
$content_type = $headers['content-type'] ?? '';
221+
$image_data = wp_remote_retrieve_body( $response );
222+
if ( empty( $content_type ) || empty( $image_data ) ) {
223+
continue;
224+
}
225+
// Determine the file extension based on MIME type.
226+
$file_extension = '';
227+
switch ( $content_type ) {
228+
case 'image/jpeg':
229+
$file_extension = '.jpg';
230+
break;
231+
case 'image/png':
232+
$file_extension = '.png';
233+
break;
234+
case 'image/gif':
235+
$file_extension = '.gif';
236+
break;
237+
case 'image/webp':
238+
$file_extension = '.webp';
239+
break;
240+
}
241+
242+
if ( '' === $file_extension ) {
243+
continue;
244+
}
245+
// create upload directory.
246+
$upload_dir = wp_upload_dir();
247+
// xtract a filename from the URL.
248+
$parsed_url = wp_parse_url( $image_url );
249+
$path_parts = pathinfo( $parsed_url['path'] );
250+
// filename to be added in directory.
251+
$original_filename = $path_parts['filename'] . $file_extension;
252+
253+
// to ensure the filename is unique within the upload directory.
254+
$filename = wp_unique_filename( $upload_dir['path'], $original_filename );
255+
$filepath = $upload_dir['path'] . '/' . $filename;
256+
257+
$wp_filesystem->put_contents( $filepath, $image_data );
258+
259+
// Create an attachment post for the image, metadata needed for WordPress media library.
260+
// guid -for url, post_title for cleaned up name, post content is empty as this is an attachment.
261+
// post_status inherit is for visibility.
262+
$attachment = array(
263+
'guid' => $upload_dir['url'] . '/' . $filename,
264+
'post_mime_type' => $content_type,
265+
'post_title' => preg_replace( '/\.[^.]+$/', '', basename( $filename ) ),
266+
'post_content' => '',
267+
'post_status' => 'inherit',
268+
'post_parent' => $post_id, // Attach to the specified post
269+
);
270+
$attach_id = wp_insert_attachment( $attachment, $filepath );
271+
272+
// Generate and assign metadata for the attachment.
273+
$attach_data = wp_generate_attachment_metadata( $attach_id, $filepath );
274+
wp_update_attachment_metadata( $attach_id, $attach_data );
275+
276+
// Add the WordPress attachment URL to the list.
277+
if ( $attach_id ) {
278+
$attachment_url = wp_get_attachment_url( $attach_id );
279+
if ( ! $attachment_url ) {
280+
$attachment_url = null;
281+
}
282+
$uploaded_image_urls[ $image_url ] = $attachment_url;
283+
}
284+
}
285+
} catch ( \Exception $e ) {
286+
// Log error.
287+
}
288+
289+
return $uploaded_image_urls;
290+
}
291+
292+
/**
293+
* Extract image URLs from content and upload them to WordPress media library.
294+
*
295+
* This function extracts image URLs from img tags in the content, uploads the images
296+
* to the WordPress media library, and then replaces the old image URLs in the content
297+
* with the new ones.
298+
*
299+
* @param string $content The content containing img tags with image URLs.
300+
* @param int $post_id The post ID to attach the images to.
301+
* @return string The updated content with new image URLs.
302+
*/
303+
public static function sideload_images_and_replace_grammar( $content, $post_id ) {
304+
// Extract image URLs from img tags in the content
305+
$image_urls = array();
306+
preg_match_all( '/<img[^>]+src=["\']([^"\']+)["\'][^>]*>/i', $content, $matches );
307+
308+
if ( ! empty( $matches[1] ) ) {
309+
$image_urls = array_unique( $matches[1] );
310+
}
311+
312+
if ( empty( $image_urls ) ) {
313+
return $content;
314+
}
315+
316+
// Upload the images to WordPress media library.
317+
$url_mapping = self::upload_images_to_wp_media_library( $image_urls, $post_id );
318+
319+
foreach ( $url_mapping as $old_url => $new_url ) {
320+
if ( null === $new_url ) {
321+
continue;
322+
}
323+
// escaping any special characters in the old URL to avoid breaking the regex.
324+
$escaped_old_url = preg_quote( $old_url, '/' );
325+
326+
$escaped_old_url_regex_double_quote = '/"' . $escaped_old_url . '.*?"/m';
327+
$content = preg_replace( $escaped_old_url_regex_double_quote, '"' . $new_url . '"', $content );
328+
329+
$escaped_old_url_regex_parenthesis = '/\(' . $escaped_old_url . '.*?\)/m';
330+
$content = preg_replace( $escaped_old_url_regex_parenthesis, '(' . $new_url . ')', $content );
331+
}
332+
333+
// Update the content with new image URLs.
334+
return $content;
335+
}
164336
}

0 commit comments

Comments
 (0)