/home/sylamedg/www/wp-content/plugins/templately/includes/Core/Importer/Utils/GutenbergHelper.php
<?php
namespace Templately\Core\Importer\Utils;
use Templately\Core\Importer\WPImport;
use Templately\Utils\Helper;
class GutenbergHelper extends ImportHelper {
const IMAGE_URL_PATTERN = '/(https?:\/\/[^\s<>"\']+\.(jpg|jpeg|gif|png|svg|webp|ico|tiff|tif)(?:\?[^\s<>"\']*)?)/i';
private $template_settings = [];
private $forms = [];
/**
* @var WPImport
*/
private $wp_importer;
public $shouldLog = true; // This is the class property to check
protected $content;
protected $post_id;
protected static $attachment_ids = [];
/**
* @param $template_json
* @param $template_settings
* @param $extra_content
*
* @return GutenbergHelper
*/
public function prepare( $template_json, $template_settings, $extra_content = [], $request_params = [] ) {
$this->template_settings = $template_settings;
$this->post_id = $this->map_post_ids[ $template_settings['post_id'] ];
$this->wp_importer = new WPImport( null, [
'session_id' => $this->session_id,
'fetch_attachments' => true,
] );
$parsed_blocks = parse_blocks( $template_json['content'] );
if ( ! empty( $extra_content ) ) {
$this->prepare_form_data( $extra_content, $template_settings );
}
if ( isset($this->template_settings['__attachments']) ) {
$this->process_images();
// Make sure we do the longest urls first, in case one is a substring of another.
}
if(!empty($this->wp_importer->url_remap)){
uksort( $this->wp_importer->url_remap, function ( $a, $b ) {
// Return the difference in length between two strings.
return strlen( $b ) - strlen( $a );
} );
}
if(!empty($template_settings["page_settings"]["fluent_cart_store_settings"])){
$this->replace_fluent_cart_store_settings($template_settings["page_settings"]["fluent_cart_store_settings"]);
}
$this->replace( $parsed_blocks, $request_params );
$this->content = wp_slash( serialize_blocks( $parsed_blocks ) );
return $this;
}
public function update() {
$this->sse_log('update', 'Updating prepared data, just a moment...', 1, 'eventLog');
wp_update_post( [
'ID' => $this->post_id,
'post_content' => $this->content
] );
}
private function prepare_form_data( $extra_content, $template_settings ) {
foreach ( $extra_content as $type => $content ) {
foreach ( $content as $block_id => $value ) {
foreach ( $template_settings['data']['form'][ $type ] as $setting ) {
if ( isset( $setting['id'] ) && $setting['id'] === $block_id ) {
$this->forms[ $block_id ] = [
'value' => $value,
'attr' => $setting['identifier']
];
}
}
}
}
}
private function replace( &$blocks, $request_params = [] ) {
foreach ( $blocks as &$block ) {
$this->sse_log('prepare', 'Preparing output for finalize, just a moment...', 1, 'eventLog');
if ( $block['blockName'] === 'core/navigation' ) {
if ( ! empty( $block['attrs']['ref'] ) && array_key_exists( $block['attrs']['ref'], $this->map_post_ids ) ) {
$block['attrs']['ref'] = $this->map_post_ids[ $block['attrs']['ref'] ];
$this->replace_archive_id( $block['attrs']['ref'] );
}
}
if ( isset( $block['attrs']['blockId'] ) && array_key_exists( $block['attrs']['blockId'], $this->forms ) ) {
$blockId = $block['attrs']['blockId'];
$form = $this->forms[$blockId];
$attr = $form['attr'];
$value = (string) $form['value'];
$block['attrs'][$attr] = $value;
}
if ( ! empty( $block['attrs']['queryData'] ) ) {
$this->replace_query_data( $block );
}
if ( isset($this->template_settings['__attachments']) ) {
$block = $this->replace_attachment_url( $block );
}
if ( ! empty( $block['innerBlocks'] ) ) {
$this->replace( $block['innerBlocks'], $request_params );
}
else if(!empty($request_params['logo']['id']) && isset($request_params['logo_size']) && $request_params['logo_size'] && $block['blockName'] === "essential-blocks/advanced-image" && $block["attrs"]["imgSource"] === "site-logo"){
$block["attrs"]["widthRange"] = $request_params['logo_size'];
unset($block["attrs"]["widthUnit"]);
if (isset($block['attrs']['blockMeta']['desktop']) && is_string($block['attrs']['blockMeta']['desktop'])) {
$meta = $block['attrs']['blockMeta']['desktop'];
$regex = '/\.image-wrapper\s*{\s*width:\s*(\d+)px;/';
if (preg_match($regex, $meta, $matches)) {
$replaced = preg_replace($regex, '.image-wrapper { width:' . $request_params['logo_size'] . 'px;', $meta);
if ($replaced) {
$block['attrs']['blockMeta']['desktop'] = $replaced;
}
}
}
$this->sse_log('prepare', 'Updated Site Logo', 1, 'eventLog');
}
}
}
private function replace_fluent_cart_store_settings($settings) {
$map_post_ids = $this->map_post_ids;
$saved_options = $settings;
$mapped_keys = [
'checkout_page_id',
'custom_payment_page_id',
'registration_page_id',
'login_page_id',
'cart_page_id',
'receipt_page_id',
'shop_page_id',
'customer_profile_page_id',
];
foreach ($mapped_keys as $key) {
$old_id = $saved_options[$key] ?? null;
if (!empty($old_id) && isset($map_post_ids[$old_id])) {
$saved_options[$key] = $map_post_ids[$old_id];
}
else if(isset($saved_options[$key])){
$saved_options[$key] = 0;
}
}
update_option('fluent_cart_store_settings', $saved_options);
}
private function replace_archive_id( $menu_id ) {
if ( ! empty( $this->imported_data['archive_settings'] ) ) {
$post = get_post( $menu_id );
$blocks = parse_blocks( $post->post_content );
$changed = false;
foreach ( $blocks as &$block ) {
$this->sse_log('query', 'Finalizing archive settings, just a moment...', 1, 'eventLog');
if (isset($block['attrs']['id'])) {
$blockId = $block['attrs']['id'];
$archiveSettings = $this->imported_data['archive_settings'];
$archiveIds = $archiveSettings[$blockId] ?? false;
if ($archiveIds) {
$block['attrs']['id'] = $archiveIds['page_id'];
$block['attrs']['url'] = get_the_permalink($archiveIds['page_id']);
$changed = true;
}
}
}
if ( $changed ) {
wp_update_post( [
'ID' => $menu_id,
'post_content' => wp_slash( serialize_blocks( $blocks ) )
] );
}
}
}
/**
* @param $block
*
* @return void
*/
private function replace_query_data( &$block ) {
if ( ! empty( $block['attrs']['queryData']['taxonomies'] ) ) {
foreach ( $block['attrs']['queryData']['taxonomies'] as &$tax ) {
$this->sse_log('query', 'Finalizing query data, just a moment...', 1, 'eventLog');
$tax['value'] = json_decode( $tax['value'], true );
if ( ! empty( $tax['value'] ) ) {
foreach ( $tax['value'] as &$val ) {
if ( array_key_exists( $val['value'], $this->map_term_ids ) ) {
$val['value'] = $this->map_term_ids[ $val['value'] ];
}
}
}
$tax['value'] = json_encode( $tax['value'] );
}
}
$this->replace_raw_taxonomies($block);
if(!empty( $block['attrs']['queryData']['author'])){
$user = wp_get_current_user();
$block['attrs']['queryData']['author'] = json_encode([['label' => $user->display_name, 'value' => $user->ID]]);
}
}
/**
* @param $block
*
* @return void
*/
private function replace_raw_taxonomies( &$block ) {
$types = ['category', 'tag'];
foreach ( $types as $type){
if(!empty($block['attrs']['queryData'][$type])){
$block['attrs']['queryData'][$type] = json_decode($block['attrs']['queryData'][$type], true);
foreach ($block['attrs']['queryData'][$type] as &$term){
$this->sse_log('prepare', 'Finalizing taxonomies, just a moment...', 1, 'eventLog');
if ( isset($term['value']) && array_key_exists( $term['value'], $this->map_term_ids ) ) {
$term['value'] = $this->map_term_ids[ $term['value'] ];
}
}
$block['attrs']['queryData'][$type] = json_encode($block['attrs']['queryData'][$type]);
}
}
}
public function replace_attachment_url($attrs) {
if ( !empty($attrs['blockName'] ) ) {
$attrs = $this->replace_attachment_ids($attrs);
}
if (is_string($attrs)) {
foreach ($this->wp_importer->url_remap as $old_url => $new_url) {
if (strpos($attrs, $old_url) !== false) {
$attrs = str_replace($old_url, $new_url, $attrs);
}
}
}
else if (is_array($attrs)) {
foreach ($attrs as $key => $attr) {
$attrs[$key] = $this->replace_attachment_url($attr);
}
}
return $attrs;
}
protected function replace_attachment_ids($attrs){
switch ($attrs['blockName']) {
case 'essential-blocks/slider':
$attrs = $this->processImages($attrs, 'images', 'imageId', 'url');
break;
case 'essential-blocks/advanced-image':
$attrs = $this->processSingleImage($attrs, 'image');
break;
case 'essential-blocks/parallax-slider':
$attrs = $this->processImages($attrs, 'sliderData', 'id', 'src');
break;
case 'essential-blocks/image-gallery':
$attrs = $this->processImages($attrs, 'images', 'id', 'url');
$attrs = $this->processImages($attrs, 'sources', 'id', 'url');
break;
case 'core/image':
$attrs = $this->processCoreImage($attrs, 'id');
break;
case 'core/media-text':
$attrs = $this->processCoreImage($attrs, 'mediaId');
break;
case 'core/cover':
$attrs = $this->processSingleImage($attrs, 'url');
break;
}
return $attrs;
}
private function processImages($attrs, $imageKey, $idKey, $urlKey) {
if (!empty($attrs['attrs'][$imageKey])) {
foreach ($attrs['attrs'][$imageKey] as $key => &$image) {
$imageUrl = $image[$urlKey];
if (!empty(self::$attachment_ids[$imageUrl])) {
$oldId = $image[$idKey];
$newId = (int) self::$attachment_ids[$imageUrl];
$image[$idKey] = $newId;
// Update innerHTML and innerContent for 'essential-blocks/slider'
if ($attrs['blockName'] === 'essential-blocks/slider') {
$attrs = $this->updateInnerHTMLAndContent($attrs, "imageId":$oldId,"", "imageId":$newId,"");
}
}
}
}
return $attrs;
}
private function processSingleImage($attrs, $imageKey) {
if (!empty(self::$attachment_ids[$attrs['attrs'][$imageKey]['url']])) {
$attrs['attrs'][$imageKey]['id'] = (int) self::$attachment_ids[$attrs['attrs'][$imageKey]['url']];
}
return $attrs;
}
private function processCoreImage($attrs, $idKey) {
preg_match(self::IMAGE_URL_PATTERN, $attrs['innerHTML'], $matches);
if (!empty($matches[0])) {
$url = $matches[0];
if (!empty(self::$attachment_ids[$url])) {
$oldId = $attrs['attrs'][$idKey];
$newId = (int) self::$attachment_ids[$url];
$attrs['attrs'][$idKey] = $newId;
// Replace old ID with new ID in innerHTML and innerContent
$attrs = $this->updateInnerHTMLAndContent($attrs, "wp-image-$oldId", "wp-image-$newId");
}
}
return $attrs;
}
private function updateInnerHTMLAndContent($attrs, $oldValue, $newValue) {
$attrs['innerHTML'] = str_replace($oldValue, $newValue, $attrs['innerHTML']);
if (is_array($attrs['innerContent'])) {
foreach ($attrs['innerContent'] as $i => $content) {
$attrs['innerContent'][$i] = str_replace($oldValue, $newValue, $content);
}
} else {
$attrs['innerContent'] = str_replace($oldValue, $newValue, $attrs['innerContent']);
}
return $attrs;
}
/**
* Parses the images from the post content, processes them as attachments, and updates the post with the new attachment URL.
* @todo: Parse using parse_blocks instead of regex
*
* @param int $post_id The ID of the post.
* @param string $post_content The content of the post.
*/
public function parse_images($post_content) {
// Find all image URLs in the post content
preg_match_all(self::IMAGE_URL_PATTERN, $post_content, $matches);
$urls = $matches[0];
$organizedUrls = [];
foreach ($urls as $url) {
// Remove the size suffix from the URL
$base_url = preg_replace('/-\d+x\d+(?=\.[a-zA-Z]+$)/', '', $url);
// Check if the URL already exists in the array
if (!isset($organizedUrls[$base_url]) || !in_array($url, $organizedUrls[$base_url])) {
// Add the URL to the array under the base URL key
$organizedUrls[$base_url][] = $url;
}
}
return $organizedUrls;
}
public function process_images(){
// Time to run the import!
set_time_limit( 0 );
$organizedUrls = $this->template_settings['__attachments'];
// For each base image URL...
foreach ($organizedUrls as $base_url => $sizes) {
// Prepare the post data for the attachment
$post_data = $this->prepare_post_data($this->post_id, $base_url);
// If prepare_post_data returned null, skip this iteration
if ($post_data === null) {
continue;
}
foreach ($sizes as $key => $size) {
if ($base_url == $size) {
unset($sizes[$key]);
continue;
}
// $size url string; get width height from the image url
preg_match('/-(\d+)x(\d+)\.[a-zA-Z]+$/', $size, $matches);
if (isset($matches[1]) && isset($matches[2])) {
$sizes[$key] = [
'file' => basename($size),
'width' => $matches[1],
'height' => $matches[2]
];
} else {
unset($sizes[$key]);
}
}
// Check if the attachment already exists
$attachment_id = $this->wp_importer->process_attachment($post_data, $base_url, $sizes);
// If there was an error, handle it here
if (is_wp_error($attachment_id)) {
$this->sse_log('error', $attachment_id->get_error_message(), -1, 'eventLog');
} else {
$this->sse_log('success', "Imported attachment: $attachment_id", -1, 'eventLog');
self::$attachment_ids[$base_url] = $attachment_id;
}
}
}
private function prepare_post_data($post_id, $image_url) {
return Utils::prepare_post_data($image_url, $post_id, [$this, 'sse_log']);
}
public function sse_log( $type, $message, $progress = 1, $action = 'updateLog', $status = null ) {
if ($this->shouldLog) {
parent::sse_log($type, $message, $progress, $action, $status);
}
else{
Helper::log(func_get_args());
}
}
public function get_content(){
return $this->content;
}
}