Commit realizado el 12:13:52 08-04-2024

This commit is contained in:
Pagina Web Monito
2024-04-08 12:13:55 -04:00
commit 0c33094de9
7815 changed files with 1365694 additions and 0 deletions

View File

@@ -0,0 +1,261 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
/**
* Class ET_GB_Utils_Conversion
*
* Handling Gutenberg serialized content conversion into builder shortcode layout
*/
class ET_GB_Utils_Conversion {
// Populate all layout block which is placed inside other block. Layout block contains
// section which has to be the first level element once converted into VB content
private $deep_layout_blocks = array();
// Layout list. Layout block got its own section. Others are concatenated into text module
private $layout_list = array();
// Temporary variable to hold non layout block into one
private $text_module_content = '';
// Serialized layout
private $shortcode_layout = '';
/**
* Check if given block is layout block
*
* @since 4.1.0
*
* @todo being set as static so it is easier to be used outside this class. If being used quite
* frequently, probably consider wrap this into function. Not needed at the moment tho
*
* @param array $block Parsed block.
*
* @return bool
*/
public static function is_layout_block( $block = array() ) {
$block_name = et_()->array_get( $block, 'blockName', '' );
return 'divi/layout' === $block_name;
}
/**
* Check if given block is reusable block
*
* @since 4.1.0
*
* @todo being set as static so it is easier to be used outside this class. If being used quite
* frequently, probably consider wrap this into function. Not needed at the moment tho
*
* @param array $block Parsed block.
*
* @return bool
*/
public static function is_reusable_block( $block = array() ) {
$block_name = et_()->array_get( $block, 'blockName', '' );
return 'core/block' === $block_name && et_()->array_get( $block, 'attrs.ref' ) > 0;
}
/**
* Get reusable block's parsed content. NOTE: WordPress has built in `render_block_core_block()`
* but it renders the block and its content instead of parse its content.
*
* @since 4.1.0
*
* @see render_block_core_block()
*
* @todo being set as static so it is easier to be used outside this class. If being used quite
* frequently, probably consider wrap this into function. Not needed at the moment tho
*
* @param array $block Parsed block.
*
* @return array
*/
public static function get_reusable_block_content( $block ) {
$block_id = et_()->array_get( $block, 'attrs.ref' );
$block_data = get_post( $block_id );
if ( ! $block_data || 'wp_block' !== $block_data->post_type || 'publish' !== $block_data->post_status ) {
return array();
}
return parse_blocks( $block_data->post_content );
}
/**
* Parse reusable block by getting its content and append it as innerBlocks
*
* @since 4.1.0
*
* @param array Parsed block.
*
* @return array Modified parsed block.
*/
public static function parse_reusable_block( $block ) {
$reusable_block_data = self::get_reusable_block_content( $block );
$block['innerBlocks'] = array_merge( $block['innerBlocks'], $reusable_block_data );
// Unset reusable block's ref attribute so reusable block content is no longer fetched
unset( $block['attrs']['ref'] );
// Change block into group so its content is being rendered
$block['blockName'] = 'core/group';
// Recreate innerContent which is used by block parser to render innerBlock.
// See: `render_block()`'s `$block['innerContent'] as $chunk` loop
$block['innerContent'] = array_merge(
array( '<div class="wp-block-group"><div class="wp-block-group__inner-container">' ),
array_fill( 0, count( $block['innerBlocks'] ), null ),
array( '</div></div>' )
);
return $block;
}
/**
* Pull layout block that is located deep inside inner blocks. Layout block contains section;
* in builder, section has to be on the first level of document
*
* @since 4.1.0
*
* @param array $block Parsed block.
*/
private function pull_layout_block( $block ) {
// Pull and populate layout block. Layout block contains section(s) so it should be rendered
// on first level layout, below Gutenberg content inside text module
if ( self::is_layout_block( $block ) ) {
// Pull layout block and populate list of layout block located on inner blocks
$this->deep_layout_blocks[] = $block;
// Remove innerContent and innerHTML value because inner block can't be simply removed
// due to nested block rendering relies on `$block['innerContent']` making cross reference
// on `$block['innerBlocks']` and removing them causes error (see: `render_block()`'s
// `$block['innerContent'] as $chunk` loop). Thus, set deep layout block's content empty
// so it doesn't get rendered
$block['innerHTML'] = '';
$block['innerContent'] = array();
return $block;
}
// Reusable block's content is not saved inside block; Thus Get reusable block's content,
// append it as innerBlock, and pull layout block if exist.
if ( self::is_reusable_block( $block ) ) {
$block = self::parse_reusable_block( $block );
}
// Recursively loop over block then pull Layout Block
if ( ! empty( $block['innerBlocks'] ) ) {
$block['innerBlocks'] = array_map(
array( $this, 'pull_layout_block' ),
$block['innerBlocks']
);
}
return $block;
}
/**
* Convert serialized block into shortcode layout
*
* @since 4.1.0
*
* @param string $serialized_block
*
* @return string
*/
public function block_to_shortcode( $serialized_block = '' ) {
// Wrapper div needs to be trimmed
$layout_open_tag = '<div class="wp-block-divi-layout">';
$layout_open_length = strlen( $layout_open_tag );
$layout_close_tag = '</div>';
$layout_close_length = strlen( $layout_close_tag );
// Parsed blocks
$blocks = parse_blocks( $serialized_block );
// Loop blocks
foreach ( $blocks as $block ) {
if ( self::is_layout_block( $block ) ) {
// Append currently populated non-Layout Block into one before layout block is appended
if ( ! empty( $this->text_module_content ) ) {
$this->layout_list[] = $this->text_module_content;
// Reset text module content so next non-layout block is placed below current layout block
$this->text_module_content = '';
}
$this->layout_list[] = $block;
} else {
// Reusable block's content is not saved inside block; Thus Get reusable block's
// content, append it as innerBlock, and pull layout block if exist.
if ( self::is_reusable_block( $block ) ) {
$block = self::parse_reusable_block( $block );
}
// Pull any Layout Block inside nested block if there's any
if ( ! empty( $block['innerBlocks'] ) ) {
$block['innerBlocks'] = array_map(
array( $this, 'pull_layout_block' ),
$block['innerBlocks']
);
}
// Populate block into temporary text module content buffer
$this->text_module_content .= render_block( $block );
}
}
// Populate remaining non-layout block into layout list
if ( ! empty( $this->text_module_content ) ) {
$this->layout_list[] = $this->text_module_content;
// Reset
$this->text_module_content = '';
}
// Loop over populated content and render it into shortcode layout
foreach ( array_merge( $this->layout_list, $this->deep_layout_blocks ) as $item ) {
if ( self::is_layout_block( $item ) ) {
$shortcode_layout = trim( et_()->array_get( $item, 'innerHTML', '' ) );
// Remove layout content opening <div>
if ( $layout_open_tag === substr( $shortcode_layout, 0, $layout_open_length ) ) {
$shortcode_layout = substr( $shortcode_layout, $layout_open_length );
}
// Remove layout content closing </div>
if ( $layout_close_tag === substr( $shortcode_layout, ( 0 - $layout_close_length ) ) ) {
$shortcode_layout = substr( $shortcode_layout, 0, ( 0 - $layout_close_length ) );
}
$this->shortcode_layout .= $shortcode_layout;
} else {
$text_module = '[et_pb_text]' . $item . '[/et_pb_text]';
$column = '[et_pb_column type="4_4"]' . $text_module . '[/et_pb_column]';
$row = '[et_pb_row admin_label="row"]' . $column . '[/et_pb_row]';
$this->shortcode_layout .= '[et_pb_section admin_label="section"]' . $row . '[/et_pb_section]';
}
}
return $this->shortcode_layout;
}
}
/**
* Convert gutenberg block layout into shortcode.
* NOTE: There is JS version for activation via Gutenberg. See: `convertBlockToShortcode()`
*
* @since 4.1.0
*
* @param string $post_content Post content / serialized block.
*
* @return string Shortcode layout.
*/
function et_builder_convert_block_to_shortcode( $post_content ) {
$conversion = new ET_GB_Utils_Conversion();
return $conversion->block_to_shortcode( $post_content );
}

