html_string = str_replace( '\"' , '' , $html_string); } /** * Extract all html needed info from text */ public function parse(){ if( trim($this->html_string) == '' ){ return false; } $doc = new DOMDocument('1.0', 'UTF-8'); libxml_use_internal_errors(true); $doc->loadHTML( mb_convert_encoding($this->html_string, 'HTML-ENTITIES', 'UTF-8'), (defined('LIBXML_HTML_NOIMPLIED') ? LIBXML_HTML_NOIMPLIED : 0) | (defined('LIBXML_HTML_NODEFDTD') ? LIBXML_HTML_NODEFDTD : 0) ); // find all img tags $elementImg = $doc->getElementsByTagName('img'); $elementImgSrc = []; foreach ($elementImg as $index => $value){ $alt = $value->getAttribute('alt'); // Replace dangerous double quotes inside alt with safe quotes $fixedAlt = str_replace(['"', '\'', '\\'], ['«', ' ', ' '], $alt); $value->setAttribute('alt', $fixedAlt); $raw_base64_src = str_replace('\"' , '' , $value->getAttribute('src')); //upload image on server instead of using base64 url $uploaded_url = $this->uploadImageWithFallback($raw_base64_src, "rp-img-".wp_rand(1 , 100000)); if( !$uploaded_url ){ // remove image $value->parentNode->removeChild($value); continue; } else { $value->setAttribute('src' , $uploaded_url); $elementImgSrc[] = [ 'src' => $uploaded_url, 'alt' => $fixedAlt]; } } $lengthImg = count($elementImgSrc); // find all H1 tags $elementH1= $doc->getElementsByTagName('h1'); foreach ($elementH1 as $index => $value){ // remove H1 $parentNode = $value->parentNode; $parentNode->removeChild($value); } $elementH2= $doc->getElementsByTagName('h2'); $elementArrayH2 = []; foreach ($elementH2 as $index => $value){ if( $value->firstChild->tagName == 'img' ){ $alt = $value->firstChild->getAttribute('alt'); // Replace dangerous double quotes inside alt with safe quotes $fixedAlt = str_replace(['"', '\'', '\\'], ['«', ' ', ' '], $alt); $value->firstChild->setAttribute('alt', $fixedAlt); $raw_base64_src = str_replace('\"' , '' , $value->firstChild->getAttribute('src')); // upload image on server instead of using base64 url $uploaded_url = $this->uploadImageWithFallback($raw_base64_src, "rp-img-".wp_rand(1 , 100000)); if ( !$uploaded_url ) { // remove image if we still can't upload it $parentNode = $value->parentNode; $parentNode->removeChild($value); continue; } $value->firstChild->setAttribute('src' , $uploaded_url); $elementImgSrc[] = [ 'src' => $uploaded_url, 'alt' => $fixedAlt ]; // make image centered! $value->firstChild->setAttribute('style' , 'margin: auto;display: block;border-radius: 20px;max-width: 100%'); $value->firstChild->setAttribute('width' , "100%"); // save this image at this location in html $snippetH2 .= $value->firstChild->ownerDocument->saveHTML($value->firstChild); $elementArrayH2[] = $snippetH2; continue; } else { // if H2 is Not Empty if( trim($value->nodeValue) !== "" ){ $elementArrayH2[] = $value->nodeValue; $snippetH2 .= $value->nodeValue; } else { // remove empty H2 $parentNode = $value->parentNode; $parentNode->removeChild($value); } } } $lengthH2 = count($elementArrayH2); $explodeH2 = explode(' ' ,$snippetH2); $explodeCountH2 = count($explodeH2); $elementH3= $doc->getElementsByTagName('h3'); $elementArrayH3 = []; foreach ($elementH3 as $index => $value){ if( $value->firstChild->tagName == 'img' ){ $alt = $value->firstChild->getAttribute('alt'); // Replace dangerous double quotes inside alt with safe quotes $fixedAlt = str_replace(['"', '\'', '\\'], ['«', ' ', ' '], $alt); $value->firstChild->setAttribute('alt', $fixedAlt); $raw_base64_src = str_replace('\"' , '' , $value->firstChild->getAttribute('src')); // upload image on server instead of using base64 url $uploaded_url = $this->uploadImageWithFallback($raw_base64_src, "rp-img-".wp_rand(1 , 100000)); if ( !$uploaded_url ) { // remove image if we still can't upload it $parentNode = $value->parentNode; $parentNode->removeChild($value); continue; } $value->firstChild->setAttribute('src' , $uploaded_url); $elementImgSrc[] = [ 'src' => $uploaded_url, 'alt' => $fixedAlt ]; // make image centered! $value->firstChild->setAttribute('style' , 'margin: auto;display: block;border-radius: 20px;max-width: 100%'); $value->firstChild->setAttribute('width' , "100%"); // save this image at this location in html $snippetH3 .= $value->firstChild->ownerDocument->saveHTML($value->firstChild); $elementArrayH3[] = $snippetH3; continue; } else { // if H3 is Not Empty if( trim($value->nodeValue) !== "" ){ $elementArrayH3[] = $value->nodeValue; $snippetH3 .= $value->nodeValue; } else { // remove empty H3 $parentNode = $value->parentNode; $parentNode->removeChild($value); } } } $lengthH3 = count($elementArrayH3); $explodeH3 = explode(' ' ,$snippetH3); $explodeCountH3 = count($explodeH3); $elementH4= $doc->getElementsByTagName('h4'); $elementArrayH4 = []; foreach ($elementH4 as $index => $value){ if( $value->firstChild->tagName == 'img' ){ $alt = $value->firstChild->getAttribute('alt'); // Replace dangerous double quotes inside alt with safe quotes $fixedAlt = str_replace(['"', '\'', '\\'], ['«', ' ', ' '], $alt); $value->firstChild->setAttribute('alt', $fixedAlt); $raw_base64_src = str_replace('\"' , '' , $value->firstChild->getAttribute('src')); // upload image on server instead of using base64 url $uploaded_url = $this->uploadImageWithFallback($raw_base64_src, "rp-img-".wp_rand(1 , 100000)); if ( !$uploaded_url ) { // remove image if we still can't upload it $parentNode = $value->parentNode; $parentNode->removeChild($value); continue; } $value->firstChild->setAttribute('src' , $uploaded_url); $elementImgSrc[] = [ 'src' => $uploaded_url, 'alt' => $fixedAlt ]; // make image centered! $value->firstChild->setAttribute('style' , 'margin: auto;display: block;border-radius: 20px;max-width: 100%'); $value->firstChild->setAttribute('width' , "100%"); // save this image at this location in html $snippetH4 .= $value->firstChild->ownerDocument->saveHTML($value->firstChild); $elementArrayH4[] = $snippetH4; continue; } else { // if H4 is Not Empty if( trim($value->nodeValue) !== "" ){ $elementArrayH4[] = $value->nodeValue; $snippetH4 .= $value->nodeValue; } else { // remove empty H4 $parentNode = $value->parentNode; $parentNode->removeChild($value); } } } $lengthH4 = count($elementArrayH4); $explodeH4 = explode(' ' ,$snippetH4); $explodeCountH4 = count($explodeH4); $elementH5= $doc->getElementsByTagName('h5'); $elementArrayH5 = []; foreach ($elementH5 as $index => $value){ if( $value->firstChild->tagName == 'img' ){ $alt = $value->firstChild->getAttribute('alt'); // Replace dangerous double quotes inside alt with safe quotes $fixedAlt = str_replace(['"', '\'', '\\'], ['«', ' ', ' '], $alt); $value->firstChild->setAttribute('alt', $fixedAlt); $raw_base64_src = str_replace('\"' , '' , $value->firstChild->getAttribute('src')); // upload image on server instead of using base64 url $uploaded_url = $this->uploadImageWithFallback($raw_base64_src, "rp-img-".wp_rand(1 , 100000)); if ( !$uploaded_url ) { // remove image if we still can't upload it $parentNode = $value->parentNode; $parentNode->removeChild($value); continue; } $value->firstChild->setAttribute('src' , $uploaded_url); $elementImgSrc[] = [ 'src' => $uploaded_url, 'alt' => $fixedAlt ]; // save this image at this location in html $snippetH5 .= $value->firstChild->ownerDocument->saveHTML($value->firstChild); $elementArrayH5[] = $snippetH5; continue; } else { // if H5 is Not Empty if( trim($value->nodeValue) !== "" ){ $elementArrayH5[] = $value->nodeValue; $snippetH5 .= $value->nodeValue; } else { // remove empty H5 $parentNode = $value->parentNode; $parentNode->removeChild($value); } } } $lengthH5 = count($elementArrayH5); $explodeH5 = explode(' ' ,$snippetH5); $explodeCountH5 = count($explodeH5); $elementH6= $doc->getElementsByTagName('h6'); $elementArrayH6 = []; foreach ($elementH6 as $index => $value){ if( $value->firstChild->tagName == 'img' ){ $alt = $value->firstChild->getAttribute('alt'); // Replace dangerous double quotes inside alt with safe quotes $fixedAlt = str_replace(['"', '\'', '\\'], ['«', ' ', ' '], $alt); $value->firstChild->setAttribute('alt', $fixedAlt); $raw_base64_src = str_replace('\"' , '' , $value->firstChild->getAttribute('src')); // upload image on server instead of using base64 url $uploaded_url = $this->uploadImageWithFallback($raw_base64_src, "rp-img-".wp_rand(1 , 100000)); if ( !$uploaded_url ) { // remove image if we still can't upload it $parentNode = $value->parentNode; $parentNode->removeChild($value); continue; } $value->firstChild->setAttribute('src' , $uploaded_url); $elementImgSrc[] = [ 'src' => $uploaded_url, 'alt' => $fixedAlt ]; // save this image at this location in html $snippetH6 .= $value->firstChild->ownerDocument->saveHTML($value->firstChild); $elementArrayH6[] = $snippetH6; continue; } else { // if H6 is Not Empty if( trim($value->nodeValue) !== "" ){ $elementArrayH6[] = $value->nodeValue; $snippetH6 .= $value->nodeValue; } else { // remove empty H6 $parentNode = $value->parentNode; $parentNode->removeChild($value); } } } $lengthH6 = count($elementArrayH6); $explodeH6 = explode(' ' ,$snippetH6); $explodeCountH6 = count($explodeH6); // Save only the inner HTML (avoid DOCTYPE/head/body wrappers) $modifiedHtml = ''; $body = $doc->getElementsByTagName('body')->item(0); if ($body) { foreach ($body->childNodes as $child) { $modifiedHtml .= $doc->saveHTML($child); } } else { $modifiedHtml = $doc->saveHTML(); } libxml_clear_errors(); libxml_use_internal_errors(false); $elementAll = (object) [ 'elementImg' => array ('count' => $lengthImg , 'items' => $elementImgSrc) , 'elementH1' => array('count' => $lengthH1 , 'items' => $elementArrayH1) , 'elementH2' => array('count' => $lengthH2 , 'items' => $elementArrayH2) , 'elementH3' => array('count' => $lengthH3 , 'items' => $elementArrayH3) , 'elementH4' => array('count' => $lengthH4 , 'items' => $elementArrayH4) , 'elementH5' => array('count' => $lengthH5 , 'items' => $elementArrayH5) , 'elementH6' => array('count' => $lengthH6 , 'items' => $elementArrayH6) , 'fullContent' => $modifiedHtml, ]; return $elementAll; } /** * Get (and create if needed) the plugin-specific uploads subdirectory. * * @return array|false Array with 'path', 'url', 'subdir' keys, or false on failure. */ private function get_plugin_upload_dir() { $upload_dir = wp_upload_dir(); if ( ! empty( $upload_dir['error'] ) ) { return false; } $plugin_subdir = '/autopost'; $path = $upload_dir['basedir'] . $plugin_subdir; $url = $upload_dir['baseurl'] . $plugin_subdir; if ( ! is_dir( $path ) ) { wp_mkdir_p( $path ); } return array( 'path' => trailingslashit( $path ), 'url' => trailingslashit( $url ), 'subdir' => $plugin_subdir, ); } /** * Upload image to server instead of using Base64 */ private function uploadImage($base64_img, $title, $max_size = []) { // option to resize image - will save space on host usualy don't need image more than 1920 x 1080 // read more information on : // https://developer.wordpress.org/reference/functions/image_resize_dimensions/ // https://developer.wordpress.org/reference/classes/wp_image_editor_imagick/resize/ // or // https://developer.wordpress.org/reference/classes/wp_image_editor_gd/resize/ // crop = false // or // crop[0] = center|left|right // crop[1] = center|top|bottom // // also if one of "width" or "height" = 0 the image will keep ratio // if "width" and "height" = 0 image will not be croped $max_size = array_merge([ 'width' => 0, 'height' => 0, 'crop' => ['center', 'center'], 'dpi'=>96, // usualy for web is I see 72 ], $max_size); // with fix for data:image/jpeg;charset=utf-8;base64, // https://en.wikipedia.org/wiki/Data_URI_scheme#Syntax // generate corect filename as WP // extract entire data mime type ex data:image/jpeg or data:text/plain // $data_src = substr($base64_img, 0, strpos($base64_img, "base64")); $mime_type = substr($base64_img, 0, strpos($base64_img, ";")); // extract mime type ex image/jpeg or text/plain $mime_type = substr($mime_type, 5); // fix: "data: image" $mime_type = str_replace(' ', '', $mime_type); // make sure is image/* I make a limitation on image but you can skip this for other mime_types if (strpos($mime_type, 'image') === false) { return false; } // return extension if false return $ext = function_exists('wp_get_default_extension_for_mime_type') ? wp_get_default_extension_for_mime_type($mime_type) : ''; if (!$ext) { return false; } // Upload dir - use plugin-specific subdirectory. $plugin_upload = $this->get_plugin_upload_dir(); if ( ! $plugin_upload ) { return false; } $upload_path = $plugin_upload['path']; $upload_url = $plugin_upload['url']; //this is optional but you make sure you don't generate Name.jpg and also name.jpg $title = strtolower($title); // set file name and make sure is unique tile will be sanitized by WP $filename = $title . '.' . $ext; $filename = wp_unique_filename($upload_path, $filename, null); // get image content and decode it $img_content = str_replace($data_src . 'base64,', '', $base64_img); $img_content = str_replace(' ', '+', $img_content); // decode in chunks for large images fix $decoded = ""; for ($i = 0; $i < ceil(strlen($img_content) / 256); $i++) { $decoded = $decoded . base64_decode(substr($img_content, $i * 256, 256)); } $img_content = $decoded; $the_file = $upload_path . $filename; // Save the image in the uploads directory. file_put_contents($the_file, $img_content); // set max DPI for jpg, png, gif, webp before any resize //setImageDpi($the_file, count($max_size) != 0 ? $max_size['dpi'] : ''); // resize image if (!empty($max_size['width']) || !empty($max_size['height'])) { $image = wp_get_image_editor($the_file); // Return an implementation that extends WP_Image_Editor if (!is_wp_error($image)) { $image->resize((int) $max_size['width'], (int) $max_size['height'], $max_size['crop']); $image->save($the_file); } } $attachment = array( 'post_mime_type' => $mime_type, 'post_title' => preg_replace('/\.[^.]+$/', '', $filename), 'post_content' => '', 'post_status' => 'inherit', 'guid' => $upload_url . $filename ); $attach_id = wp_insert_attachment($attachment, $upload_path . $filename); // make sure function wp_generate_attachment_metadata exist if (!function_exists('wp_generate_attachment_metadata')) { require_once( ABSPATH . 'wp-admin/includes/image.php' ); } $attach_data = wp_generate_attachment_metadata($attach_id, $upload_path . $filename); wp_update_attachment_metadata($attach_id, $attach_data); return wp_get_attachment_url($attach_id); } /** * Try main upload method, then fallback if it fails. * * This wrapper makes sure images are uploaded as reliably as possible * across different WordPress / hosting environments. */ private function uploadImageWithFallback($base64_img, $title, $max_size = []) { // First, try the primary method. $uploaded_url = $this->uploadImage($base64_img, $title, $max_size); if ($uploaded_url && is_string($uploaded_url)) { return $uploaded_url; } // If that failed, try a more permissive fallback uploader. $fallback_url = $this->uploadImageFallback($base64_img, $title, $max_size); if ($fallback_url && is_string($fallback_url)) { return $fallback_url; } return false; } /** * Fallback image upload that avoids strict MIME / extension detection * and works on a wider range of WordPress / PHP setups. */ private function uploadImageFallback($base64_img, $title, $max_size = []) { // Ensure we have sane defaults for resize options, similar to main method. $max_size = array_merge([ 'width' => 0, 'height' => 0, 'crop' => ['center', 'center'], 'dpi' => 96, ], $max_size); // Decode base64 payload in a simpler / more tolerant way. if (strpos($base64_img, 'base64,') !== false) { $img_content = substr($base64_img, strpos($base64_img, 'base64,') + 7); } else { // Assume the whole string is base64 without a data URI prefix. $img_content = $base64_img; } $img_content = str_replace(' ', '+', $img_content); $binary = base64_decode($img_content); if (!$binary) { return false; } // Use PHP to detect image mime type directly from binary string. $image_info = @getimagesizefromstring($binary); if ($image_info === false || empty($image_info['mime']) || strpos($image_info['mime'], 'image/') !== 0) { return false; } $mime_type = $image_info['mime']; // Minimal, WordPress-independent mime → extension map. $ext = 'jpg'; if ($mime_type === 'image/png') { $ext = 'png'; } elseif ($mime_type === 'image/gif') { $ext = 'gif'; } elseif ($mime_type === 'image/webp') { $ext = 'webp'; } // Upload dir - use plugin-specific subdirectory. $plugin_upload = $this->get_plugin_upload_dir(); if ( ! $plugin_upload ) { return false; } $upload_path = $plugin_upload['path']; $upload_url = $plugin_upload['url']; // This is optional but makes sure you don't generate Name.jpg and also name.jpg $title = strtolower($title); // Set file name and make sure it is unique; title will be sanitized by WP. $filename = $title . '.' . $ext; $filename = wp_unique_filename($upload_path, $filename, null); $the_file = $upload_path . $filename; // Save the image in the uploads directory. file_put_contents($the_file, $binary); if (!file_exists($the_file)) { return false; } // Resize image if requested. if (!empty($max_size['width']) || !empty($max_size['height'])) { $image = wp_get_image_editor($the_file); if (!is_wp_error($image)) { $image->resize((int) $max_size['width'], (int) $max_size['height'], $max_size['crop']); $image->save($the_file); } } $attachment = array( 'post_mime_type' => $mime_type, 'post_title' => preg_replace('/\.[^.]+$/', '', $filename), 'post_content' => '', 'post_status' => 'inherit', 'guid' => $upload_url . $filename, ); $attach_id = wp_insert_attachment($attachment, $upload_path . $filename); // make sure function wp_generate_attachment_metadata exist if (!function_exists('wp_generate_attachment_metadata')) { require_once(ABSPATH . 'wp-admin/includes/image.php'); } $attach_data = wp_generate_attachment_metadata($attach_id, $upload_path . $filename); wp_update_attachment_metadata($attach_id, $attach_data); return wp_get_attachment_url($attach_id); } private function setImageDpi($file, $dpi) { $orig = getimagesize($file); switch ($orig[2]) { case 1: $src = imagecreatefromgif($file); break; case 2: $src = imagecreatefromjpeg($file); break; case 3: $src = imagecreatefrompng($file); break; case 18: $src = imagecreatefromwebp($file); break; default: return ''; break; } if (empty($src)) return''; $res=imageresolution($src); $res[0]= min($res[0],$dpi); $res[1]= min($res[1],$dpi); imageresolution($src, $res[0], $res[1]); switch ($orig[2]) { case 1: $src = imagegif($src, $file); break; case 2: $src = imagejpeg($src, $file); break; case 3: $src = imagepng($src, $file); break; case 18: $src = imagewebp($src, $file); break; default: return ''; break; } } }