0 ) { $settingsData = (array) json_decode( html_entity_decode( stripslashes( $settingsData ) ) ); } } else { $settings[ 'responsiveBreakpoints' ] = [ 'tablet' => 1024, 'mobile' => 767 ]; update_option( 'eb_settings', $settings ); $settingsData = $settings[ 'responsiveBreakpoints' ]; } return $settingsData[ $size ]; } /** * Recursive function for parsing blocks */ public static function eb_block_style_recursive( $block, &$eb_blocks ) { if ( count( $block ) > 0 ) { foreach ( $block as $item ) { $attributes = $item[ 'attrs' ]; $blockId = ""; if ( isset( $attributes[ 'blockId' ] ) && ! empty( $attributes[ 'blockId' ] ) ) { $blockId = $attributes[ 'blockId' ]; } $blockMeta = ""; if ( isset( $attributes[ 'blockMeta' ] ) && ! empty( $attributes[ 'blockMeta' ] ) ) { $blockMeta = $attributes[ 'blockMeta' ]; } $commonStyles = ""; if ( isset( $attributes[ 'commonStyles' ] ) && ! empty( $attributes[ 'commonStyles' ] ) ) { $commonStyles = $attributes[ 'commonStyles' ]; } $customCss = ""; if ( isset( $attributes[ 'customCss' ] ) && ! empty( $attributes[ 'customCss' ] ) ) { $customCss = $attributes[ 'customCss' ]; } if ( isset( $attributes[ 'ref' ] ) && ! empty( $attributes[ 'ref' ] ) && $item[ "blockName" ] === "core/block" ) { // `ref` comes from the saved block and can name any post ID. // Only a published reusable block (wp_block) is read: anything // else (another user's private post, a missing ID) is skipped, // so its CSS is never copied into a public file. $reusable_block = get_post( absint( $attributes[ 'ref' ] ) ); if ( $reusable_block instanceof WP_Post && 'wp_block' === $reusable_block->post_type && 'publish' === $reusable_block->post_status ) { $reusable_content = parse_blocks( $reusable_block->post_content ); $reusable_blocks = [ ]; $eb_blocks[ "reusableBlocks" ][ $reusable_block->ID ] = self::eb_block_style_recursive( $reusable_content, $reusable_blocks ); } } else { if ( isset( $item[ "innerBlocks" ] ) && count( $item[ "innerBlocks" ] ) > 0 ) { self::eb_block_style_recursive( $item[ 'innerBlocks' ], $eb_blocks ); if ( isset( $attributes[ 'blockMeta' ] ) && ! empty( $attributes[ 'blockMeta' ] ) ) { $eb_blocks[ $blockId ] = [ 'blockMeta' => $blockMeta, 'commonStyles' => $commonStyles, 'customCss' => $customCss ]; } } else if ( isset( $attributes[ 'blockMeta' ] ) && ! empty( $attributes[ 'blockMeta' ] ) ) { $eb_blocks[ $blockId ] = [ 'blockMeta' => $blockMeta, 'commonStyles' => $commonStyles, 'customCss' => $customCss ]; } } } } return $eb_blocks; } /** * Blockarray to Style Array Function */ public static function blocks_to_style_array( $blocks, $styles = [ ] ) { if ( is_array( $blocks ) && count( $blocks ) > 0 ) { foreach ( $blocks as $blockId => $block ) { if ( 'reusableBlocks' === $blockId ) { if ( is_array( $block ) && count( $block ) > 0 ) { foreach ( $block as $reusableId => $reusableBlock ) { self::blocks_to_style_array( $reusableBlock, $styles ); } } } else { $styles[ $blockId ] = [ 'desktop' => "", 'tab' => "", 'mobile' => "", 'customCss' => "" ]; if ( is_array( $block ) && count( $block ) > 0 ) { foreach ( $block as $value ) { if ( is_array( $value ) && count( $value ) > 0 ) { if ( isset( $value[ "desktop" ] ) ) { $styles[ $blockId ][ "desktop" ] .= $value[ "desktop" ]; } if ( isset( $value[ "tab" ] ) ) { $styles[ $blockId ][ "tab" ] .= $value[ "tab" ]; } if ( isset( $value[ "mobile" ] ) ) { $styles[ $blockId ][ "mobile" ] .= $value[ "mobile" ]; } } else if ( isset( $block[ 'customCss' ] ) && is_string( $block[ 'customCss' ] ) && strlen( $block[ 'customCss' ] ) > 0 ) { $styles[ $blockId ][ "customCss" ] .= $block[ 'customCss' ]; } } } } } } return $styles; } /** * Whether CSS stored with a post may be written to a public file as is. * * Block CSS (blockMeta, commonStyles, customCss) and blockId are block * attributes, so anyone who can save a post controls them. Content by an * author without unfiltered_html is passed through sanitize_css(). * * @param WP_Post|null $post Post the CSS belongs to. * @return bool */ public static function is_trusted_post( $post ) { if ( ! ( $post instanceof WP_Post ) || empty( $post->post_author ) ) { return false; } // On a save the editor's own rights count too: on multisite, an Editor could // otherwise update a Super Admin's post and get unsanitized CSS. if ( doing_action( 'save_post' ) && ! current_user_can( 'unfiltered_html' ) ) { return false; } return user_can( (int) $post->post_author, 'unfiltered_html' ); } /** * Remove constructs that have no place in block styles: @import (loads * remote CSS), at-rules hidden behind CSS escapes, legacy script-in-CSS * (expression(), behavior, -moz-binding), script URLs and anything that * looks like markup. * * @param string $css CSS. * @return string */ public static function sanitize_css( $css ) { if ( ! is_string( $css ) || '' === $css ) { return ''; } // No markup can be formed without "<" (or its CSS escape). $css = str_replace( [ '<', '\\3c', '\\3C' ], '', $css ); // Comments can sit inside url() or split a keyword, so drop them before matching. $css = preg_replace( '#/\*.*?(?:\*/|$)#s', '', $css ); $css = preg_replace( '/@import\b[^;]*;?/i', '', $css ); // An escaped at-keyword such as `@\69mport` is still @import to a browser. $css = preg_replace( '/@[\w-]*\\\\[^;{]*;?/', '', $css ); $css = preg_replace( '/expression\s*\(/i', '(', $css ); $css = preg_replace( '/(?:javascript|vbscript)\s*:/i', '', $css ); // Match the property only, so scroll-behavior and the like are kept. $css = preg_replace( '/(? $block_style ) { $block_style_key = self::sanitize_block_key( $block_style_key ); if ( $sanitize && is_array( $block_style ) ) { $block_style = array_map( [ __CLASS__, 'sanitize_css' ], $block_style ); } if ( ! empty( $block_css = (array) $block_style ) ) { $css .= sprintf( '/* %1$s Starts */', $block_style_key ); foreach ( $block_css as $media => $style ) { switch ( $media ) { case "desktop": $css .= preg_replace( '/\s+/', ' ', $style ); break; case "tab": $css .= ' @media(max-width: ' . self::get_responsive_breakpoints( 'tablet' ) . 'px){'; $css .= preg_replace( '/\s+/', ' ', $style ); $css .= '}'; break; case "mobile": $css .= ' @media(max-width: ' . self::get_responsive_breakpoints( 'mobile' ) . 'px){'; $css .= preg_replace( '/\s+/', ' ', $style ); $css .= '}'; break; case "customCss": $css .= preg_replace( '/\s+/', ' ', $style ); break; } } $css .= sprintf( '/* =%1$s= Ends */', $block_style_key ); } } return trim( $css ); } /** * Helper function to get string between 2 string * @since 3.3.0 */ public static function get_between_data( $string, $start, $end ) { $pos_string = stripos( $string, $start ); $substr_data = substr( $string, $pos_string ); $string_two = substr( $substr_data, strlen( $start ) ); $second_pos = stripos( $string_two, $end ); $string_three = substr( $string_two, 0, $second_pos ); // remove whitespaces from result $result_unit = trim( $string_three ); // return result_unit return $result_unit; } /** * Is Gutenberg Editor */ public static function eb_stylehandler_is_gutenberg_editor( $pagenow, $param ) { if ( $pagenow == 'post-new.php' || $pagenow == 'post.php' || $pagenow == 'site-editor.php' ) { return true; } if ( $pagenow == 'themes.php' && ! empty( $param ) && str_contains( $param, 'gutenberg-edit-site' ) ) { return true; } return false; } } EbStyleHandlerParseCss::init(); }