View File

@@ -0,0 +1,198 @@
<?php
/**
* Helpers needed for the WP Editor compatibility.
*
* @package Divi
* @subpackage Builder
* @since 4.14.8
*/
if ( ! defined( 'ET_WP_EDITOR_TEMPLATE_POST_TYPE' ) ) {
define( 'ET_WP_EDITOR_TEMPLATE_POST_TYPE', 'wp_template' );
}
if ( ! defined( 'ET_WP_EDITOR_TEMPLATE_PART_POST_TYPE' ) ) {
define( 'ET_WP_EDITOR_TEMPLATE_PART_POST_TYPE', 'wp_template_part' );
}
if ( ! function_exists( 'et_builder_get_wp_editor_template_post_types' ) ) {
/**
* Get supported WP Editor template post types.
*
* At this moment, the list is:
* - wp_template
* - wp_template_part
*
* @since 4.14.8
*
* @return array List of supported WP Editor template post types.
*/
function et_builder_get_wp_editor_template_post_types() {
// Supported WP Editor template post types.
$post_types = array(
ET_WP_EDITOR_TEMPLATE_POST_TYPE,
ET_WP_EDITOR_TEMPLATE_PART_POST_TYPE,
);
return $post_types;
}
}
if ( ! function_exists( 'et_builder_is_wp_editor_template_post_type' ) ) {
/**
* Whether current post type is supported WP Editor template post type or not.
*
* @since 4.14.8
*
* @param string $type Template post type.
*
* @return boolean Post type check status.
*/
function et_builder_is_wp_editor_template_post_type( $type ) {
return in_array( $type, et_builder_get_wp_editor_template_post_types(), true );
}
}
if ( ! function_exists( 'et_builder_wp_editor_decorate_page_resource_slug' ) ) {
/**
* Decorate a page resource slug based on the current request and WP Editor.
*
* @since 4.14.8
*
* @param integer|string $post_id Post ID.
* @param string $resource_slug Resource slug.
*
* @return string
*/
function et_builder_wp_editor_decorate_page_resource_slug( $post_id, $resource_slug ) {
// Bail early if current page is not singular.
if ( ! is_numeric( $post_id ) || ! is_singular() ) {
return $resource_slug;
}
$templates = et_builder_get_wp_editor_templates();
// Bail early if current page doesn't have templates.
if ( empty( $templates ) ) {
return $resource_slug;
}
foreach ( $templates as $template ) {
// The `wpe` is stand for WP Editor.
$template_id = isset( $template->wp_id ) ? (int) $template->wp_id : 0;
$resource_slug .= $template_id ? '-wpe-' . $template_id : '';
}
return $resource_slug;
}
}
if ( ! function_exists( 'et_builder_get_wp_editor_templates' ) ) {
/**
* Get WP Editor templates on current post.
*
* @since 4.14.8
*
* @return array List of templates and template parts.
*/
function et_builder_get_wp_editor_templates() {
static $templates = null;
// Bail early if the list is already processed.
if ( null !== $templates ) {
return $templates;
}
$templates = array();
// Bail early if `get_block_template` function doesn't exist because we need it to
// get template data. This function is introduced on WP 5.8 along with Template and
// Template Parts editors.
if ( ! function_exists( 'get_block_template' ) ) {
return $templates;
}
// Bail early if current page is not singular.
if ( ! is_singular() ) {
return $templates;
}
global $post;
// Bail early if current post doesn't have page template.
if ( empty( $post->page_template ) ) {
return $templates;
}
// A. Template.
// Get block template data based on post slug and post type.
$template = get_block_template( get_stylesheet() . '//' . $post->page_template, ET_WP_EDITOR_TEMPLATE_POST_TYPE );
// Bail early if the template is empty.
if ( empty( $template ) ) {
return $templates;
}
$template_id = isset( $template->wp_id ) ? (int) $template->wp_id : 0;
$templates[ $template_id ] = $template;
// Parse and fetch blocks list in the template to find the template parts.
$blocks = parse_blocks( $template->content );
// Bail early if the blocks is empty.
if ( empty( $blocks ) ) {
return $templates;
}
foreach ( $blocks as $block ) {
$name = et_()->array_get( $block, 'blockName' );
$slug = et_()->array_get( $block, array( 'attrs', 'slug' ) );
// Skip if current block is not template part.
if ( 'core/template-part' !== $name || empty( $slug ) ) {
continue;
}
// B. Template Parts.
// Get block template part data based on post slug and post type.
$template_part = get_block_template( get_stylesheet() . '//' . $slug, ET_WP_EDITOR_TEMPLATE_PART_POST_TYPE );
// Skip if the template part is empty.
if ( empty( $template_part ) ) {
continue;
}
$template_part_id = isset( $template_part->wp_id ) ? (int) $template_part->wp_id : 0;
$templates[ $template_part_id ] = $template_part;
}
return $templates;
}
}
if ( ! function_exists( 'et_builder_is_block_theme' ) ) {
/**
* Whether current theme is block theme or not.
*
* @since 4.17.4
*
* @return boolean Block theme status.
*/
function et_builder_is_block_theme() {
// Use `wp_is_block_theme` on WP 5.9.
if ( function_exists( 'wp_is_block_theme' ) ) {
return (bool) wp_is_block_theme();
}
// Use `gutenberg_is_fse_theme` on GB plugin.
if ( function_exists( 'gutenberg_is_fse_theme' ) ) {
return (bool) gutenberg_is_fse_theme();
}
// Use manual check on WP 5.8 below.
$block_templates_index_html_file = get_stylesheet_directory() . '/block-templates/index.html';
$templates_index_html_file = get_stylesheet_directory() . '/templates/index.html';
return is_readable( $block_templates_index_html_file ) || is_readable( $templates_index_html_file );
}
}