From 53ed307f9fcf1d121956072eda6b71a65f48dec4 Mon Sep 17 00:00:00 2001 From: Matias Benedetto Date: Wed, 8 Feb 2023 22:57:17 +0700 Subject: [PATCH 01/12] bundle images inserted with the editor in to the theme assets --- admin/class-create-block-theme-admin.php | 230 +++++++++++++++++++++-- 1 file changed, 217 insertions(+), 13 deletions(-) diff --git a/admin/class-create-block-theme-admin.php b/admin/class-create-block-theme-admin.php index 72ba1aa5..66523350 100644 --- a/admin/class-create-block-theme-admin.php +++ b/admin/class-create-block-theme-admin.php @@ -556,6 +556,103 @@ function get_theme_templates( $export_type, $new_slug ) { } + function is_absolute_url( $url ) { + return isset( parse_url( $url )[ 'host' ] ); + } + + function make_image_blocks_local ( $nested_blocks ) { + $new_blocks = []; + foreach ( $nested_blocks as $block ) { + // recursive call for inner blocks + if ( !empty ( $block['innerBlocks'] ) ) { + $block['innerBlocks'] = $this->make_image_blocks_local( $block[ 'innerBlocks' ] ); + } + if ( 'core/image' === $block[ 'blockName' ] ) { + $doc = new DOMDocument(); + @$doc->loadHTML( $block[ 'innerHTML' ], LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD ); + $tags = $doc->getElementsByTagName( 'img' ); + $block_has_external_images = false; + foreach ( $tags as $tag ) { + $image_url = $tag->getAttribute( 'src' ); + if ( $this->is_absolute_url( $image_url ) ) { + $block_has_external_images = true; + $media[] = $tag->getAttribute( 'src' ); + $tag->setAttribute( + 'src', + '/assets/images/'. basename( $tag->getAttribute( 'src' ) ) + ); + } + } + if ( $block_has_external_images ) { + $block['innerHTML'] = $doc->saveHTML(); + $block['innerContent'] = array ( $doc->saveHTML() ); + } + } + $new_blocks[] = $block; + } + return $new_blocks; + } + + function get_media_absolute_urls_from_blocks ( $flatten_blocks ) { + $media = []; + foreach ( $flatten_blocks as $block ) { + if ('core/image' === $block[ 'blockName' ]) { + $doc = new DOMDocument(); + @$doc->loadHTML( $block['innerHTML'], LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD ); + $tags = $doc->getElementsByTagName( 'img' ); + $block_has_external_images = false; + foreach ($tags as $tag) { + $image_url = $tag->getAttribute( 'src' ); + if ($this->is_absolute_url( $image_url )) { + $media[] = $tag->getAttribute( 'src' ); + } + } + } + } + return $media; + } + + // find all the media files used in the templates and add them to the zip + function make_template_images_local ( $template ) { + $new_content = $template->content; + $template_blocks = parse_blocks( $template->content ); + $flatten_blocks = _flatten_blocks( $template_blocks ); + + $blocks = $this->make_image_blocks_local( $template_blocks ); + $blocks = serialize_blocks ( $blocks ); + + $template->content = $this->clean_serialized_markup ( $blocks ); + $template->media = $this->get_media_absolute_urls_from_blocks ( $flatten_blocks ); + return $template; + } + + function clean_serialized_markup ( $markup ) { + $markup = str_replace( '%20', ' ', $markup ); + $markup = str_replace( '<', '<', $markup ); + $markup = str_replace( '>', '>', $markup ); + return $markup; + } + + function pattern_from_template ( $template ) { + $theme_slug = wp_get_theme()->get( 'TextDomain' ); + $pattern_slug = $theme_slug . '/' . $template->slug; + $pattern_content = ( +'slug .' + * Slug: ' . $pattern_slug. ' + * Categories: hidden + * Inserter: no + */ +?> +'. $template->content + ); + return array ( + 'slug' => $pattern_slug, + 'content' => $pattern_content + ); + } + /** * Add block templates and parts to the zip. * @@ -567,7 +664,6 @@ function get_theme_templates( $export_type, $new_slug ) { * all = all templates no matter what */ function add_templates_to_zip( $zip, $export_type, $new_slug ) { - $theme_templates = $this->get_theme_templates( $export_type, $new_slug ); if ( $theme_templates->templates ) { @@ -579,16 +675,59 @@ function add_templates_to_zip( $zip, $export_type, $new_slug ) { } foreach ( $theme_templates->templates as $template ) { + $template_data = $this->make_template_images_local( $template ); + + // If there are images in the template, add it as a pattern + if ( count( $template_data->media ) > 0 ) { + $pattern = $this->pattern_from_template( $template_data ); + $template_data->content = ''; + + // Add pattern to zip + $zip->addFromString( + 'patterns/' . $template_data->slug . '.php', + $pattern[ 'content' ] + ); + + // Add image assets to zip + foreach ( $template_data->media as $media ) { + $download_file = file_get_contents( $media ); + $zip->addFromString( 'assets/images/' . basename( $media ), $download_file ); + } + } + + // Add template to zip $zip->addFromString( - 'templates/' . $template->slug . '.html', - $template->content + 'templates/' . $template_data->slug . '.html', + $template_data->content ); + } foreach ( $theme_templates->parts as $template_part ) { + $template_data = $this->make_template_images_local( $template_part ); + + // If there are images in the template, add it as a pattern + if ( count( $template_data->media ) > 0 ) { + $pattern = $this->pattern_from_template( $template_data ); + $template_data->content = ''; + + // Add pattern to zip + $zip->addFromString( + 'patterns/' . $template_data->slug . '.php', + $pattern[ 'content' ] + ); + + // Add image assets to zip + foreach ( $template_data->media as $media ) { + $download_file = file_get_contents( $media ); + $zip->addFromString( 'assets/images/' . basename( $media ), $download_file ); + } + } + + // Add template to zip $zip->addFromString( - 'parts/' . $template_part->slug . '.html', - $template_part->content + 'parts/' . $template_data->slug . '.html', + $template_data->content ); } @@ -601,27 +740,92 @@ function add_templates_to_local( $export_type ) { $template_folders = get_block_theme_folders(); // If there is no templates folder, create it. - if ( ! is_dir( get_stylesheet_directory() . '/' . $template_folders['wp_template'] ) ) { - wp_mkdir_p( get_stylesheet_directory() . '/' . $template_folders['wp_template'] ); + if ( ! is_dir( get_stylesheet_directory() . DIRECTORY_SEPARATOR . $template_folders['wp_template'] ) ) { + wp_mkdir_p( get_stylesheet_directory() . DIRECTORY_SEPARATOR . $template_folders['wp_template'] ); + } + + if ( ! is_dir( get_stylesheet_directory() . '/assets/images' ) ) { + wp_mkdir_p( get_stylesheet_directory() . '/assets/images' ); } foreach ( $theme_templates->templates as $template ) { + $template_data = $this->make_template_images_local( $template ); + + // If there are images in the template, add it as a pattern + if ( ! empty ( $template_data->media ) ) { + // If there is no templates folder, create it. + if ( ! is_dir( get_stylesheet_directory() . DIRECTORY_SEPARATOR . 'patterns' ) ) { + wp_mkdir_p( get_stylesheet_directory() . DIRECTORY_SEPARATOR . 'patterns' ); + } + + // If there are external images, add it as a pattern + $pattern = $this->pattern_from_template( $template_data ); + $template_data->content = ''; + + // Write the pattern + file_put_contents( + get_stylesheet_directory() . DIRECTORY_SEPARATOR . 'patterns' . DIRECTORY_SEPARATOR . $template_data->slug . '.php', + $pattern[ 'content' ] + ); + } + + // Write the template content file_put_contents( - get_stylesheet_directory() . '/' . $template_folders['wp_template'] . '/' . $template->slug . '.html', - $template->content + get_stylesheet_directory() . DIRECTORY_SEPARATOR . $template_folders['wp_template'] . DIRECTORY_SEPARATOR . $template->slug . '.html', + $template_data->content ); + + // Write the image assets + foreach ( $template_data->media as $media ) { + $download_file = file_get_contents( $media ); + file_put_contents( + get_stylesheet_directory() . DIRECTORY_SEPARATOR .'assets' . DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR . basename( $media ), + $download_file + ); + } + } // If there is no parts folder, create it. - if ( ! is_dir( get_stylesheet_directory() . '/' . $template_folders['wp_template_part'] ) ) { - wp_mkdir_p( get_stylesheet_directory() . '/' . $template_folders['wp_template_part'] ); + if ( ! is_dir( get_stylesheet_directory() . DIRECTORY_SEPARATOR . $template_folders['wp_template_part'] ) ) { + wp_mkdir_p( get_stylesheet_directory() . DIRECTORY_SEPARATOR . $template_folders['wp_template_part'] ); } foreach ( $theme_templates->parts as $template_part ) { + $template_data = $this->make_template_images_local( $template_part ); + + // If there are images in the template, add it as a pattern + if ( ! empty ( $template_data->media ) ) { + // If there is no templates folder, create it. + if ( ! is_dir( get_stylesheet_directory() . DIRECTORY_SEPARATOR . 'patterns' ) ) { + wp_mkdir_p( get_stylesheet_directory() . DIRECTORY_SEPARATOR . 'patterns' ); + } + + // If there are external images, add it as a pattern + $pattern = $this->pattern_from_template( $template_data ); + $template_data->content = ''; + + // Write the pattern + file_put_contents( + get_stylesheet_directory() . DIRECTORY_SEPARATOR . 'patterns' . DIRECTORY_SEPARATOR . $template_data->slug . '.php', + $pattern[ 'content' ] + ); + } + + // Write the template content file_put_contents( - get_stylesheet_directory() . '/' . $template_folders['wp_template_part'] . '/' . $template_part->slug . '.html', - $template_part->content + get_stylesheet_directory() . DIRECTORY_SEPARATOR . $template_folders['wp_template_part'] . DIRECTORY_SEPARATOR . $template_data->slug . '.html', + $template_data->content ); + + // Write the image assets + foreach ( $template_data->media as $media ) { + $download_file = file_get_contents( $media ); + file_put_contents( + get_stylesheet_directory() . DIRECTORY_SEPARATOR .'assets' . DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR . basename( $media ), + $download_file + ); + } } } From 86c28d0d943aceb620a42c13c865cce9ed6e7a3a Mon Sep 17 00:00:00 2001 From: Matias Benedetto Date: Thu, 9 Feb 2023 22:39:37 +0800 Subject: [PATCH 02/12] User get_stylesheet_directory_uri() instead of get_template_direcctory_uri() for image paths Co-authored-by: Jeff Ong --- admin/class-create-block-theme-admin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/class-create-block-theme-admin.php b/admin/class-create-block-theme-admin.php index 66523350..8beff63c 100644 --- a/admin/class-create-block-theme-admin.php +++ b/admin/class-create-block-theme-admin.php @@ -579,7 +579,7 @@ function make_image_blocks_local ( $nested_blocks ) { $media[] = $tag->getAttribute( 'src' ); $tag->setAttribute( 'src', - '/assets/images/'. basename( $tag->getAttribute( 'src' ) ) + '/assets/images/'. basename( $tag->getAttribute( 'src' ) ) ); } } From 0fd1b8f2a5f1b0f5da3ba6dafe1428c42e9adfb8 Mon Sep 17 00:00:00 2001 From: Matias Benedetto Date: Mon, 13 Feb 2023 19:22:01 +0700 Subject: [PATCH 03/12] making cover media local --- admin/class-create-block-theme-admin.php | 89 +++++++++++++++++------- 1 file changed, 64 insertions(+), 25 deletions(-) diff --git a/admin/class-create-block-theme-admin.php b/admin/class-create-block-theme-admin.php index 8beff63c..20c08d06 100644 --- a/admin/class-create-block-theme-admin.php +++ b/admin/class-create-block-theme-admin.php @@ -560,33 +560,70 @@ function is_absolute_url( $url ) { return isset( parse_url( $url )[ 'host' ] ); } - function make_image_blocks_local ( $nested_blocks ) { + function make_relative_image_url ( $absolute_url ) { + return '/assets/images/'. basename( $absolute_url ); + } + + function make_img_tags_local ( $html ) { + if ( empty( $html ) ) { + return $html; + } + $doc = new DOMDocument(); + @$doc->loadHTML( $html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD ); + $img_tags = $doc->getElementsByTagName( 'img' ); + $html_has_external_images = false; + foreach ( $img_tags as $tag ) { + $image_url = $tag->getAttribute( 'src' ); + if ( $this->is_absolute_url( $image_url ) ) { + $html_has_external_images = true; + $img_src = $tag->getAttribute( 'src' ); + $media[] = $img_src; + $html = str_replace( $img_src, $this->make_relative_image_url( $img_src ), $html ); + } + } + return $html; + } + + function make_image_block_local ( $block ) { + if ( 'core/image' === $block[ 'blockName' ] ) { + $inner_html = $this->make_img_tags_local( $block[ 'innerHTML' ] ); + $block['innerHTML'] = $inner_html; + $block['innerContent'] = array ( $inner_html ); + } + return $block; + } + + function make_cover_block_local ( $block ) { + if ( 'core/cover' === $block[ 'blockName' ] ) { + $inner_html = $this->make_img_tags_local( $block[ 'innerHTML' ] ); + + if ( isset ( $block['attrs']['url'] ) && $this->is_absolute_url( $block['attrs']['url'] ) ) { + $block_has_external_images = true; + $block['attrs']['url'] = $this->make_relative_image_url( $block['attrs']['url'] ); + } + + $inner_content = []; + foreach ( $block['innerContent'] as $content ) { + $content_html = $this->make_img_tags_local( $content ); + $inner_content[] = $content_html; + } + + $block['innerHTML'] = $inner_html; + $block['innerContent'] = $inner_content; + } + return $block; + } + + function make_media_blocks_local ( $nested_blocks ) { $new_blocks = []; foreach ( $nested_blocks as $block ) { + $inner_blocks = $block['innerBlocks']; + $block = $this->make_image_block_local( $block ); + $block = $this->make_cover_block_local( $block ); + // recursive call for inner blocks if ( !empty ( $block['innerBlocks'] ) ) { - $block['innerBlocks'] = $this->make_image_blocks_local( $block[ 'innerBlocks' ] ); - } - if ( 'core/image' === $block[ 'blockName' ] ) { - $doc = new DOMDocument(); - @$doc->loadHTML( $block[ 'innerHTML' ], LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD ); - $tags = $doc->getElementsByTagName( 'img' ); - $block_has_external_images = false; - foreach ( $tags as $tag ) { - $image_url = $tag->getAttribute( 'src' ); - if ( $this->is_absolute_url( $image_url ) ) { - $block_has_external_images = true; - $media[] = $tag->getAttribute( 'src' ); - $tag->setAttribute( - 'src', - '/assets/images/'. basename( $tag->getAttribute( 'src' ) ) - ); - } - } - if ( $block_has_external_images ) { - $block['innerHTML'] = $doc->saveHTML(); - $block['innerContent'] = array ( $doc->saveHTML() ); - } + $block['innerBlocks'] = $this->make_media_blocks_local( $inner_blocks ); } $new_blocks[] = $block; } @@ -596,7 +633,7 @@ function make_image_blocks_local ( $nested_blocks ) { function get_media_absolute_urls_from_blocks ( $flatten_blocks ) { $media = []; foreach ( $flatten_blocks as $block ) { - if ('core/image' === $block[ 'blockName' ]) { + if ( 'core/image' === $block[ 'blockName' ] || 'core/cover' === $block[ 'blockName' ] ) { $doc = new DOMDocument(); @$doc->loadHTML( $block['innerHTML'], LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD ); $tags = $doc->getElementsByTagName( 'img' ); @@ -618,7 +655,7 @@ function make_template_images_local ( $template ) { $template_blocks = parse_blocks( $template->content ); $flatten_blocks = _flatten_blocks( $template_blocks ); - $blocks = $this->make_image_blocks_local( $template_blocks ); + $blocks = $this->make_media_blocks_local( $template_blocks ); $blocks = serialize_blocks ( $blocks ); $template->content = $this->clean_serialized_markup ( $blocks ); @@ -630,6 +667,8 @@ function clean_serialized_markup ( $markup ) { $markup = str_replace( '%20', ' ', $markup ); $markup = str_replace( '<', '<', $markup ); $markup = str_replace( '>', '>', $markup ); + $markup = str_replace( '\u003c', '<', $markup ); + $markup = str_replace( '\u003e', '>', $markup ); return $markup; } From b6a0abd7d520400e6d0fa345af5f358c773fb9dc Mon Sep 17 00:00:00 2001 From: Matias Benedetto Date: Mon, 13 Feb 2023 20:25:44 +0700 Subject: [PATCH 04/12] add support for cover blocks that use background images instead of img tags --- admin/class-create-block-theme-admin.php | 42 ++++++++++++++++++++---- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/admin/class-create-block-theme-admin.php b/admin/class-create-block-theme-admin.php index 20c08d06..6e36ee4a 100644 --- a/admin/class-create-block-theme-admin.php +++ b/admin/class-create-block-theme-admin.php @@ -564,29 +564,41 @@ function make_relative_image_url ( $absolute_url ) { return '/assets/images/'. basename( $absolute_url ); } - function make_img_tags_local ( $html ) { + function make_html_images_local ( $html ) { if ( empty( $html ) ) { return $html; } $doc = new DOMDocument(); @$doc->loadHTML( $html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD ); $img_tags = $doc->getElementsByTagName( 'img' ); - $html_has_external_images = false; + // replace all images that have absolute urls foreach ( $img_tags as $tag ) { $image_url = $tag->getAttribute( 'src' ); if ( $this->is_absolute_url( $image_url ) ) { - $html_has_external_images = true; $img_src = $tag->getAttribute( 'src' ); - $media[] = $img_src; $html = str_replace( $img_src, $this->make_relative_image_url( $img_src ), $html ); } } + // also replace background images with absolute urls (used in cover blocks) + $div_tags = $doc->getElementsByTagName( 'div' ); + foreach ( $div_tags as $tag ) { + $style = $tag->getAttribute( 'style' ); + if ( $style ) { + preg_match_all('#\bhttps?://[^,\s()<>]+(?:\([\w\d]+\)|([^,[:punct:]\s]|/))#', $style, $match); + $urls = $match[0]; + foreach ( $urls as $url ) { + if ( $this->is_absolute_url( $url ) ) { + $html = str_replace( $url, $this->make_relative_image_url( $url ), $html ); + } + } + } + } return $html; } function make_image_block_local ( $block ) { if ( 'core/image' === $block[ 'blockName' ] ) { - $inner_html = $this->make_img_tags_local( $block[ 'innerHTML' ] ); + $inner_html = $this->make_html_images_local( $block[ 'innerHTML' ] ); $block['innerHTML'] = $inner_html; $block['innerContent'] = array ( $inner_html ); } @@ -595,7 +607,7 @@ function make_image_block_local ( $block ) { function make_cover_block_local ( $block ) { if ( 'core/cover' === $block[ 'blockName' ] ) { - $inner_html = $this->make_img_tags_local( $block[ 'innerHTML' ] ); + $inner_html = $this->make_html_images_local( $block[ 'innerHTML' ] ); if ( isset ( $block['attrs']['url'] ) && $this->is_absolute_url( $block['attrs']['url'] ) ) { $block_has_external_images = true; @@ -604,7 +616,7 @@ function make_cover_block_local ( $block ) { $inner_content = []; foreach ( $block['innerContent'] as $content ) { - $content_html = $this->make_img_tags_local( $content ); + $content_html = $this->make_html_images_local( $content ); $inner_content[] = $content_html; } @@ -636,6 +648,8 @@ function get_media_absolute_urls_from_blocks ( $flatten_blocks ) { if ( 'core/image' === $block[ 'blockName' ] || 'core/cover' === $block[ 'blockName' ] ) { $doc = new DOMDocument(); @$doc->loadHTML( $block['innerHTML'], LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD ); + + // Get the media urls from img tags $tags = $doc->getElementsByTagName( 'img' ); $block_has_external_images = false; foreach ($tags as $tag) { @@ -644,6 +658,20 @@ function get_media_absolute_urls_from_blocks ( $flatten_blocks ) { $media[] = $tag->getAttribute( 'src' ); } } + // Get the media urls from div style tags (used in cover blocks) + $div_tags = $doc->getElementsByTagName( 'div' ); + foreach ( $div_tags as $tag ) { + $style = $tag->getAttribute( 'style' ); + if ( $style ) { + preg_match_all('#\bhttps?://[^,\s()<>]+(?:\([\w\d]+\)|([^,[:punct:]\s]|/))#', $style, $match); + $urls = $match[0]; + foreach ( $urls as $url ) { + if ( $this->is_absolute_url( $url ) ) { + $media[] = $url; + } + } + } + } } } return $media; From 1fba5dccb1f6400b8e80321fc9a41da93d903056 Mon Sep 17 00:00:00 2001 From: Matias Benedetto Date: Mon, 13 Feb 2023 20:46:56 +0700 Subject: [PATCH 05/12] adding support for core/media-text block --- admin/class-create-block-theme-admin.php | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/admin/class-create-block-theme-admin.php b/admin/class-create-block-theme-admin.php index 6e36ee4a..9d943d6c 100644 --- a/admin/class-create-block-theme-admin.php +++ b/admin/class-create-block-theme-admin.php @@ -608,20 +608,33 @@ function make_image_block_local ( $block ) { function make_cover_block_local ( $block ) { if ( 'core/cover' === $block[ 'blockName' ] ) { $inner_html = $this->make_html_images_local( $block[ 'innerHTML' ] ); - + $inner_content = []; + foreach ( $block['innerContent'] as $content ) { + $content_html = $this->make_html_images_local( $content ); + $inner_content[] = $content_html; + } + $block['innerHTML'] = $inner_html; + $block['innerContent'] = $inner_content; if ( isset ( $block['attrs']['url'] ) && $this->is_absolute_url( $block['attrs']['url'] ) ) { - $block_has_external_images = true; $block['attrs']['url'] = $this->make_relative_image_url( $block['attrs']['url'] ); } + } + return $block; + } + function make_mediatext_block_local ( $block ) { + if ( 'core/media-text' === $block[ 'blockName' ] ) { + $inner_html = $this->make_html_images_local( $block[ 'innerHTML' ] ); $inner_content = []; foreach ( $block['innerContent'] as $content ) { $content_html = $this->make_html_images_local( $content ); $inner_content[] = $content_html; } - $block['innerHTML'] = $inner_html; $block['innerContent'] = $inner_content; + if ( isset ( $block['attrs']['mediaLink'] ) && $this->is_absolute_url( $block['attrs']['mediaLink'] ) ) { + $block['attrs']['mediaLink'] = $this->make_relative_image_url( $block['attrs']['mediaLink'] ); + } } return $block; } @@ -632,6 +645,7 @@ function make_media_blocks_local ( $nested_blocks ) { $inner_blocks = $block['innerBlocks']; $block = $this->make_image_block_local( $block ); $block = $this->make_cover_block_local( $block ); + $block = $this->make_mediatext_block_local( $block ); // recursive call for inner blocks if ( !empty ( $block['innerBlocks'] ) ) { From 5bfdf1e05891103e095f4168bdf1acee201cec6f Mon Sep 17 00:00:00 2001 From: Matias Benedetto Date: Wed, 15 Feb 2023 13:39:10 +0700 Subject: [PATCH 06/12] escaping alt attributes of image, cover and mediatext blocks --- admin/class-create-block-theme-admin.php | 25 ++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/admin/class-create-block-theme-admin.php b/admin/class-create-block-theme-admin.php index 4cfcc78b..c2be92f6 100644 --- a/admin/class-create-block-theme-admin.php +++ b/admin/class-create-block-theme-admin.php @@ -599,6 +599,7 @@ function make_html_images_local ( $html ) { function make_image_block_local ( $block ) { if ( 'core/image' === $block[ 'blockName' ] ) { $inner_html = $this->make_html_images_local( $block[ 'innerHTML' ] ); + $inner_html = $this->escape_alt_for_pattern ( $inner_html ); $block['innerHTML'] = $inner_html; $block['innerContent'] = array ( $inner_html ); } @@ -608,9 +609,11 @@ function make_image_block_local ( $block ) { function make_cover_block_local ( $block ) { if ( 'core/cover' === $block[ 'blockName' ] ) { $inner_html = $this->make_html_images_local( $block[ 'innerHTML' ] ); + $inner_html = $this->escape_alt_for_pattern ( $inner_html ); $inner_content = []; foreach ( $block['innerContent'] as $content ) { $content_html = $this->make_html_images_local( $content ); + $content_html = $this->escape_alt_for_pattern ( $content_html ); $inner_content[] = $content_html; } $block['innerHTML'] = $inner_html; @@ -625,9 +628,11 @@ function make_cover_block_local ( $block ) { function make_mediatext_block_local ( $block ) { if ( 'core/media-text' === $block[ 'blockName' ] ) { $inner_html = $this->make_html_images_local( $block[ 'innerHTML' ] ); + $inner_html = $this->escape_alt_for_pattern ( $inner_html ); $inner_content = []; foreach ( $block['innerContent'] as $content ) { $content_html = $this->make_html_images_local( $content ); + $content_html = $this->escape_alt_for_pattern ( $content_html ); $inner_content[] = $content_html; } $block['innerHTML'] = $inner_html; @@ -734,6 +739,26 @@ function pattern_from_template ( $template ) { ); } + function escape_text_for_pattern( $text ) { + if ( $text && trim ( $text ) !== "" ) { + return ''; + } + } + + function escape_alt_for_pattern ( $html ) { + preg_match( '@alt="([^"]+)"@' , $html, $match ); + if ( isset( $match[0] ) ) { + $alt_attribute = $match[0]; + $alt_value= $match[1]; + $html = str_replace( + $alt_attribute, + 'alt="'.$this->escape_text_for_pattern( $alt_value ).'"', + $html + ); + } + return $html; + } + /** * Add block templates and parts to the zip. * From 614a0bb7303839f46c97c20421f1cd43e9f615be Mon Sep 17 00:00:00 2001 From: Matias Benedetto Date: Wed, 15 Feb 2023 16:03:48 +0700 Subject: [PATCH 07/12] using swith to avoid calling the functions with every block --- admin/class-create-block-theme-admin.php | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/admin/class-create-block-theme-admin.php b/admin/class-create-block-theme-admin.php index c2be92f6..492a3358 100644 --- a/admin/class-create-block-theme-admin.php +++ b/admin/class-create-block-theme-admin.php @@ -648,10 +648,17 @@ function make_media_blocks_local ( $nested_blocks ) { $new_blocks = []; foreach ( $nested_blocks as $block ) { $inner_blocks = $block['innerBlocks']; - $block = $this->make_image_block_local( $block ); - $block = $this->make_cover_block_local( $block ); - $block = $this->make_mediatext_block_local( $block ); - + switch ( $block[ 'blockName' ] ) { + case 'core/image': + $block = $this->make_image_block_local($block); + break; + case 'core/cover': + $block = $this->make_cover_block_local($block); + break; + case 'core/media-text': + $block = $this->make_mediatext_block_local($block); + break; + } // recursive call for inner blocks if ( !empty ( $block['innerBlocks'] ) ) { $block['innerBlocks'] = $this->make_media_blocks_local( $inner_blocks ); From c59c50e07db3c2e4b6909a4a1c2f35958ba3b12b Mon Sep 17 00:00:00 2001 From: Matias Benedetto Date: Wed, 15 Feb 2023 18:00:37 +0700 Subject: [PATCH 08/12] Implementing WP_HTML_Tag_Processor to get and set element html attributes and fallback to DOMDocument and regex if WP_HTML_Tag_Processor is not available yet --- admin/class-create-block-theme-admin.php | 214 +++++++++++++++++------ 1 file changed, 159 insertions(+), 55 deletions(-) diff --git a/admin/class-create-block-theme-admin.php b/admin/class-create-block-theme-admin.php index 492a3358..e963ffd7 100644 --- a/admin/class-create-block-theme-admin.php +++ b/admin/class-create-block-theme-admin.php @@ -568,32 +568,64 @@ function make_html_images_local ( $html ) { if ( empty( $html ) ) { return $html; } - $doc = new DOMDocument(); - @$doc->loadHTML( $html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD ); - $img_tags = $doc->getElementsByTagName( 'img' ); - // replace all images that have absolute urls - foreach ( $img_tags as $tag ) { - $image_url = $tag->getAttribute( 'src' ); - if ( $this->is_absolute_url( $image_url ) ) { - $img_src = $tag->getAttribute( 'src' ); - $html = str_replace( $img_src, $this->make_relative_image_url( $img_src ), $html ); + + // If the WP_HTML_Tag_Processor class exists, use it to parse the HTML. + // This API was recently in Gutenberg and not yet available in WordPress core. https://github.com/WordPress/gutenberg/pull/42485 + // If it's not available, fallb ack to DOMDocument which can not be installed in all the systems and has some issues. + // When WP_HTML_Tag_Processor is availabe in core (6.2) we can remove the DOMDocument fallback. + if ( class_exists( 'WP_HTML_Tag_Processor' ) ) { + $html = new WP_HTML_Tag_Processor( $html ); + while ( $html->next_tag( 'img' ) ) { + if ( $this->is_absolute_url( $html->get_attribute( 'src' ) ) ) { + $html->set_attribute( 'src', $this->make_relative_image_url( $html->get_attribute( 'src' ) ) ); + } + } + while ( $html->next_tag( 'div' ) ) { + $style = $html->get_attribute( 'style' ); + if ( $style ) { + preg_match_all('#\bhttps?://[^,\s()<>]+(?:\([\w\d]+\)|([^,[:punct:]\s]|/))#', $style, $match); + $urls = $match[0]; + foreach ( $urls as $url ) { + if ( $this->is_absolute_url( $url ) ) { + $html->set_attribute( 'style', str_replace( $url, $this->make_relative_image_url( $url ), $style ) ); + } + } + } } + return $html->__toString(); } - // also replace background images with absolute urls (used in cover blocks) - $div_tags = $doc->getElementsByTagName( 'div' ); - foreach ( $div_tags as $tag ) { - $style = $tag->getAttribute( 'style' ); - if ( $style ) { - preg_match_all('#\bhttps?://[^,\s()<>]+(?:\([\w\d]+\)|([^,[:punct:]\s]|/))#', $style, $match); - $urls = $match[0]; - foreach ( $urls as $url ) { - if ( $this->is_absolute_url( $url ) ) { - $html = str_replace( $url, $this->make_relative_image_url( $url ), $html ); + + // Fallback to DOMDocument. + // TODO: When WP_HTML_Tag_Processor is availabe in core (6.2) we can remove this implementation entirely. + if ( ! class_exists( 'WP_HTML_Tag_Processor' ) ) { + $doc = new DOMDocument(); + @$doc->loadHTML( $html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD ); + $img_tags = $doc->getElementsByTagName( 'img' ); + // replace all images that have absolute urls + foreach ( $img_tags as $tag ) { + $image_url = $tag->getAttribute( 'src' ); + if ( $this->is_absolute_url( $image_url ) ) { + $img_src = $tag->getAttribute( 'src' ); + $html = str_replace( $img_src, $this->make_relative_image_url( $img_src ), $html ); + } + } + // also replace background images with absolute urls (used in cover blocks) + $div_tags = $doc->getElementsByTagName( 'div' ); + foreach ( $div_tags as $tag ) { + $style = $tag->getAttribute( 'style' ); + if ( $style ) { + preg_match_all('#\bhttps?://[^,\s()<>]+(?:\([\w\d]+\)|([^,[:punct:]\s]|/))#', $style, $match); + $urls = $match[0]; + foreach ( $urls as $url ) { + if ( $this->is_absolute_url( $url ) ) { + $html = str_replace( $url, $this->make_relative_image_url( $url ), $html ); + } } } } + return $html; } - return $html; + } function make_image_block_local ( $block ) { @@ -650,13 +682,13 @@ function make_media_blocks_local ( $nested_blocks ) { $inner_blocks = $block['innerBlocks']; switch ( $block[ 'blockName' ] ) { case 'core/image': - $block = $this->make_image_block_local($block); + $block = $this->make_image_block_local( $block ); break; case 'core/cover': - $block = $this->make_cover_block_local($block); + $block = $this->make_cover_block_local( $block ); break; case 'core/media-text': - $block = $this->make_mediatext_block_local($block); + $block = $this->make_mediatext_block_local( $block ); break; } // recursive call for inner blocks @@ -670,36 +702,87 @@ function make_media_blocks_local ( $nested_blocks ) { function get_media_absolute_urls_from_blocks ( $flatten_blocks ) { $media = []; - foreach ( $flatten_blocks as $block ) { - if ( 'core/image' === $block[ 'blockName' ] || 'core/cover' === $block[ 'blockName' ] ) { - $doc = new DOMDocument(); - @$doc->loadHTML( $block['innerHTML'], LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD ); - - // Get the media urls from img tags - $tags = $doc->getElementsByTagName( 'img' ); - $block_has_external_images = false; - foreach ($tags as $tag) { - $image_url = $tag->getAttribute( 'src' ); - if ($this->is_absolute_url( $image_url )) { - $media[] = $tag->getAttribute( 'src' ); + + // If WP_HTML_Tag_Processor is available, use it to get the absolute URLs of img and background images + // This class is available in core yet, but it will be available in the future (6.2) + // see https://github.com/WordPress/gutenberg/pull/42485 + if ( class_exists( 'WP_HTML_Tag_Processor' ) ) { + foreach ( $flatten_blocks as $block ) { + // Gets the absolute URLs of img in these blocks + if ( + 'core/image' === $block[ 'blockName' ] || + 'core/cover' === $block[ 'blockName' ] || + 'core/media-text' === $block[ 'blockName' ] + ) { + $html = new WP_HTML_Tag_Processor( $block[ 'innerHTML' ] ); + while ( $html->next_tag( 'img' ) ) { + $url = $html->get_attribute( 'src' ); + if ( $this->is_absolute_url( $url ) ) { + $media[] = $url; + } } } - // Get the media urls from div style tags (used in cover blocks) - $div_tags = $doc->getElementsByTagName( 'div' ); - foreach ( $div_tags as $tag ) { - $style = $tag->getAttribute( 'style' ); - if ( $style ) { - preg_match_all('#\bhttps?://[^,\s()<>]+(?:\([\w\d]+\)|([^,[:punct:]\s]|/))#', $style, $match); - $urls = $match[0]; - foreach ( $urls as $url ) { - if ( $this->is_absolute_url( $url ) ) { - $media[] = $url; + + // Gets the absolute URLs of background images in these blocks + if ( 'core/cover' === $block['blockName'] ) { + $html = new WP_HTML_Tag_Processor( $block[ 'innerHTML' ] ); + while ( $html->next_tag( 'div' ) ) { + $style = $html->get_attribute( 'style' ); + if ( $style ) { + $matches = []; + preg_match( '/background-image: url\((.*)\)/', $style, $matches ); + if ( isset( $matches[1] ) ) { + $url = $matches[1]; + if ( $this->is_absolute_url( $url ) ) { + $media[] = $url; + } } } } } + } } + + // Fallback to DOMDocument. + // TODO: When WP_HTML_Tag_Processor is availabe in core (6.2) we can remove this implementation entirely. + if ( ! class_exists ( 'WP_HTML_Tag_Processor' ) ) { + foreach ( $flatten_blocks as $block ) { + if ( + 'core/image' === $block[ 'blockName' ] || + 'core/cover' === $block[ 'blockName' ] || + 'core/media-text' === $block[ 'blockName' ] + ) { + $doc = new DOMDocument(); + @$doc->loadHTML( $block['innerHTML'], LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD ); + + // Get the media urls from img tags + $tags = $doc->getElementsByTagName( 'img' ); + $block_has_external_images = false; + foreach ($tags as $tag) { + $image_url = $tag->getAttribute( 'src' ); + if ($this->is_absolute_url( $image_url )) { + $media[] = $tag->getAttribute( 'src' ); + } + } + // Get the media urls from div style tags (used in cover blocks) + $div_tags = $doc->getElementsByTagName( 'div' ); + foreach ( $div_tags as $tag ) { + $style = $tag->getAttribute( 'style' ); + if ( $style ) { + preg_match_all('#\bhttps?://[^,\s()<>]+(?:\([\w\d]+\)|([^,[:punct:]\s]|/))#', $style, $match); + $urls = $match[0]; + foreach ( $urls as $url ) { + if ( $this->is_absolute_url( $url ) ) { + $media[] = $url; + } + } + } + } + } + } + } + return $media; } @@ -753,17 +836,38 @@ function escape_text_for_pattern( $text ) { } function escape_alt_for_pattern ( $html ) { - preg_match( '@alt="([^"]+)"@' , $html, $match ); - if ( isset( $match[0] ) ) { - $alt_attribute = $match[0]; - $alt_value= $match[1]; - $html = str_replace( - $alt_attribute, - 'alt="'.$this->escape_text_for_pattern( $alt_value ).'"', - $html - ); + if ( empty ( $html ) ){ + return $html; + } + + // Use WP_HTML_Tag_Processor if available + // see: https://github.com/WordPress/gutenberg/pull/42485 + if ( class_exists( 'WP_HTML_Tag_Processor' ) ) { + $html = new WP_HTML_Tag_Processor( $html ); + while ( $html->next_tag( 'img' ) ) { + // $alt_attribute = $html->get_attribute( 'alt' ); + // if ( !empty ( $alt_attribute ) ) { + $html->set_attribute( 'alt', 'hola' ); + // } + } + return $html->__toString(); + } + + // Fallback to regex + // TODO: When WP_HTML_Tag_Processor is availabe in core (6.2) we can remove this implementation entirely. + if ( ! class_exists( 'WP_HTML_Tag_Processor' ) ) { + preg_match( '@alt="([^"]+)"@' , $html, $match ); + if ( isset( $match[0] ) ) { + $alt_attribute = $match[0]; + $alt_value= $match[1]; + $html = str_replace( + $alt_attribute, + 'alt="'.$this->escape_text_for_pattern( $alt_value ).'"', + $html + ); + } + return $html; } - return $html; } /** From 557ecce927050115769941fa4196b31af326e369 Mon Sep 17 00:00:00 2001 From: Matias Benedetto Date: Wed, 15 Feb 2023 22:37:03 +0700 Subject: [PATCH 09/12] adding theme name to translation mark --- admin/class-create-block-theme-admin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/class-create-block-theme-admin.php b/admin/class-create-block-theme-admin.php index e963ffd7..fc710061 100644 --- a/admin/class-create-block-theme-admin.php +++ b/admin/class-create-block-theme-admin.php @@ -831,7 +831,7 @@ function pattern_from_template ( $template ) { function escape_text_for_pattern( $text ) { if ( $text && trim ( $text ) !== "" ) { - return ''; + return 'get( 'Name' ) .' ) ); ?>'; } } From fe9a6cfb755e9ab7ee84d44e53e80795b3d70d05 Mon Sep 17 00:00:00 2001 From: Matias Benedetto Date: Thu, 16 Feb 2023 16:22:04 +0700 Subject: [PATCH 10/12] support to bundle video block assets --- admin/class-create-block-theme-admin.php | 191 ++++++++++++++++------- 1 file changed, 132 insertions(+), 59 deletions(-) diff --git a/admin/class-create-block-theme-admin.php b/admin/class-create-block-theme-admin.php index fc710061..49dc7835 100644 --- a/admin/class-create-block-theme-admin.php +++ b/admin/class-create-block-theme-admin.php @@ -557,14 +557,18 @@ function get_theme_templates( $export_type, $new_slug ) { } function is_absolute_url( $url ) { - return isset( parse_url( $url )[ 'host' ] ); + return ! empty( $url ) && isset( parse_url( $url )[ 'host' ] ); } - function make_relative_image_url ( $absolute_url ) { - return '/assets/images/'. basename( $absolute_url ); + function make_relative_media_url ( $absolute_url ) { + if ( ! empty ( $absolute_url ) && $this->is_absolute_url( $absolute_url ) ) { + $folder_path = $this->get_media_folder_path_from_url( $absolute_url ); + return '' . $folder_path . basename( $absolute_url ); + } + return $absolute_url; } - function make_html_images_local ( $html ) { + function make_html_media_local ( $html ) { if ( empty( $html ) ) { return $html; } @@ -577,9 +581,19 @@ function make_html_images_local ( $html ) { $html = new WP_HTML_Tag_Processor( $html ); while ( $html->next_tag( 'img' ) ) { if ( $this->is_absolute_url( $html->get_attribute( 'src' ) ) ) { - $html->set_attribute( 'src', $this->make_relative_image_url( $html->get_attribute( 'src' ) ) ); + $html->set_attribute( 'src', $this->make_relative_media_url( $html->get_attribute( 'src' ) ) ); + } + } + $html = new WP_HTML_Tag_Processor( $html->__toString() ); + while ( $html->next_tag( 'video' ) ) { + if ( $this->is_absolute_url( $html->get_attribute( 'src' ) ) ) { + $html->set_attribute( 'src', $this->make_relative_media_url( $html->get_attribute( 'src' ) ) ); + } + if ( $this->is_absolute_url( $html->get_attribute( 'poster' ) ) ) { + $html->set_attribute( 'poster', $this->make_relative_media_url( $html->get_attribute( 'poster' ) ) ); } } + $html = new WP_HTML_Tag_Processor( $html->__toString() ); while ( $html->next_tag( 'div' ) ) { $style = $html->get_attribute( 'style' ); if ( $style ) { @@ -587,7 +601,7 @@ function make_html_images_local ( $html ) { $urls = $match[0]; foreach ( $urls as $url ) { if ( $this->is_absolute_url( $url ) ) { - $html->set_attribute( 'style', str_replace( $url, $this->make_relative_image_url( $url ), $style ) ); + $html->set_attribute( 'style', str_replace( $url, $this->make_relative_media_url( $url ), $style ) ); } } } @@ -600,13 +614,26 @@ function make_html_images_local ( $html ) { if ( ! class_exists( 'WP_HTML_Tag_Processor' ) ) { $doc = new DOMDocument(); @$doc->loadHTML( $html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD ); - $img_tags = $doc->getElementsByTagName( 'img' ); // replace all images that have absolute urls + $img_tags = $doc->getElementsByTagName( 'img' ); foreach ( $img_tags as $tag ) { $image_url = $tag->getAttribute( 'src' ); if ( $this->is_absolute_url( $image_url ) ) { $img_src = $tag->getAttribute( 'src' ); - $html = str_replace( $img_src, $this->make_relative_image_url( $img_src ), $html ); + $html = str_replace( $img_src, $this->make_relative_media_url( $img_src ), $html ); + } + } + // replace all video that have absolute urls + $video_tags = $doc->getElementsByTagName( 'video' ); + foreach ( $video_tags as $tag ) { + $video_url = $tag->getAttribute( 'src' ); + if ( !empty( $video_url ) && $this->is_absolute_url( $video_url ) ) { + $video_src = $tag->getAttribute( 'src' ); + $html = str_replace( $video_src, $this->make_relative_media_url( $video_src ), $html ); + } + $poster_url = $tag->getAttribute( 'poster' ); + if ( !empty ( $poster_url ) && $this->is_absolute_url( $poster_url ) ) { + $html = str_replace( $poster_url, $this->make_relative_media_url( $poster_url ), $html ); } } // also replace background images with absolute urls (used in cover blocks) @@ -618,7 +645,7 @@ function make_html_images_local ( $html ) { $urls = $match[0]; foreach ( $urls as $url ) { if ( $this->is_absolute_url( $url ) ) { - $html = str_replace( $url, $this->make_relative_image_url( $url ), $html ); + $html = str_replace( $url, $this->make_relative_media_url( $url ), $html ); } } } @@ -628,9 +655,9 @@ function make_html_images_local ( $html ) { } - function make_image_block_local ( $block ) { - if ( 'core/image' === $block[ 'blockName' ] ) { - $inner_html = $this->make_html_images_local( $block[ 'innerHTML' ] ); + function make_image_video_block_local ( $block ) { + if ( 'core/image' === $block[ 'blockName' ] || 'core/video' === $block[ 'blockName' ] ) { + $inner_html = $this->make_html_media_local( $block[ 'innerHTML' ] ); $inner_html = $this->escape_alt_for_pattern ( $inner_html ); $block['innerHTML'] = $inner_html; $block['innerContent'] = array ( $inner_html ); @@ -640,18 +667,18 @@ function make_image_block_local ( $block ) { function make_cover_block_local ( $block ) { if ( 'core/cover' === $block[ 'blockName' ] ) { - $inner_html = $this->make_html_images_local( $block[ 'innerHTML' ] ); + $inner_html = $this->make_html_media_local( $block[ 'innerHTML' ] ); $inner_html = $this->escape_alt_for_pattern ( $inner_html ); $inner_content = []; foreach ( $block['innerContent'] as $content ) { - $content_html = $this->make_html_images_local( $content ); + $content_html = $this->make_html_media_local( $content ); $content_html = $this->escape_alt_for_pattern ( $content_html ); $inner_content[] = $content_html; } $block['innerHTML'] = $inner_html; $block['innerContent'] = $inner_content; if ( isset ( $block['attrs']['url'] ) && $this->is_absolute_url( $block['attrs']['url'] ) ) { - $block['attrs']['url'] = $this->make_relative_image_url( $block['attrs']['url'] ); + $block['attrs']['url'] = $this->make_relative_media_url( $block['attrs']['url'] ); } } return $block; @@ -659,18 +686,18 @@ function make_cover_block_local ( $block ) { function make_mediatext_block_local ( $block ) { if ( 'core/media-text' === $block[ 'blockName' ] ) { - $inner_html = $this->make_html_images_local( $block[ 'innerHTML' ] ); + $inner_html = $this->make_html_media_local( $block[ 'innerHTML' ] ); $inner_html = $this->escape_alt_for_pattern ( $inner_html ); $inner_content = []; foreach ( $block['innerContent'] as $content ) { - $content_html = $this->make_html_images_local( $content ); + $content_html = $this->make_html_media_local( $content ); $content_html = $this->escape_alt_for_pattern ( $content_html ); $inner_content[] = $content_html; } $block['innerHTML'] = $inner_html; $block['innerContent'] = $inner_content; if ( isset ( $block['attrs']['mediaLink'] ) && $this->is_absolute_url( $block['attrs']['mediaLink'] ) ) { - $block['attrs']['mediaLink'] = $this->make_relative_image_url( $block['attrs']['mediaLink'] ); + $block['attrs']['mediaLink'] = $this->make_relative_media_url( $block['attrs']['mediaLink'] ); } } return $block; @@ -682,7 +709,8 @@ function make_media_blocks_local ( $nested_blocks ) { $inner_blocks = $block['innerBlocks']; switch ( $block[ 'blockName' ] ) { case 'core/image': - $block = $this->make_image_block_local( $block ); + case 'core/video': + $block = $this->make_image_video_block_local( $block ); break; case 'core/cover': $block = $this->make_cover_block_local( $block ); @@ -711,6 +739,7 @@ function get_media_absolute_urls_from_blocks ( $flatten_blocks ) { // Gets the absolute URLs of img in these blocks if ( 'core/image' === $block[ 'blockName' ] || + 'core/video' === $block[ 'blockName' ] || 'core/cover' === $block[ 'blockName' ] || 'core/media-text' === $block[ 'blockName' ] ) { @@ -721,6 +750,17 @@ function get_media_absolute_urls_from_blocks ( $flatten_blocks ) { $media[] = $url; } } + $html = new WP_HTML_Tag_Processor( $html->__toString() ); + while ( $html->next_tag( 'video' ) ) { + $url = $html->get_attribute( 'src' ); + if ( $this->is_absolute_url( $url ) ) { + $media[] = $url; + } + $poster_url = $html->get_attribute( 'poster' ); + if ( $this->is_absolute_url( $poster_url ) ) { + $media[] = $poster_url; + } + } } // Gets the absolute URLs of background images in these blocks @@ -750,6 +790,7 @@ function get_media_absolute_urls_from_blocks ( $flatten_blocks ) { foreach ( $flatten_blocks as $block ) { if ( 'core/image' === $block[ 'blockName' ] || + 'core/video' === $block[ 'blockName' ] || 'core/cover' === $block[ 'blockName' ] || 'core/media-text' === $block[ 'blockName' ] ) { @@ -758,13 +799,24 @@ function get_media_absolute_urls_from_blocks ( $flatten_blocks ) { // Get the media urls from img tags $tags = $doc->getElementsByTagName( 'img' ); - $block_has_external_images = false; - foreach ($tags as $tag) { + foreach ( $tags as $tag ) { $image_url = $tag->getAttribute( 'src' ); if ($this->is_absolute_url( $image_url )) { $media[] = $tag->getAttribute( 'src' ); } } + // Get the media urls from video tags + $tags = $doc->getElementsByTagName( 'video' ); + foreach ( $tags as $tag ) { + $video_url = $tag->getAttribute( 'src' ); + if ($this->is_absolute_url( $video_url )) { + $media[] = $tag->getAttribute( 'src' ); + } + $poster_url = $tag->getAttribute( 'poster' ); + if ($this->is_absolute_url( $poster_url )) { + $media[] = $tag->getAttribute( 'poster' ); + } + } // Get the media urls from div style tags (used in cover blocks) $div_tags = $doc->getElementsByTagName( 'div' ); foreach ( $div_tags as $tag ) { @@ -802,10 +854,9 @@ function make_template_images_local ( $template ) { function clean_serialized_markup ( $markup ) { $markup = str_replace( '%20', ' ', $markup ); - $markup = str_replace( '<', '<', $markup ); - $markup = str_replace( '>', '>', $markup ); $markup = str_replace( '\u003c', '<', $markup ); $markup = str_replace( '\u003e', '>', $markup ); + $markup = html_entity_decode( $markup, ENT_QUOTES | ENT_XML1, 'UTF-8' ); return $markup; } @@ -831,7 +882,8 @@ function pattern_from_template ( $template ) { function escape_text_for_pattern( $text ) { if ( $text && trim ( $text ) !== "" ) { - return 'get( 'Name' ) .' ) ); ?>'; + return "get( "Name" ) ."' ); ?>"; + } } @@ -845,10 +897,10 @@ function escape_alt_for_pattern ( $html ) { if ( class_exists( 'WP_HTML_Tag_Processor' ) ) { $html = new WP_HTML_Tag_Processor( $html ); while ( $html->next_tag( 'img' ) ) { - // $alt_attribute = $html->get_attribute( 'alt' ); - // if ( !empty ( $alt_attribute ) ) { - $html->set_attribute( 'alt', 'hola' ); - // } + $alt_attribute = $html->get_attribute( 'alt' ); + if ( !empty ( $alt_attribute ) ) { + $html->set_attribute( 'alt', $this->escape_text_for_pattern( $alt_attribute ) ); + } } return $html->__toString(); } @@ -870,6 +922,49 @@ function escape_alt_for_pattern ( $html ) { } } + function get_media_folder_path_from_url ( $url ) { + $extension = strtolower( pathinfo( $url, PATHINFO_EXTENSION ) ); + $folder_path = ""; + $image_extensions = [ 'jpg', 'jpeg', 'png', 'gif', 'svg', 'webp' ]; + $video_extensions = [ 'mp4', 'm4v', 'webm', 'ogv', 'wmv', 'avi', 'mov', 'mpg', 'ogv', '3gp', '3g2' ]; + if ( in_array( $extension, $image_extensions ) ) { + $folder_path = "/assets/images/"; + } else if ( in_array( $extension, $video_extensions ) ) { + $folder_path = "/assets/videos/"; + } else { + $folder_path = "/assets/"; + } + return $folder_path; + } + + function get_file_extension_from_url ( $url ) { + $extension = pathinfo( $url, PATHINFO_EXTENSION ); + return $extension; + } + + function add_media_to_zip ( $zip, $media ) { + $media = array_unique( $media ); + foreach ( $media as $url ) { + $folder_path = $this->get_media_folder_path_from_url( $url ); + $download_file = file_get_contents( $url ); + $zip->addFromString( $folder_path . basename( $url ), $download_file ); + } + } + + function add_media_to_local ( $media ) { + foreach ( $media as $url ) { + $download_file = file_get_contents( $url ); + $media_path = get_stylesheet_directory() . DIRECTORY_SEPARATOR . $this->get_media_folder_path_from_url ( $url ); + if ( ! is_dir( $media_path ) ) { + wp_mkdir_p( $media_path ); + } + file_put_contents( + $media_path . basename( $url ), + $download_file + ); + } + } + /** * Add block templates and parts to the zip. * @@ -905,11 +1000,8 @@ function add_templates_to_zip( $zip, $export_type, $new_slug ) { $pattern[ 'content' ] ); - // Add image assets to zip - foreach ( $template_data->media as $media ) { - $download_file = file_get_contents( $media ); - $zip->addFromString( 'assets/images/' . basename( $media ), $download_file ); - } + // Add media assets to zip + $this->add_media_to_zip( $zip, $template_data->media ); } // Add template to zip @@ -934,11 +1026,8 @@ function add_templates_to_zip( $zip, $export_type, $new_slug ) { $pattern[ 'content' ] ); - // Add image assets to zip - foreach ( $template_data->media as $media ) { - $download_file = file_get_contents( $media ); - $zip->addFromString( 'assets/images/' . basename( $media ), $download_file ); - } + // Add media assets to zip + $this->add_media_to_zip( $zip, $template_data->media ); } // Add template to zip @@ -961,10 +1050,6 @@ function add_templates_to_local( $export_type ) { wp_mkdir_p( get_stylesheet_directory() . DIRECTORY_SEPARATOR . $template_folders['wp_template'] ); } - if ( ! is_dir( get_stylesheet_directory() . '/assets/images' ) ) { - wp_mkdir_p( get_stylesheet_directory() . '/assets/images' ); - } - foreach ( $theme_templates->templates as $template ) { $template_data = $this->make_template_images_local( $template ); @@ -992,15 +1077,9 @@ function add_templates_to_local( $export_type ) { $template_data->content ); - // Write the image assets - foreach ( $template_data->media as $media ) { - $download_file = file_get_contents( $media ); - file_put_contents( - get_stylesheet_directory() . DIRECTORY_SEPARATOR .'assets' . DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR . basename( $media ), - $download_file - ); - } - + // Write the media assets + $this->add_media_to_local( $template_data->media ); + } // If there is no parts folder, create it. @@ -1035,14 +1114,8 @@ function add_templates_to_local( $export_type ) { $template_data->content ); - // Write the image assets - foreach ( $template_data->media as $media ) { - $download_file = file_get_contents( $media ); - file_put_contents( - get_stylesheet_directory() . DIRECTORY_SEPARATOR .'assets' . DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR . basename( $media ), - $download_file - ); - } + // Write the media assets + $this->add_media_to_local( $template_data->media ); } } From 6f0000205cee02cb9ab0e8f14873d07a5fb0a7ce Mon Sep 17 00:00:00 2001 From: Matias Benedetto Date: Thu, 16 Feb 2023 17:45:59 +0700 Subject: [PATCH 11/12] Fix the template parts included in patterns --- admin/class-create-block-theme-admin.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/admin/class-create-block-theme-admin.php b/admin/class-create-block-theme-admin.php index 49dc7835..dcc0e1ff 100644 --- a/admin/class-create-block-theme-admin.php +++ b/admin/class-create-block-theme-admin.php @@ -703,6 +703,16 @@ function make_mediatext_block_local ( $block ) { return $block; } + function add_theme_attr_to_template_part_block ( $block ) { + // The template parts included in the patterns need to indicate the theme they belong to + if ( 'core/template-part' === $block[ 'blockName' ] ) { + $block['attrs']['theme'] = ( $_POST['theme']['type'] === "export" || $_POST['theme']['type'] === "save" ) + ? get_stylesheet() + : $_POST['theme']['name']; + } + return $block; + } + function make_media_blocks_local ( $nested_blocks ) { $new_blocks = []; foreach ( $nested_blocks as $block ) { @@ -718,6 +728,9 @@ function make_media_blocks_local ( $nested_blocks ) { case 'core/media-text': $block = $this->make_mediatext_block_local( $block ); break; + case 'core/template-part': + $block = $this->add_theme_attr_to_template_part_block( $block ); + break; } // recursive call for inner blocks if ( !empty ( $block['innerBlocks'] ) ) { From def9cb48be22a867e33d2152309ccbfe6fedc738 Mon Sep 17 00:00:00 2001 From: Matias Benedetto Date: Fri, 17 Feb 2023 00:18:00 +0700 Subject: [PATCH 12/12] fixing theme slug in template part linked from a pattern --- admin/class-create-block-theme-admin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/class-create-block-theme-admin.php b/admin/class-create-block-theme-admin.php index dcc0e1ff..7c6b498e 100644 --- a/admin/class-create-block-theme-admin.php +++ b/admin/class-create-block-theme-admin.php @@ -707,7 +707,7 @@ function add_theme_attr_to_template_part_block ( $block ) { // The template parts included in the patterns need to indicate the theme they belong to if ( 'core/template-part' === $block[ 'blockName' ] ) { $block['attrs']['theme'] = ( $_POST['theme']['type'] === "export" || $_POST['theme']['type'] === "save" ) - ? get_stylesheet() + ? strtolower( wp_get_theme()->get( 'Name' ) ) : $_POST['theme']['name']; } return $block;